Whamcloud - gitweb
LU-81 deadlock of changelog adding vs. changelog cancelling
[fs/lustre-release.git] / lustre / mdd / mdd_device.c
index d69839b..2747214 100644 (file)
@@ -1357,6 +1357,8 @@ struct mdd_changelog_user_data {
         __u32 mcud_minid;  /**< user id with lowest rec reference */
         __u32 mcud_usercount;
         int   mcud_found:1;
+        struct mdd_device   *mcud_mdd;
+        const struct lu_env *mcud_env;
 };
 #define MCUD_UNREGISTER -1LL
 
@@ -1399,12 +1401,28 @@ static int mdd_changelog_user_purge_cb(struct llog_handle *llh,
         /* Special case: unregister this user */
         if (mcud->mcud_endrec == MCUD_UNREGISTER) {
                 struct llog_cookie cookie;
+                void *trans_h;
+                struct mdd_device *mdd = mcud->mcud_mdd;
+
                 cookie.lgc_lgl = llh->lgh_id;
                 cookie.lgc_index = hdr->lrh_index;
+
+                /* XXX This is a workaround for the deadlock of changelog
+                 * adding vs. changelog cancelling. LU-81. */
+                mdd_txn_param_build(mcud->mcud_env, mdd, MDD_TXN_UNLINK_OP, 0);
+                trans_h = mdd_trans_start(mcud->mcud_env, mdd);
+                if (IS_ERR(trans_h)) {
+                        CERROR("fsfilt_start_log failed: %ld\n",
+                               PTR_ERR(trans_h));
+                        RETURN(PTR_ERR(trans_h));
+                }
+
                 rc = llog_cat_cancel_records(llh->u.phd.phd_cat_handle,
                                              1, &cookie);
                 if (rc == 0)
                         mcud->mcud_usercount--;
+
+                mdd_trans_stop(mcud->mcud_env, mdd, rc, trans_h);
                 RETURN(rc);
         }
 
@@ -1420,7 +1438,8 @@ static int mdd_changelog_user_purge_cb(struct llog_handle *llh,
         RETURN(rc);
 }
 
-static int mdd_changelog_user_purge(struct mdd_device *mdd, int id,
+static int mdd_changelog_user_purge(const struct lu_env *env,
+                                    struct mdd_device *mdd, int id,
                                     long long endrec)
 {
         struct mdd_changelog_user_data data;
@@ -1435,6 +1454,8 @@ static int mdd_changelog_user_purge(struct mdd_device *mdd, int id,
         data.mcud_minrec = 0;
         data.mcud_usercount = 0;
         data.mcud_endrec = endrec;
+        data.mcud_mdd = mdd;
+        data.mcud_env = env;
         cfs_spin_lock(&mdd->mdd_cl.mc_lock);
         endrec = mdd->mdd_cl.mc_index;
         cfs_spin_unlock(&mdd->mdd_cl.mc_lock);
@@ -1498,7 +1519,8 @@ static int mdd_iocontrol(const struct lu_env *env, struct md_device *m,
         switch (cmd) {
         case OBD_IOC_CHANGELOG_CLEAR: {
                 struct changelog_setinfo *cs = karg;
-                rc = mdd_changelog_user_purge(mdd, cs->cs_id, cs->cs_recno);
+                rc = mdd_changelog_user_purge(env, mdd, cs->cs_id,
+                                              cs->cs_recno);
                 RETURN(rc);
         }
         case OBD_IOC_GET_MNTOPT: {
@@ -1524,7 +1546,7 @@ static int mdd_iocontrol(const struct lu_env *env, struct md_device *m,
                 rc = mdd_changelog_user_register(mdd, &data->ioc_u32_1);
                 break;
         case OBD_IOC_CHANGELOG_DEREG:
-                rc = mdd_changelog_user_purge(mdd, data->ioc_u32_1,
+                rc = mdd_changelog_user_purge(env, mdd, data->ioc_u32_1,
                                               MCUD_UNREGISTER);
                 break;
         default: