Whamcloud - gitweb
Branch b1_8
authorjohann <johann>
Fri, 21 Aug 2009 15:42:44 +0000 (15:42 +0000)
committerjohann <johann>
Fri, 21 Aug 2009 15:42:44 +0000 (15:42 +0000)
b=20321
i=bzzz
i=dmitry

Take i_alloc_sem in filter_destroy() when truncating the object & fix inode mutex leak

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

index c62a402..3d46722 100644 (file)
@@ -23,14 +23,14 @@ Severity   : normal
 Bugzilla   : 19934
 Description: correctly send lsm on open replay
 Details    : MDS is trust to LSM size on replay open, but client can set wrong size
-             to lsm buffer.
+            to lsm buffer.
 
 Severity   : normal
 Bugzilla   : 20008
 Description: truncate starts GFP_FS allocation under transaction causing deadlock
 Details    : ldiskfs_truncate calls grab_cache_page which may start page
-             allocation under an open transaction. This may lead to
-             calling prune_icache with consequent lustre reentrance.
+            allocation under an open transaction. This may lead to
+            calling prune_icache with consequent lustre reentrance.
 
 Severity   : enhancement 
 Bugzilla   : 20200
@@ -49,7 +49,8 @@ Description: Deadlock between filter_destroy() and filter_commitrw_write().
 Details    : filter_destroy() does not hold the DLM lock over the whole
             operation. If the DLM lock is dropped, filter_commitrw() can go
             through, causing the deadlock between page lock and i_mutex.
-
+            The i_alloc_sem should also be hold in filter_destroy() while
+            truncating the file.
 
 Severity   : enhancement
 Bugzilla   : 18539
index 9cdcb40..735901d 100644 (file)
@@ -3605,18 +3605,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));
         }
 
@@ -3625,6 +3635,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 05c7053..6cd82ef 100644 (file)
@@ -778,7 +778,7 @@ cleanup:
                  * lnb->page automatically returns back into per-thread page
                  * pool (bug 5137)
                  */
-                f_dput(res->dentry);
+                 break;
         }
 
         /* trigger quota pre-acquire */
@@ -812,6 +812,7 @@ cleanup:
                         filter_release_cache(obd, obj, nb, inode);
                 up_read(&inode->i_alloc_sem);
         }
+        f_dput(res->dentry);
 
         RETURN(rc);
 }