[PATCH] deadlock in ext2

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi.

The attached patch addresses 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.

   Thanx...

      ps

Signed-off-by: Peter Staubach <[email protected]>
--- linux-2.6.15.x86_64/fs/ext2/xattr.c.org
+++ linux-2.6.15.x86_64/fs/ext2/xattr.c
@@ -792,18 +792,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 of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux