+/* Error codes:
+ *
+ * -EINVAL : UUID can't be found in the LMV's target list
+ * -ENOTCONN: The UUID is found, but the target connection is bad (!)
+ * -EBADF : The UUID is found, but the OBD of the wrong type (!)
+ */
+static int lmv_set_mdc_active(struct lmv_obd *lmv, struct obd_uuid *uuid,
+ int activate)
+{
+ struct obd_device *obd;
+ struct lmv_tgt_desc *tgt;
+ int i, rc = 0;
+ ENTRY;
+
+ CDEBUG(D_INFO, "Searching in lmv %p for uuid %s (activate=%d)\n",
+ lmv, uuid->uuid, activate);
+
+ spin_lock(&lmv->lmv_lock);
+ for (i = 0, tgt = lmv->tgts; i < lmv->desc.ld_tgt_count; i++, tgt++) {
+ if (tgt->ltd_exp == NULL)
+ continue;
+
+ CDEBUG(D_INFO, "lmv idx %d is %s conn "LPX64"\n",
+ i, tgt->uuid.uuid, tgt->ltd_exp->exp_handle.h_cookie);
+ if (strncmp(uuid->uuid, tgt->uuid.uuid, sizeof uuid->uuid) == 0)
+ break;
+ }
+
+ if (i == lmv->desc.ld_tgt_count)
+ GOTO(out, rc = -EINVAL);
+
+ obd = class_exp2obd(tgt->ltd_exp);
+ if (obd == NULL)
+ GOTO(out, rc = -ENOTCONN);
+
+ CDEBUG(D_INFO, "Found OBD %s=%s device %d (%p) type %s at LMV idx %d\n",
+ obd->obd_name, obd->obd_uuid.uuid, obd->obd_minor, obd,
+ obd->obd_type->typ_name, i);
+ LASSERT(strcmp(obd->obd_type->typ_name, LUSTRE_MDC_NAME) == 0);
+
+ if (tgt->active == activate) {
+ CDEBUG(D_INFO, "OBD %p already %sactive!\n", obd,
+ activate ? "" : "in");
+ GOTO(out, rc);
+ }
+
+ CDEBUG(D_INFO, "Marking OBD %p %sactive\n", obd, activate ? "" : "in");
+
+ tgt->active = activate;
+ if (activate)
+ lmv->desc.ld_active_tgt_count++;
+ else
+ lmv->desc.ld_active_tgt_count--;
+
+ EXIT;
+ out:
+ spin_unlock(&lmv->lmv_lock);
+ return rc;
+}
+
+static int lmv_notify(struct obd_device *obd, struct obd_device *watched,
+ int active)
+{
+ int rc;
+ struct obd_uuid *uuid;
+
+ if (strcmp(watched->obd_type->typ_name, LUSTRE_MDC_NAME)) {
+ CERROR("unexpected notification of %s %s!\n",
+ watched->obd_type->typ_name,
+ watched->obd_name);
+ return -EINVAL;
+ }
+ uuid = &watched->u.cli.cl_import->imp_target_uuid;
+
+ /* Set MDC as active before notifying the observer, so the
+ * observer can use the MDC normally.
+ */
+ rc = lmv_set_mdc_active(&obd->u.lmv, uuid, active);
+ if (rc) {
+ CERROR("%sactivation of %s failed: %d\n",
+ active ? "" : "de", uuid->uuid, rc);
+ RETURN(rc);
+ }
+
+ if (obd->obd_observer)
+ /* Pass the notification up the chain. */
+ rc = obd_notify(obd->obd_observer, watched, active);
+
+ RETURN(rc);
+}
+