+ obd_id vals[2];
+ unsigned long flags;
+ __u32 vallen, group;
+ int old_count, count, index, i;
+ int rc;
+ char name[32] = "CATLIST";
+
+ lock_kernel();
+
+ ptlrpc_daemonize();
+
+ SIGNAL_MASK_LOCK(current, flags);
+ sigfillset(¤t->blocked);
+ RECALC_SIGPENDING;
+ SIGNAL_MASK_UNLOCK(current, flags);
+
+ unlock_kernel();
+
+ obd = mlsi->mlsi_obd;
+ watched = mlsi->mlsi_watched;
+ index = mlsi->mlsi_index;
+
+ LASSERT(obd != NULL);
+ LASSERT(watched != NULL);
+
+ OBD_FREE(mlsi, sizeof(*mlsi));
+
+ mds = &obd->u.mds;
+ down(&mds->mds_orphan_recovery_sem);
+
+ uuid = &watched->u.cli.cl_import->imp_target_uuid;
+ CWARN("MDS %s: %s now active, repairing the connection\n",
+ obd->obd_name, uuid->uuid);
+
+ group = FILTER_GROUP_FIRST_MDS + mds->mds_num;
+ rc = obd_set_info(watched->obd_self_export, strlen("mds_conn"),
+ "mds_conn", sizeof(group), &group);
+ if (rc)
+ GOTO(cleanup, rc);
+
+ old_count = mds->mds_dt_desc.ld_tgt_count;
+
+ rc = mds_dt_update_desc(obd, mds->mds_dt_exp);
+ if (rc)
+ GOTO(cleanup, rc);
+
+ count = mds->mds_dt_desc.ld_tgt_count;
+ LASSERT(count >= old_count);
+
+ vallen = sizeof(vals[1]);
+ rc = obd_get_info(watched->obd_self_export, strlen("last_id"),
+ "last_id", &vallen, &vals[1]);
+ if (rc)
+ GOTO(cleanup, rc);
+
+ for (i = 0; i < 2; i++) {
+ if (!mds->mds_capa_keys[i].k_key)
+ break;
+ rc = obd_set_info(mds->mds_dt_exp, strlen("capa_key"),
+ "capa_key", sizeof(struct lustre_capa_key),
+ mds->mds_capa_keys[i].k_key);
+ if (rc)
+ GOTO(cleanup, rc);
+ }
+
+ /* we don't set next id manually, instead OSCs will set them
+ * during own recovery from DELORPHAN reply -bzzz */
+#if 0
+ vals[0] = index;
+ rc = mds_dt_set_info(obd->obd_self_export, strlen("next_id"),
+ "next_id", 2, vals);
+ if (rc)
+ GOTO(cleanup, rc);
+#endif
+
+ obd_llog_finish(obd, &obd->obd_llogs, old_count);
+ obd_llog_cat_initialize(obd, &obd->obd_llogs, count, name);
+
+ ctxt = llog_get_context(&obd->obd_llogs, LLOG_UNLINK_ORIG_CTXT);
+ LASSERT(ctxt != NULL);
+
+ rc = llog_connect(ctxt, count, NULL, NULL, uuid);
+ if (rc != 0) {
+ CERROR("%s: failed at llog_origin_connect: %d\n",
+ obd->obd_name, rc);
+ GOTO(cleanup, rc);
+ }
+
+ CWARN("MDS %s: %s now active, resetting orphans\n",
+ obd->obd_name, uuid->uuid);
+
+ rc = mds_dt_clear_orphans(&obd->u.mds, uuid);
+ if (rc != 0) {
+ CERROR("%s: failed at mds_dt_clear_orphans(): %d\n",
+ obd->obd_name, rc);
+ GOTO(cleanup, rc);
+ }
+ rc = 0;
+
+ EXIT;
+cleanup:
+ up(&mds->mds_orphan_recovery_sem);
+ return rc;
+}
+
+int mds_dt_start_synchronize(struct obd_device *obd,
+ struct obd_device *watched,
+ void *data)
+{
+ struct mds_dt_sync_info *mlsi;
+ int rc;
+
+ ENTRY;
+
+ OBD_ALLOC(mlsi, sizeof(*mlsi));
+ if (mlsi == NULL)
+ RETURN(-ENOMEM);
+
+ mlsi->mlsi_obd = obd;
+ mlsi->mlsi_watched = watched;
+ mlsi->mlsi_index = (int)data;
+
+ rc = kernel_thread(mds_dt_synchronize, mlsi, CLONE_VM | CLONE_FILES);
+ if (rc < 0)
+ CERROR("%s: error starting mds_dt_synchronize(): %d\n",
+ obd->obd_name, rc);
+ else {
+ CDEBUG(D_HA, "%s: mds_dt_synchronize() thread: %d\n",
+ obd->obd_name, rc);
+ rc = 0;
+ }
+
+ RETURN(rc);
+}
+
+int mds_notify(struct obd_device *obd, struct obd_device *watched,
+ int active, void *data)
+{