Whamcloud - gitweb
LU-81 deadlock of changelog adding vs. changelog cancelling
[fs/lustre-release.git] / lustre / mds / mds_log.c
index 582531e..91ea64c 100644 (file)
@@ -26,7 +26,7 @@
  * GPL HEADER END
  */
 /*
- * Copyright  2008 Sun Microsystems, Inc. All rights reserved
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
  */
 /*
@@ -60,7 +60,7 @@ static int mds_llog_origin_add(struct llog_ctxt *ctxt, struct llog_rec_hdr *rec,
                                struct llog_cookie *logcookies, int numcookies)
 {
         struct obd_device *obd = ctxt->loc_obd;
-        struct obd_device *lov_obd = obd->u.mds.mds_osc_obd;
+        struct obd_device *lov_obd = obd->u.mds.mds_lov_obd;
         struct llog_ctxt *lctxt;
         int rc;
         ENTRY;
@@ -78,7 +78,7 @@ static int mds_llog_origin_connect(struct llog_ctxt *ctxt,
                                    struct obd_uuid *uuid)
 {
         struct obd_device *obd = ctxt->loc_obd;
-        struct obd_device *lov_obd = obd->u.mds.mds_osc_obd;
+        struct obd_device *lov_obd = obd->u.mds.mds_lov_obd;
         struct llog_ctxt *lctxt;
         int rc;
         ENTRY;
@@ -98,7 +98,7 @@ static int mds_llog_repl_cancel(struct llog_ctxt *ctxt, struct lov_stripe_md *ls
                           int count, struct llog_cookie *cookies, int flags)
 {
         struct obd_device *obd = ctxt->loc_obd;
-        struct obd_device *lov_obd = obd->u.mds.mds_osc_obd;
+        struct obd_device *lov_obd = obd->u.mds.mds_lov_obd;
         struct llog_ctxt *lctxt;
         int rc;
         ENTRY;
@@ -121,7 +121,10 @@ static int llog_changelog_cancel_cb(struct llog_handle *llh,
         struct llog_changelog_rec *rec = (struct llog_changelog_rec *)hdr;
         struct llog_cookie cookie;
         long long endrec = *(long long *)data;
-        int rc;
+        int rc, err;
+        struct obd_device *obd;
+        void *trans_h;
+        struct inode *inode;
         ENTRY;
 
         /* This is always a (sub)log, not the catalog */
@@ -133,11 +136,34 @@ static int llog_changelog_cancel_cb(struct llog_handle *llh,
 
         cookie.lgc_lgl = llh->lgh_id;
         cookie.lgc_index = hdr->lrh_index;
+        obd = llh->lgh_ctxt->loc_exp->exp_obd;
+        inode = llh->lgh_file->f_dentry->d_inode;
+
+        /* XXX This is a workaround for the deadlock of changelog adding vs.
+         * changelog cancelling. Changelog adding always start transaction
+         * before acquiring the catlog lock (lgh_lock), whereas, changelog
+         * cancelling do start transaction after holding catlog lock.
+         *
+         * We start the transaction earlier here to keep the locking ordering:
+         * 'start transaction -> catlog lock'. LU-81. */
+        trans_h = fsfilt_start_log(obd, inode, FSFILT_OP_CANCEL_UNLINK,
+                                   NULL, 1);
+        if (IS_ERR(trans_h)) {
+                CERROR("fsfilt_start_log failed: %ld\n", PTR_ERR(trans_h));
+                RETURN(PTR_ERR(trans_h));
+        }
 
         /* cancel them one at a time.  I suppose we could store up the cookies
            and cancel them all at once; probably more efficient, but this is
            done as a user call, so who cares... */
         rc = llog_cat_cancel_records(llh->u.phd.phd_cat_handle, 1, &cookie);
+
+        err = fsfilt_commit(obd, inode, trans_h, 0);
+        if (err) {
+                CERROR("fsfilt_commit failed: %d\n", err);
+                rc = (rc >= 0) ? err : rc;
+        }
+
         RETURN(rc < 0 ? rc : 0);
 }
 
@@ -198,7 +224,7 @@ EXPORT_SYMBOL(mds_changelog_llog_init);
 int mds_llog_init(struct obd_device *obd, struct obd_llog_group *olg,
                   struct obd_device *disk_obd, int *index)
 {
-        struct obd_device *lov_obd = obd->u.mds.mds_osc_obd;
+        struct obd_device *lov_obd = obd->u.mds.mds_lov_obd;
         struct llog_ctxt *ctxt;
         int rc;
         ENTRY;
@@ -296,15 +322,15 @@ int mds_log_op_unlink(struct obd_device *obd,
         int rc;
         ENTRY;
 
-        if (IS_ERR(mds->mds_osc_obd))
-                RETURN(PTR_ERR(mds->mds_osc_obd));
+        if (IS_ERR(mds->mds_lov_obd))
+                RETURN(PTR_ERR(mds->mds_lov_obd));
 
-        rc = obd_unpackmd(mds->mds_osc_exp, &lsm, lmm, lmm_size);
+        rc = obd_unpackmd(mds->mds_lov_exp, &lsm, lmm, lmm_size);
         if (rc < 0)
                 RETURN(rc);
         rc = mds_llog_add_unlink(obd, lsm, 0, logcookies,
                                  cookies_size / sizeof(struct llog_cookie));
-        obd_free_memmd(mds->mds_osc_exp, &lsm);
+        obd_free_memmd(mds->mds_lov_exp, &lsm);
         RETURN(rc);
 }
 EXPORT_SYMBOL(mds_log_op_unlink);
@@ -317,8 +343,8 @@ int mds_log_op_orphan(struct obd_device *obd, struct lov_stripe_md *lsm,
         int rc;
         ENTRY;
 
-        if (IS_ERR(mds->mds_osc_obd))
-                RETURN(PTR_ERR(mds->mds_osc_obd));
+        if (IS_ERR(mds->mds_lov_obd))
+                RETURN(PTR_ERR(mds->mds_lov_obd));
 
         rc = mds_llog_add_unlink(obd, lsm, count - 1, &logcookie, 1);
         RETURN(rc);