+ struct lod_object *lod_obj;
+ struct lu_object *lu_obj;
+ const struct lu_fid *fid = &hdr->loh_fid;
+ mdsno_t mds;
+ int rc = 0;
+ ENTRY;
+
+ OBD_SLAB_ALLOC_PTR_GFP(lod_obj, lod_object_kmem, CFS_ALLOC_IO);
+ if (lod_obj == NULL)
+ RETURN(ERR_PTR(-ENOMEM));
+
+ rc = lod_fld_lookup(env, lu2lod_dev(dev), fid, &mds, LU_SEQ_RANGE_MDT);
+ if (rc) {
+ OBD_SLAB_FREE_PTR(lod_obj, lod_object_kmem);
+ RETURN(ERR_PTR(rc));
+ }
+
+ lod_obj->ldo_mds_num = mds;
+ lu_obj = lod2lu_obj(lod_obj);
+ dt_object_init(&lod_obj->ldo_obj, NULL, dev);
+ lod_obj->ldo_obj.do_ops = &lod_obj_ops;
+ if (likely(mds == lu_site2seq(dev->ld_site)->ss_node_id))
+ lu_obj->lo_ops = &lod_lu_obj_ops;
+ else
+ lu_obj->lo_ops = &lod_lu_robj_ops;
+ RETURN(lu_obj);
+}
+
+static int lod_cleanup_desc_tgts(const struct lu_env *env,
+ struct lod_device *lod,
+ struct lod_tgt_descs *ltd,
+ struct lustre_cfg *lcfg)
+{
+ struct lu_device *next;
+ int rc = 0;
+ int i;
+
+ lod_getref(ltd);
+ if (ltd->ltd_tgts_size <= 0) {
+ lod_putref(lod, ltd);
+ return 0;
+ }
+ cfs_foreach_bit(ltd->ltd_tgt_bitmap, i) {
+ struct lod_tgt_desc *tgt;
+ int rc1;
+
+ tgt = LTD_TGT(ltd, i);
+ LASSERT(tgt && tgt->ltd_tgt);
+ next = &tgt->ltd_tgt->dd_lu_dev;
+ rc1 = next->ld_ops->ldo_process_config(env, next, lcfg);
+ if (rc1) {
+ CERROR("%s: error cleaning up LOD index %u: cmd %#x"
+ ": rc = %d\n", lod2obd(lod)->obd_name, i,
+ lcfg->lcfg_command, rc1);
+ rc = rc1;
+ }
+ }
+ lod_putref(lod, ltd);
+ return rc;
+}
+
+static int lodname2mdt_index(char *lodname, int *index)
+{
+ char *ptr, *tmp;
+
+ /* The lodname suppose to be fsname-MDTxxxx-mdtlov */
+ ptr = strrchr(lodname, '-');
+ if (ptr == NULL) {
+ CERROR("invalid MDT index in '%s'\n", lodname);
+ return -EINVAL;
+ }
+
+ if (strncmp(ptr, "-mdtlov", 7) != 0) {
+ CERROR("invalid MDT index in '%s'\n", lodname);
+ return -EINVAL;
+ }
+
+ if ((unsigned long)ptr - (unsigned long)lodname <= 8) {
+ CERROR("invalid MDT index in '%s'\n", lodname);
+ return -EINVAL;
+ }
+
+ if (strncmp(ptr - 8, "-MDT", 4) != 0) {
+ CERROR("invalid MDT index in '%s'\n", lodname);
+ return -EINVAL;
+ }
+
+ *index = simple_strtol(ptr - 4, &tmp, 16);
+ if (*tmp != '-' || *index > INT_MAX || *index < 0) {
+ CERROR("invalid MDT index in '%s'\n", lodname);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+/*
+ * Init client sequence manager which is used by local MDS to talk to sequence
+ * controller on remote node.
+ */
+static int lod_seq_init_cli(const struct lu_env *env,
+ struct lod_device *lod,
+ char *tgtuuid, int index)
+{
+ struct seq_server_site *ss;
+ struct obd_device *osp;
+ int rc;
+ char *prefix;
+ struct obd_uuid obd_uuid;
+ ENTRY;
+
+ ss = lu_site2seq(lod2lu_dev(lod)->ld_site);
+ LASSERT(ss != NULL);
+
+ /* check if this is adding the first MDC and controller is not yet
+ * initialized. */
+ if (index != 0 || ss->ss_client_seq)
+ RETURN(0);
+
+ obd_str2uuid(&obd_uuid, tgtuuid);
+ osp = class_find_client_obd(&obd_uuid, LUSTRE_OSP_NAME,
+ &lod->lod_dt_dev.dd_lu_dev.ld_obd->obd_uuid);
+ if (osp == NULL) {
+ CERROR("%s: can't find %s device\n",
+ lod->lod_dt_dev.dd_lu_dev.ld_obd->obd_name,
+ tgtuuid);
+ RETURN(-EINVAL);
+ }
+
+ if (!osp->obd_set_up) {
+ CERROR("target %s not set up\n", osp->obd_name);
+ rc = -EINVAL;
+ }
+
+ LASSERT(ss->ss_control_exp);
+ OBD_ALLOC_PTR(ss->ss_client_seq);
+ if (ss->ss_client_seq == NULL)
+ RETURN(-ENOMEM);
+
+ OBD_ALLOC(prefix, MAX_OBD_NAME + 5);
+ if (!prefix) {
+ OBD_FREE_PTR(ss->ss_client_seq);
+ ss->ss_client_seq = NULL;
+ RETURN(-ENOMEM);
+ }
+
+ snprintf(prefix, MAX_OBD_NAME + 5, "ctl-%s", osp->obd_name);
+ rc = seq_client_init(ss->ss_client_seq, ss->ss_control_exp,
+ LUSTRE_SEQ_METADATA, prefix, NULL);
+ OBD_FREE(prefix, MAX_OBD_NAME + 5);
+ if (rc) {
+ OBD_FREE_PTR(ss->ss_client_seq);
+ ss->ss_client_seq = NULL;
+ RETURN(rc);
+ }
+
+ LASSERT(ss->ss_server_seq != NULL);
+ rc = seq_server_set_cli(ss->ss_server_seq, ss->ss_client_seq,
+ env);
+
+ RETURN(rc);
+}