From adbd0a3310f34e991df0d37eae865cf748037f4f Mon Sep 17 00:00:00 2001 From: Chris Wright Date: Fri, 17 Feb 2006 15:19:19 -0800 Subject: [PATCH] ext2 deadlock fix, fwd from akpm --- queue/fix-deadlock-in-ext2.patch | 56 ++++++++++++++++++++++++++++++++ queue/series | 1 + 2 files changed, 57 insertions(+) create mode 100644 queue/fix-deadlock-in-ext2.patch diff --git a/queue/fix-deadlock-in-ext2.patch b/queue/fix-deadlock-in-ext2.patch new file mode 100644 index 00000000000..204c45bd669 --- /dev/null +++ b/queue/fix-deadlock-in-ext2.patch @@ -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 + +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 +Cc: +Signed-off-by: Andrew Morton +--- + + 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: diff --git a/queue/series b/queue/series index dc5f2885969..72fa12ad140 100644 --- a/queue/series +++ b/queue/series @@ -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 -- 2.47.3