]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
ext2 deadlock fix, fwd from akpm
authorChris Wright <chrisw@sous-sol.org>
Fri, 17 Feb 2006 23:19:19 +0000 (15:19 -0800)
committerChris Wright <chrisw@sous-sol.org>
Fri, 17 Feb 2006 23:19:19 +0000 (15:19 -0800)
queue/fix-deadlock-in-ext2.patch [new file with mode: 0644]
queue/series

diff --git a/queue/fix-deadlock-in-ext2.patch b/queue/fix-deadlock-in-ext2.patch
new file mode 100644 (file)
index 0000000..204c45b
--- /dev/null
@@ -0,0 +1,56 @@
+From stable-bounces@linux.kernel.org  Fri Feb 17 13:57:16 2006
+Date: Fri, 17 Feb 2006 13:52:36 -0800
+From: akpm@osdl.org
+To: torvalds@osdl.org
+Cc: staubach@redhat.com, stable@kernel.org
+Subject: [PATCH] fix deadlock in ext2
+
+From: Peter Staubach <staubach@redhat.com>
+
+Fix a deadlock possible in the ext2 file system implementation.  This
+deadlock occurs when a file is removed from an ext2 file system which was
+mounted with the "sync" mount option.
+
+The problem is that ext2_xattr_delete_inode() was invoking the routine,
+sync_dirty_buffer(), using a buffer head which was previously locked via
+lock_buffer().  The first thing that sync_dirty_buffer() does is to lock
+the buffer head that it was passed.  It does this via lock_buffer().  Oops.
+
+The solution is to unlock the buffer head in ext2_xattr_delete_inode()
+before invoking sync_dirty_buffer().  This makes the code in
+ext2_xattr_delete_inode() obey the same locking rules as all other callers
+of sync_dirty_buffer() in the ext2 file system implementation.
+
+Signed-off-by: Peter Staubach <staubach@redhat.com>
+Cc: <stable@kernel.org>
+Signed-off-by: Andrew Morton <akpm@osdl.org>
+---
+
+ fs/ext2/xattr.c |    6 ++++--
+ 1 files changed, 4 insertions(+), 2 deletions(-)
+
+--- linux-2.6.15.4.orig/fs/ext2/xattr.c
++++ linux-2.6.15.4/fs/ext2/xattr.c
+@@ -796,18 +796,20 @@ ext2_xattr_delete_inode(struct inode *in
+               ext2_free_blocks(inode, EXT2_I(inode)->i_file_acl, 1);
+               get_bh(bh);
+               bforget(bh);
++              unlock_buffer(bh);
+       } else {
+               HDR(bh)->h_refcount = cpu_to_le32(
+                       le32_to_cpu(HDR(bh)->h_refcount) - 1);
+               if (ce)
+                       mb_cache_entry_release(ce);
++              ea_bdebug(bh, "refcount now=%d",
++                      le32_to_cpu(HDR(bh)->h_refcount));
++              unlock_buffer(bh);
+               mark_buffer_dirty(bh);
+               if (IS_SYNC(inode))
+                       sync_dirty_buffer(bh);
+               DQUOT_FREE_BLOCK(inode, 1);
+       }
+-      ea_bdebug(bh, "refcount now=%d", le32_to_cpu(HDR(bh)->h_refcount) - 1);
+-      unlock_buffer(bh);
+       EXT2_I(inode)->i_file_acl = 0;
+ cleanup:
index dc5f28859693e2230971feaeaa1278030bf58d60..72fa12ad140c988b81f78003093154cfd6591b3d 100644 (file)
@@ -14,3 +14,4 @@ sys32_signal-forgets-to-initialize-sa_mask.patch
 fix-s390-build-failure.patch
 fix-deadlock-in-br_stp_disable_bridge.patch
 fix-zap_thread-s-ptrace-related-problems.patch
+fix-deadlock-in-ext2.patch