+
+}
+
+struct mds_lov_sync_info {
+ struct obd_device *mlsi_obd; /* the lov device to sync */
+ struct obd_uuid *mlsi_uuid; /* target to sync */
+};
+
+int mds_lov_synchronize(void *data)
+{
+ struct mds_lov_sync_info *mlsi = data;
+ struct obd_device *obd;
+ struct obd_uuid *uuid;
+ unsigned long flags;
+ int rc;
+
+ lock_kernel();
+ ptlrpc_daemonize();
+
+ SIGNAL_MASK_LOCK(current, flags);
+ sigfillset(¤t->blocked);
+ RECALC_SIGPENDING;
+ SIGNAL_MASK_UNLOCK(current, flags);
+
+ obd = mlsi->mlsi_obd;
+ uuid = mlsi->mlsi_uuid;
+
+ OBD_FREE(mlsi, sizeof(*mlsi));
+
+ LASSERT(obd != NULL);
+ LASSERT(uuid != NULL);
+
+ rc = obd_set_info(obd->u.mds.mds_osc_exp, strlen("mds_conn"),
+ "mds_conn", 0, uuid);
+ if (rc != 0)
+ RETURN(rc);
+
+ rc = llog_connect(llog_get_context(obd, LLOG_UNLINK_ORIG_CTXT),
+ obd->u.mds.mds_lov_desc.ld_tgt_count,
+ NULL, NULL, uuid);
+ if (rc != 0) {
+ CERROR("%s: failed at llog_origin_connect: %d\n",
+ obd->obd_name, rc);
+ RETURN(rc);
+ }
+
+ CWARN("MDS %s: %s now active, resetting orphans\n",
+ obd->obd_name, uuid->uuid);
+ rc = mds_lov_clearorphans(&obd->u.mds, uuid);
+ if (rc != 0) {
+ CERROR("%s: failed at mds_lov_clearorphans: %d\n",
+ obd->obd_name, rc);
+ RETURN(rc);
+ }
+
+ RETURN(0);
+}
+
+int mds_lov_start_synchronize(struct obd_device *obd, struct obd_uuid *uuid)
+{
+ struct mds_lov_sync_info *mlsi;
+ int rc;
+
+ ENTRY;
+
+ OBD_ALLOC(mlsi, sizeof(*mlsi));
+ if (mlsi == NULL)
+ RETURN(-ENOMEM);
+
+ mlsi->mlsi_obd = obd;
+ mlsi->mlsi_uuid = uuid;
+
+ rc = kernel_thread(mds_lov_synchronize, mlsi, CLONE_VM | CLONE_FILES);
+ if (rc < 0)
+ CERROR("%s: error starting mds_lov_synchronize: %d\n",
+ obd->obd_name, rc);
+ else {
+ CDEBUG(D_HA, "%s: mds_lov_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)
+{
+ struct obd_uuid *uuid;
+ int rc = 0;
+ ENTRY;
+
+ if (!active)
+ RETURN(0);
+
+ if (strcmp(watched->obd_type->typ_name, "osc")) {
+ 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;
+ if (obd->obd_recovering) {
+ CWARN("MDS %s: in recovery, not resetting orphans on %s\n",
+ obd->obd_name, uuid->uuid);
+ } else {
+ LASSERT(llog_get_context(obd, LLOG_UNLINK_ORIG_CTXT) != NULL);
+
+ rc = mds_lov_start_synchronize(obd, uuid);
+ }
+ RETURN(rc);
+}
+
+/* Convert the on-disk LOV EA structre.
+ * We always try to convert from an old LOV EA format to the common in-memory
+ * (lsm) format (obd_unpackmd() understands the old on-disk (lmm) format) and
+ * then convert back to the new on-disk format and save it back to disk
+ * (obd_packmd() only ever saves to the new on-disk format) so we don't have
+ * to convert it each time this inode is accessed.
+ *
+ * This function is a bit interesting in the error handling. We can safely
+ * ship the old lmm to the client in case of failure, since it uses the same
+ * obd_unpackmd() code and can do the conversion if the MDS fails for some
+ * reason. We will not delete the old lmm data until we have written the
+ * new format lmm data in fsfilt_set_md(). */
+int mds_convert_lov_ea(struct obd_device *obd, struct inode *inode,
+ struct lov_mds_md *lmm, int lmm_size)
+{
+ struct lov_stripe_md *lsm = NULL;
+ void *handle;
+ int rc, err;
+ ENTRY;
+
+ if (le32_to_cpu(lmm->lmm_magic) == LOV_MAGIC)
+ RETURN(0);
+
+ CDEBUG(D_INODE, "converting LOV EA on %lu/%u from V0 to V1\n",
+ inode->i_ino, inode->i_generation);
+ rc = obd_unpackmd(obd->u.mds.mds_osc_exp, &lsm, lmm, lmm_size);
+ if (rc < 0)
+ GOTO(conv_end, rc);
+
+ rc = obd_packmd(obd->u.mds.mds_osc_exp, &lmm, lsm);
+ if (rc < 0)
+ GOTO(conv_free, rc);
+ lmm_size = rc;
+
+ handle = fsfilt_start(obd, inode, FSFILT_OP_SETATTR, NULL);
+ if (IS_ERR(handle)) {
+ rc = PTR_ERR(handle);
+ GOTO(conv_free, rc);
+ }
+
+ rc = fsfilt_set_md(obd, inode, handle, lmm, lmm_size);
+
+ err = fsfilt_commit(obd, inode, handle, 0);
+ if (!rc)
+ rc = err ? err : lmm_size;
+ GOTO(conv_free, rc);
+conv_free:
+ obd_free_memmd(obd->u.mds.mds_osc_exp, &lsm);
+conv_end:
+ return rc;