+ LASSERT(mdc != NULL);
+ if (ld->ld_md_tgts_nr == LOV_MDC_TGT_MAX) {
+ /* If the maximum value of LOV_MDC_TGT_MAX will become too
+ * small then all MD target handling must be rewritten in LOD
+ * manner, check lod_add_device() and related functionality.
+ */
+ CERROR("%s: cannot serve more than %d MDC devices\n",
+ lov_obd->obd_name, LOV_MDC_TGT_MAX);
+ RETURN(-ERANGE);
+ }
+
+ /* grab FLD from lmv, do that here, when first MDC is added
+ * to be sure LMV is set up and can be found */
+ if (ld->ld_lmv == NULL) {
+ next = 0;
+ while ((lmv_obd = class_devices_in_group(&lov_obd->obd_uuid,
+ &next)) != NULL) {
+ if ((strncmp(lmv_obd->obd_type->typ_name,
+ LUSTRE_LMV_NAME,
+ strlen(LUSTRE_LMV_NAME)) == 0))
+ break;
+ }
+ if (lmv_obd == NULL) {
+ CERROR("%s: cannot find LMV OBD by UUID (%s)\n",
+ lov_obd->obd_name,
+ obd_uuid2str(&lmv_obd->obd_uuid));
+ RETURN(-ENODEV);
+ }
+ spin_lock(&lmv_obd->obd_dev_lock);
+ class_incref(lmv_obd, "lov", ld);
+ spin_unlock(&lmv_obd->obd_dev_lock);
+ ld->ld_lmv = lmv_obd;
+ }
+
+ LASSERT(lov_obd->u.lov.lov_mdc_tgts[ld->ld_md_tgts_nr].lmtd_mdc ==
+ NULL);
+
+ if (ld->ld_flags & LOV_DEV_INITIALIZED) {
+ rc = lov_mdc_dev_init(env, ld, mdc->obd_lu_dev, idx,
+ ld->ld_md_tgts_nr);
+ if (rc) {
+ CERROR("%s: failed to add MDC %s as target: rc = %d\n",
+ lov_obd->obd_name, obd_uuid2str(&mdc->obd_uuid),
+ rc);
+ RETURN(rc);
+ }
+ }
+
+ lov_obd->u.lov.lov_mdc_tgts[ld->ld_md_tgts_nr].lmtd_mdc = mdc;
+ lov_obd->u.lov.lov_mdc_tgts[ld->ld_md_tgts_nr].lmtd_index = idx;
+ ld->ld_md_tgts_nr++;
+
+ RETURN(rc);
+}
+
+static int lov_process_config(const struct lu_env *env,
+ struct lu_device *d, struct lustre_cfg *cfg)
+{
+ struct obd_device *obd = d->ld_obd;
+ int cmd;
+ int rc;
+ int gen;
+ __u32 index;
+
+ obd_getref(obd);
+
+ cmd = cfg->lcfg_command;
+
+ rc = lov_process_config_base(d->ld_obd, cfg, &index, &gen);
+ if (rc < 0)
+ GOTO(out, rc);
+
+ switch (cmd) {
+ case LCFG_LOV_ADD_OBD:
+ case LCFG_LOV_ADD_INA:
+ rc = lov_cl_add_target(env, d, index);
+ if (rc != 0)
+ lov_del_target(d->ld_obd, index, NULL, 0);
+ break;
+ case LCFG_LOV_DEL_OBD:
+ lov_cl_del_target(env, d, index);
+ break;
+ case LCFG_ADD_MDC:
+ {
+ struct obd_device *mdc;
+ struct obd_uuid tgt_uuid;
+
+ /* modify_mdc_tgts add 0:lustre-clilmv 1:lustre-MDT0000_UUID
+ * 2:0 3:1 4:lustre-MDT0000-mdc_UUID */
+ if (LUSTRE_CFG_BUFLEN(cfg, 1) > sizeof(tgt_uuid.uuid))
+ GOTO(out, rc = -EINVAL);
+
+ obd_str2uuid(&tgt_uuid, lustre_cfg_buf(cfg, 1));
+
+ if (sscanf(lustre_cfg_buf(cfg, 2), "%d", &index) != 1)
+ GOTO(out, rc = -EINVAL);
+
+ mdc = class_find_client_obd(&tgt_uuid, LUSTRE_MDC_NAME,
+ &obd->obd_uuid);
+ if (mdc == NULL)
+ GOTO(out, rc = -ENODEV);
+ rc = lov_add_mdc_target(env, d, mdc, index);
+ break;
+ }
+ }
+out:
+ obd_putref(obd);
+ RETURN(rc);