Whamcloud - gitweb
Branch HEAD
authorjohann <johann>
Wed, 2 Sep 2009 16:53:26 +0000 (16:53 +0000)
committerjohann <johann>
Wed, 2 Sep 2009 16:53:26 +0000 (16:53 +0000)
b=20231
i=bzzz
i=dmitry

Take i_alloc_sem in filter_destroy() to prevent deadlock with writers.

lustre/obdfilter/filter.c
lustre/obdfilter/filter_io_26.c

index 11dcf00..13786ce 100644 (file)
@@ -4090,18 +4090,28 @@ int filter_destroy(struct obd_export *exp, struct obdo *oa,
          * down(i_zombie)       down(i_zombie)
          *                      restart transaction
          * (see BUG 4180) -bzzz
+         *
+         * take i_alloc_sem too to prevent other threads from writing to the
+         * file while we are truncating it. This can cause lock ordering issue
+         * between page lock, i_mutex & starting new journal handle.
+         * (see bug 20321) -johann
          */
+        down_write(&dchild->d_inode->i_alloc_sem);
         LOCK_INODE_MUTEX(dchild->d_inode);
 
         /* VBR: version recovery check */
         rc = filter_version_get_check(exp, oti, dchild->d_inode);
-        if (rc)
+        if (rc) {
+                UNLOCK_INODE_MUTEX(dchild->d_inode);
+                up_write(&dchild->d_inode->i_alloc_sem);
                 GOTO(cleanup, rc);
+        }
 
         handle = fsfilt_start_log(obd, dchild->d_inode, FSFILT_OP_SETATTR,
                                   NULL, 1);
         if (IS_ERR(handle)) {
                 UNLOCK_INODE_MUTEX(dchild->d_inode);
+                up_write(&dchild->d_inode->i_alloc_sem);
                 GOTO(cleanup, rc = PTR_ERR(handle));
         }
 
@@ -4110,6 +4120,7 @@ int filter_destroy(struct obd_export *exp, struct obdo *oa,
         rc = fsfilt_setattr(obd, dchild, handle, &iattr, 1);
         rc2 = fsfilt_commit(obd, dchild->d_inode, handle, 0);
         UNLOCK_INODE_MUTEX(dchild->d_inode);
+        up_write(&dchild->d_inode->i_alloc_sem);
         if (rc)
                 GOTO(cleanup, rc);
         if (rc2)
index d546f5b..2621f3f 100644 (file)
@@ -752,7 +752,7 @@ cleanup:
                  * lnb->page automatically returns back into per-thread page
                  * pool (bug 5137)
                  */
-                f_dput(res->dentry);
+                 break;
         }
 
         /* trigger quota pre-acquire */
@@ -781,6 +781,7 @@ cleanup:
                 page_cache_release(lnb->page);
                 lnb->page = NULL;
         }
+        f_dput(res->dentry);
 
         if (inode && (fo->fo_writethrough_cache == 0 ||
                         i_size_read(inode) > fo->fo_readcache_max_filesize))