context before init.
Branch HEAD
b=18800
i=rread
i=wangdi
* File join has been disabled in this release, refer to Bugzilla 16929.
Severity : normal
+Frequency : rare
+Bugzilla : 18800
+Description: access to llog context before init.
+Details : move handling CATALOGS file at osc layer and forbid access to llog
+ context before init.
+
+Severity : normal
Bugzilla : 19529
Description: Avoid deadlock for local client writes
Details : Use new OBD_BRW_MEMALLOC flag to notify OST about writes in the
struct llog_rec_hdr *rec, struct lov_stripe_md *lsm,
struct llog_cookie *logcookies, int numcookies);
-int llog_cat_initialize(struct obd_device *obd, struct obd_llog_group *olg,
- int idx, struct obd_uuid *uuid);
int obd_llog_init(struct obd_device *obd, struct obd_llog_group *olg,
- struct obd_device *disk_obd, int count,
- struct llog_catid *logid, struct obd_uuid *uuid);
+ struct obd_device *disk_obd, int *idx);
int obd_llog_finish(struct obd_device *obd, int count);
/* llog_lvfs.c */
extern struct llog_operations llog_lvfs_ops;
-int llog_get_cat_list(struct obd_device *obd, struct obd_device *disk_obd,
+int llog_get_cat_list(struct obd_device *disk_obd,
char *name, int idx, int count,
struct llog_catid *idarray);
-int llog_put_cat_list(struct obd_device *obd, struct obd_device *disk_obd,
+int llog_put_cat_list(struct obd_device *disk_obd,
char *name, int idx, int count, struct llog_catid *idarray);
+#define LLOG_CTXT_FLAG_UNINITIALIZED 0x00000001
+
struct llog_ctxt {
int loc_idx; /* my index the obd array of ctxt's */
struct llog_gen loc_gen;
struct semaphore loc_sem; /* protects loc_llcd and loc_imp */
atomic_t loc_refcount;
void *llog_proc_cb;
+ long loc_flags; /* flags, see above defines */
};
#define LCM_NAME_SIZE 64
/* llog related obd_methods */
int (*o_llog_init)(struct obd_device *obd, struct obd_llog_group *grp,
- struct obd_device *disk_obd, int count,
- struct llog_catid *logid, struct obd_uuid *uuid);
+ struct obd_device *disk_obd, int *idx);
int (*o_llog_finish)(struct obd_device *obd, int count);
int (*o_llog_connect)(struct obd_export *, struct llogd_conn_body *);
RETURN(-EINVAL);
}
- rc = obd_llog_init(obd, &obd->obd_olg, mdc_obd, 0, NULL, tgt_uuid);
+ rc = obd_llog_init(obd, &obd->obd_olg, mdc_obd, NULL);
if (rc) {
lmv_init_unlock(lmv);
CERROR("lmv failed to setup llogging subsystems\n");
struct obd_uuid *uuidp, int gen);
/* lov_log.c */
int lov_llog_init(struct obd_device *obd, struct obd_llog_group *olg,
- struct obd_device *tgt, int count, struct llog_catid *logid,
- struct obd_uuid *uuid);
+ struct obd_device *tgt, int *idx);
int lov_llog_finish(struct obd_device *obd, int count);
/* lov_pack.c */
};
int lov_llog_init(struct obd_device *obd, struct obd_llog_group *olg,
- struct obd_device *tgt, int count, struct llog_catid *logid,
- struct obd_uuid *uuid)
+ struct obd_device *disk_obd, int *index)
{
struct lov_obd *lov = &obd->u.lov;
struct obd_device *child;
int i, rc = 0;
ENTRY;
- /* allow init only one target at one time */
- LASSERT(uuid);
-
LASSERT(olg == &obd->obd_olg);
- rc = llog_setup(obd, olg, LLOG_MDS_OST_ORIG_CTXT, tgt, 0, NULL,
+ rc = llog_setup(obd, olg, LLOG_MDS_OST_ORIG_CTXT, disk_obd, 0, NULL,
&lov_mds_ost_orig_logops);
if (rc)
RETURN(rc);
- rc = llog_setup(obd, olg, LLOG_SIZE_REPL_CTXT, tgt, 0, NULL,
+ rc = llog_setup(obd, olg, LLOG_SIZE_REPL_CTXT, disk_obd, 0, NULL,
&lov_size_repl_logops);
if (rc)
GOTO(err_cleanup, rc);
obd_getref(obd);
/* count may not match lov->desc.ld_tgt_count during dynamic ost add */
for (i = 0; i < lov->desc.ld_tgt_count; i++) {
- if (!lov->lov_tgts[i] || !lov->lov_tgts[i]->ltd_active)
+ if (!lov->lov_tgts[i])
continue;
- if (!obd_uuid_equals(uuid, &lov->lov_tgts[i]->ltd_uuid))
+
+ if (index && i != *index)
continue;
- LASSERT(lov->lov_tgts[i]->ltd_exp);
- child = lov->lov_tgts[i]->ltd_exp->exp_obd;
- rc = obd_llog_init(child, &child->obd_olg, tgt, 1, logid, uuid);
+ child = lov->lov_tgts[i]->ltd_obd;
+ rc = obd_llog_init(child, &child->obd_olg, disk_obd, &i);
if (rc)
CERROR("error osc_llog_init idx %d osc '%s' tgt '%s' "
- "(rc=%d)\n", i, child->obd_name, tgt->obd_name,
- rc);
- break;
+ "(rc=%d)\n", i, child->obd_name,
+ disk_obd->obd_name, rc);
+ rc = 0;
}
obd_putref(obd);
GOTO(err_cleanup, rc);
sptlrpc_lprocfs_cliobd_attach(obd);
ptlrpc_lprocfs_register_obd(obd);
- rc = obd_llog_init(obd, &obd->obd_olg, obd, 0, NULL, NULL);
+ rc = obd_llog_init(obd, &obd->obd_olg, obd, NULL);
if (rc) {
mdc_cleanup(obd);
CERROR("failed to setup llogging subsystems\n");
static int mdc_llog_init(struct obd_device *obd, struct obd_llog_group *olg,
- struct obd_device *tgt, int count,
- struct llog_catid *logid, struct obd_uuid *uuid)
+ struct obd_device *tgt, int *index)
{
struct llog_ctxt *ctxt;
int rc;
&llog_client_ops);
if (rc)
RETURN(rc);
+
ctxt = llog_get_context(obd, LLOG_LOVEA_REPL_CTXT);
llog_initiator_connect(ctxt);
llog_ctxt_put(ctxt);
/* mds/mds_log.c */
int mds_llog_init(struct obd_device *obd, struct obd_llog_group *olg,
- struct obd_device *tgt, int count,
- struct llog_catid *logid, struct obd_uuid *uuid);
+ struct obd_device *tgt, int *index);
int mds_llog_finish(struct obd_device *obd, int count);
int mds_changelog_llog_init(struct obd_device *obd, struct obd_device *tgt);
EXPORT_SYMBOL(mds_changelog_llog_init);
int mds_llog_init(struct obd_device *obd, struct obd_llog_group *olg,
- struct obd_device *tgt, int count, struct llog_catid *logid,
- struct obd_uuid *uuid)
+ struct obd_device *disk_obd, int *index)
{
struct obd_device *lov_obd = obd->u.mds.mds_osc_obd;
struct llog_ctxt *ctxt;
ENTRY;
LASSERT(olg == &obd->obd_olg);
- rc = llog_setup(obd, &obd->obd_olg, LLOG_MDS_OST_ORIG_CTXT, tgt,
+ rc = llog_setup(obd, &obd->obd_olg, LLOG_MDS_OST_ORIG_CTXT, disk_obd,
0, NULL, &mds_ost_orig_logops);
if (rc)
RETURN(rc);
- rc = llog_setup(obd, &obd->obd_olg, LLOG_SIZE_REPL_CTXT, tgt,
+ rc = llog_setup(obd, &obd->obd_olg, LLOG_SIZE_REPL_CTXT, disk_obd,
0, NULL, &mds_size_repl_logops);
if (rc)
GOTO(err_llog, rc);
- rc = obd_llog_init(lov_obd, &lov_obd->obd_olg, tgt, count, logid, uuid);
+ rc = obd_llog_init(lov_obd, &lov_obd->obd_olg, disk_obd, index);
if (rc) {
CERROR("lov_llog_init err %d\n", rc);
GOTO(err_cleanup, rc);
/* If we added a target we have to reconnect the llogs */
/* We only _need_ to do this at first add (idx), or the first time
after recovery. However, it should now be safe to call anytime. */
- rc = llog_cat_initialize(obd, &obd->obd_olg, idx, uuid);
+ rc = obd_llog_init(obd, &obd->obd_olg, obd, &idx);
if (rc)
GOTO(out, rc);
GOTO(err_exit, rc);
}
+ /* try init too early */
+ rc = obd_llog_init(obd, &obd->obd_olg, obd, NULL);
+ if (rc)
+ GOTO(err_exit, rc);
+
mds->mds_osc_obd->u.lov.lov_sp_me = LUSTRE_SP_MDT;
OBD_ALLOC(data, sizeof(*data));
if (data == NULL)
- RETURN(-ENOMEM);
+ GOTO(err_exit, rc = -ENOMEM);
+
data->ocd_connect_flags = OBD_CONNECT_VERSION | OBD_CONNECT_INDEX |
OBD_CONNECT_REQPORTAL | OBD_CONNECT_QUOTA64 |
OBD_CONNECT_OSS_CAPA | OBD_CONNECT_FID |
/* liblustre only support null flavor to MGS */
obd->u.cli.cl_flvr_mgc.sf_rpc = SPTLRPC_FLVR_NULL;
- rc = obd_llog_init(obd, &obd->obd_olg, obd, 0, NULL, NULL);
+ rc = obd_llog_init(obd, &obd->obd_olg, obd, NULL);
if (rc) {
CERROR("failed to setup llogging subsystems\n");
GOTO(err_cleanup, rc);
}
static int mgc_llog_init(struct obd_device *obd, struct obd_llog_group *olg,
- struct obd_device *tgt, int count,
- struct llog_catid *logid, struct obd_uuid *uuid)
+ struct obd_device *tgt, int *index)
{
struct llog_ctxt *ctxt;
int rc;
if (rc)
GOTO(err_decref, rc);
- rc = obd_llog_init(obd, &obd->obd_olg, obd, 0, NULL, NULL);
+ rc = obd_llog_init(obd, &obd->obd_olg, obd, NULL);
if (rc) {
CERROR("failed to setup llogging subsystems\n");
GOTO(err_cleanup, rc);
}
static int mgc_llog_init(struct obd_device *obd, struct obd_llog_group *olg,
- struct obd_device *tgt, int count,
- struct llog_catid *logid, struct obd_uuid *uuid)
+ struct obd_device *tgt, int *index)
{
struct llog_ctxt *ctxt;
int rc;
static int mgs_handle(struct ptlrpc_request *req);
static int mgs_llog_init(struct obd_device *obd, struct obd_llog_group *olg,
- struct obd_device *tgt, int count,
- struct llog_catid *logid, struct obd_uuid *uuid)
+ struct obd_device *tgt, int *index)
{
int rc;
ENTRY;
GOTO(err_ns, rc);
}
- rc = obd_llog_init(obd, &obd->obd_olg, obd, 0, NULL, NULL);
+ rc = obd_llog_init(obd, &obd->obd_olg, obd, NULL);
if (rc)
GOTO(err_fs, rc);
struct completion lpi_completion;
};
-int llog_put_cat_list(struct obd_device *obd, struct obd_device *disk_obd,
- char *name, int idx, int count,
- struct llog_catid *idarray);
-
int llog_cat_id2handle(struct llog_handle *cathandle, struct llog_handle **res,
struct llog_logid *logid);
int class_config_dump_handler(struct llog_handle * handle,
RETURN(-ENOMEM);
mutex_down(&obd->obd_olg.olg_cat_processing);
- rc = llog_get_cat_list(obd, obd, name, 0, count, idarray);
+ rc = llog_get_cat_list(obd, name, 0, count, idarray);
if (rc)
GOTO(out, rc);
}
/* reads the catalog list */
-int llog_get_cat_list(struct obd_device *obd, struct obd_device *disk_obd,
+int llog_get_cat_list(struct obd_device *disk_obd,
char *name, int idx, int count, struct llog_catid *idarray)
{
struct lvfs_run_ctxt saved;
if (!count)
RETURN(0);
- push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
+ push_ctxt(&saved, &disk_obd->obd_lvfs_ctxt, NULL);
file = filp_open(name, O_RDWR | O_CREAT | O_LARGEFILE, 0700);
if (!file || IS_ERR(file)) {
rc = PTR_ERR(file);
EXIT;
out:
- pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
+ pop_ctxt(&saved, &disk_obd->obd_lvfs_ctxt, NULL);
if (file && !IS_ERR(file))
rc1 = filp_close(file, 0);
if (rc == 0)
EXPORT_SYMBOL(llog_get_cat_list);
/* writes the cat list */
-int llog_put_cat_list(struct obd_device *obd, struct obd_device *disk_obd,
+int llog_put_cat_list(struct obd_device *disk_obd,
char *name, int idx, int count, struct llog_catid *idarray)
{
struct lvfs_run_ctxt saved;
if (!count)
GOTO(out1, rc = 0);
- push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
+ push_ctxt(&saved, &disk_obd->obd_lvfs_ctxt, NULL);
file = filp_open(name, O_RDWR | O_CREAT | O_LARGEFILE, 0700);
if (!file || IS_ERR(file)) {
rc = PTR_ERR(file);
}
out:
- pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
+ pop_ctxt(&saved, &disk_obd->obd_lvfs_ctxt, NULL);
if (file && !IS_ERR(file))
rc1 = filp_close(file, 0);
return 0;
}
-int llog_get_cat_list(struct obd_device *obd, struct obd_device *disk_obd,
+int llog_get_cat_list(struct obd_device *disk_obd,
char *name, int idx, int count, struct llog_catid *idarray)
{
LBUG();
return 0;
}
-int llog_put_cat_list(struct obd_device *obd, struct obd_device *disk_obd,
+int llog_put_cat_list(struct obd_device *disk_obd,
char *name, int idx, int count, struct llog_catid *idarray)
{
LBUG();
ctxt->loc_logops = op;
sema_init(&ctxt->loc_sem, 1);
ctxt->loc_exp = class_export_get(disk_obd->obd_self_export);
+ ctxt->loc_flags = LLOG_CTXT_FLAG_UNINITIALIZED;
rc = llog_group_set_ctxt(olg, ctxt, index);
if (rc) {
if (rc == -EEXIST) {
ctxt = llog_group_get_ctxt(olg, index);
if (ctxt) {
- /*
+ /*
* mds_lov_update_desc() might call here multiple
* times. So if the llog is already set up then
* don't to do it again.
CERROR("obd %s ctxt %d lop_setup=%p failed %d\n",
obd->obd_name, index, op->lop_setup, rc);
llog_ctxt_put(ctxt);
+ } else {
+ CDEBUG(D_CONFIG, "obd %s ctxt %d is initialized\n",
+ obd->obd_name, index);
+ ctxt->loc_flags &= ~LLOG_CTXT_FLAG_UNINITIALIZED;
}
RETURN(rc);
RETURN(-ENODEV);
}
+ if (ctxt->loc_flags & LLOG_CTXT_FLAG_UNINITIALIZED)
+ RETURN(-ENXIO);
+
+
CTXT_CHECK_OP(ctxt, add, -EOPNOTSUPP);
raised = cfs_cap_raised(CFS_CAP_SYS_RESOURCE);
if (!raised)
}
EXPORT_SYMBOL(llog_obd_origin_add);
-int llog_cat_initialize(struct obd_device *obd, struct obd_llog_group *olg,
- int idx, struct obd_uuid *uuid)
-{
- char name[32] = CATLIST;
- struct llog_catid idarray;
- int rc;
- ENTRY;
-
- mutex_down(&olg->olg_cat_processing);
- rc = llog_get_cat_list(obd, obd, name, idx, 1, &idarray);
- if (rc) {
- CERROR("rc: %d\n", rc);
- GOTO(out, rc);
- }
-
- CDEBUG(D_INFO, "%s: Init llog for %s/%d - catid "LPX64"/"LPX64":%x\n",
- obd->obd_name, uuid->uuid, idx, idarray.lci_logid.lgl_oid,
- idarray.lci_logid.lgl_ogr, idarray.lci_logid.lgl_ogen);
-
- rc = obd_llog_init(obd, olg, obd, 1, &idarray, uuid);
- if (rc) {
- CERROR("rc: %d\n", rc);
- GOTO(out, rc);
- }
-
- rc = llog_put_cat_list(obd, obd, name, idx, 1, &idarray);
- if (rc) {
- CERROR("rc: %d\n", rc);
- GOTO(out, rc);
- }
-
- out:
- mutex_up(&olg->olg_cat_processing);
-
- RETURN(rc);
-}
-EXPORT_SYMBOL(llog_cat_initialize);
-
int obd_llog_init(struct obd_device *obd, struct obd_llog_group *olg,
- struct obd_device *disk_obd, int count,
- struct llog_catid *logid, struct obd_uuid *uuid)
+ struct obd_device *disk_obd, int *index)
{
int rc;
ENTRY;
OBD_CHECK_DT_OP(obd, llog_init, 0);
OBD_COUNTER_INCREMENT(obd, llog_init);
- rc = OBP(obd, llog_init)(obd, olg, disk_obd, count, logid, uuid);
+ rc = OBP(obd, llog_init)(obd, olg, disk_obd, index);
RETURN(rc);
}
EXPORT_SYMBOL(obd_llog_init);
static int llog_test_llog_init(struct obd_device *obd,
struct obd_llog_group *olg,
- struct obd_device *tgt, int count,
- struct llog_catid *logid, struct obd_uuid *uuid)
+ struct obd_device *tgt, int *index)
{
int rc;
ENTRY;
RETURN(-EINVAL);
}
+ /* disk obd */
tgt = class_name2obd(lustre_cfg_string(lcfg, 1));
if (!tgt || !tgt->obd_attached || !tgt->obd_set_up) {
CERROR("target device not attached or not set up (%s)\n",
RETURN(-EINVAL);
}
- rc = obd_llog_init(obd, NULL, tgt, 0, NULL, NULL);
+ rc = obd_llog_init(obd, NULL, tgt, NULL);
if (rc)
RETURN(rc);
ptlrpc_init_client(LDLM_CB_REQUEST_PORTAL, LDLM_CB_REPLY_PORTAL,
"filter_ldlm_cb_client", &obd->obd_ldlm_client);
- rc = obd_llog_init(obd, &obd->obd_olg, obd, 1, NULL, NULL);
+ rc = obd_llog_init(obd, &obd->obd_olg, obd, NULL);
if (rc) {
CERROR("failed to setup llogging subsystems\n");
GOTO(err_post, rc);
static int
filter_llog_init(struct obd_device *obd, struct obd_llog_group *olg,
- struct obd_device *tgt, int count, struct llog_catid *catid,
- struct obd_uuid *uuid)
+ struct obd_device *tgt, int *index)
{
struct filter_obd *filter = &obd->u.filter;
struct llog_ctxt *ctxt;
olg->olg_initializing = 1;
spin_unlock(&filter->fo_llog_list_lock);
- rc = llog_cat_initialize(obd, olg, 1, NULL);
+ rc = obd_llog_init(obd, olg, obd, NULL);
if (rc) {
spin_lock(&filter->fo_llog_list_lock);
list_del(&olg->olg_list);
struct obdo *oa = oinfo->oi_oa;
ENTRY;
- if ((oa->o_valid & OBD_MD_FLGROUP) && (oa->o_gr != 0)){
+ if ((oa->o_valid & OBD_MD_FLGROUP) &&
+ (oa->o_gr == FILTER_GROUP_ECHO || oa->o_gr == FILTER_GROUP_LLOG)){
rc = osc_real_create(exp, oinfo->oi_oa, ea, oti);
rc = oinfo->oi_cb_up(oinfo, rc);
RETURN(rc);
};
static struct llog_operations osc_mds_ost_orig_logops;
-static int osc_llog_init(struct obd_device *obd, struct obd_llog_group *olg,
- struct obd_device *tgt, int count,
- struct llog_catid *catid, struct obd_uuid *uuid)
+
+static int __osc_llog_init(struct obd_device *obd, struct obd_llog_group *olg,
+ struct obd_device *tgt, struct llog_catid *catid)
{
int rc;
ENTRY;
- LASSERT(olg == &obd->obd_olg);
- spin_lock(&obd->obd_dev_lock);
- if (osc_mds_ost_orig_logops.lop_setup != llog_obd_origin_setup) {
- osc_mds_ost_orig_logops = llog_lvfs_ops;
- osc_mds_ost_orig_logops.lop_setup = llog_obd_origin_setup;
- osc_mds_ost_orig_logops.lop_cleanup = llog_obd_origin_cleanup;
- osc_mds_ost_orig_logops.lop_add = llog_obd_origin_add;
- osc_mds_ost_orig_logops.lop_connect = llog_origin_connect;
- }
- spin_unlock(&obd->obd_dev_lock);
-
- rc = llog_setup(obd, &obd->obd_olg, LLOG_MDS_OST_ORIG_CTXT, tgt, count,
+ rc = llog_setup(obd, &obd->obd_olg, LLOG_MDS_OST_ORIG_CTXT, tgt, 1,
&catid->lci_logid, &osc_mds_ost_orig_logops);
if (rc) {
CERROR("failed LLOG_MDS_OST_ORIG_CTXT\n");
GOTO(out, rc);
}
- rc = llog_setup(obd, &obd->obd_olg, LLOG_SIZE_REPL_CTXT, tgt, count,
+ rc = llog_setup(obd, &obd->obd_olg, LLOG_SIZE_REPL_CTXT, tgt, 1,
NULL, &osc_size_repl_logops);
if (rc) {
struct llog_ctxt *ctxt =
GOTO(out, rc);
out:
if (rc) {
- CERROR("osc '%s' tgt '%s' cnt %d catid %p rc=%d\n",
- obd->obd_name, tgt->obd_name, count, catid, rc);
+ CERROR("osc '%s' tgt '%s' catid %p rc=%d\n",
+ obd->obd_name, tgt->obd_name, catid, rc);
CERROR("logid "LPX64":0x%x\n",
catid->lci_logid.lgl_oid, catid->lci_logid.lgl_ogen);
}
return rc;
}
+static int osc_llog_init(struct obd_device *obd, struct obd_llog_group *olg,
+ struct obd_device *disk_obd, int *index)
+{
+ struct llog_catid catid;
+ static char name[32] = CATLIST;
+ int rc;
+ ENTRY;
+
+ LASSERT(olg == &obd->obd_olg);
+
+ mutex_down(&olg->olg_cat_processing);
+ rc = llog_get_cat_list(disk_obd, name, *index, 1, &catid);
+ if (rc) {
+ CERROR("rc: %d\n", rc);
+ GOTO(out, rc);
+ }
+
+ CDEBUG(D_INFO, "%s: Init llog for %d - catid "LPX64"/"LPX64":%x\n",
+ obd->obd_name, *index, catid.lci_logid.lgl_oid,
+ catid.lci_logid.lgl_ogr, catid.lci_logid.lgl_ogen);
+
+ rc = __osc_llog_init(obd, olg, disk_obd, &catid);
+ if (rc) {
+ CERROR("rc: %d\n", rc);
+ GOTO(out, rc);
+ }
+
+ rc = llog_put_cat_list(disk_obd, name, *index, 1, &catid);
+ if (rc) {
+ CERROR("rc: %d\n", rc);
+ GOTO(out, rc);
+ }
+
+ out:
+ mutex_up(&olg->olg_cat_processing);
+
+ return rc;
+}
+
static int osc_llog_finish(struct obd_device *obd, int count)
{
struct llog_ctxt *ctxt;
spin_lock_init(&osc_ast_guard);
lockdep_set_class(&osc_ast_guard, &osc_ast_guard_class);
+ osc_mds_ost_orig_logops = llog_lvfs_ops;
+ osc_mds_ost_orig_logops.lop_setup = llog_obd_origin_setup;
+ osc_mds_ost_orig_logops.lop_cleanup = llog_obd_origin_cleanup;
+ osc_mds_ost_orig_logops.lop_add = llog_obd_origin_add;
+ osc_mds_ost_orig_logops.lop_connect = llog_origin_connect;
+
RETURN(rc);
}
GOTO(release_ctxt, rc = -ENOMEM);
mutex_down(&obd->obd_olg.olg_cat_processing);
- rc = llog_get_cat_list(obd, obd, name, 0, count, idarray);
+ rc = llog_get_cat_list(obd, name, 0, count, idarray);
if (rc)
GOTO(out_free, rc);