diff options
author | Frederic Weisbecker <fweisbec@gmail.com> | 2010-09-30 18:15:38 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-01 13:50:59 -0400 |
commit | 9d8117e72bf453dd9d85e0cd322ce4a0f8bccbc0 (patch) | |
tree | b04c93fa9d41db9802c576f8dfaf74edb42ebc60 /fs/reiserfs | |
parent | 3f259d092c7a2fdf217823e8f1838530adb0cdb0 (diff) |
reiserfs: fix unwanted reiserfs lock recursion
Prevent from recursively locking the reiserfs lock in reiserfs_unpack()
because we may call journal_begin() that requires the lock to be taken
only once, otherwise it won't be able to release the lock while taking
other mutexes, ending up in inverted dependencies between the journal
mutex and the reiserfs lock for example.
This fixes:
=======================================================
[ INFO: possible circular locking dependency detected ]
2.6.35.4.4a #3
-------------------------------------------------------
lilo/1620 is trying to acquire lock:
(&journal->j_mutex){+.+...}, at: [<d0325bff>] do_journal_begin_r+0x7f/0x340 [reiserfs]
but task is already holding lock:
(&REISERFS_SB(s)->lock){+.+.+.}, at: [<d032a278>] reiserfs_write_lock+0x28/0x40 [reiserfs]
which lock already depends on the new lock.
the existing dependency chain (in reverse order) is:
-> #1 (&REISERFS_SB(s)->lock){+.+.+.}:
[<c10562b7>] lock_acquire+0x67/0x80
[<c12facad>] __mutex_lock_common+0x4d/0x410
[<c12fb0c8>] mutex_lock_nested+0x18/0x20
[<d032a278>] reiserfs_write_lock+0x28/0x40 [reiserfs]
[<d0325c06>] do_journal_begin_r+0x86/0x340 [reiserfs]
[<d0325f77>] journal_begin+0x77/0x140 [reiserfs]
[<d0315be4>] reiserfs_remount+0x224/0x530 [reiserfs]
[<c10b6a20>] do_remount_sb+0x60/0x110
[<c10cee25>] do_mount+0x625/0x790
[<c10cf014>] sys_mount+0x84/0xb0
[<c12fca3d>] syscall_call+0x7/0xb
-> #0 (&journal->j_mutex){+.+...}:
[<c10560f6>] __lock_acquire+0x1026/0x1180
[<c10562b7>] lock_acquire+0x67/0x80
[<c12facad>] __mutex_lock_common+0x4d/0x410
[<c12fb0c8>] mutex_lock_nested+0x18/0x20
[<d0325bff>] do_journal_begin_r+0x7f/0x340 [reiserfs]
[<d0325f77>] journal_begin+0x77/0x140 [reiserfs]
[<d0326271>] reiserfs_persistent_transaction+0x41/0x90 [reiserfs]
[<d030d06c>] reiserfs_get_block+0x22c/0x1530 [reiserfs]
[<c10db9db>] __block_prepare_write+0x1bb/0x3a0
[<c10dbbe6>] block_prepare_write+0x26/0x40
[<d030b738>] reiserfs_prepare_write+0x88/0x170 [reiserfs]
[<d03294d6>] reiserfs_unpack+0xe6/0x120 [reiserfs]
[<d0329782>] reiserfs_ioctl+0x272/0x320 [reiserfs]
[<c10c3188>] vfs_ioctl+0x28/0xa0
[<c10c3bbd>] do_vfs_ioctl+0x32d/0x5c0
[<c10c3eb3>] sys_ioctl+0x63/0x70
[<c12fca3d>] syscall_call+0x7/0xb
other info that might help us debug this:
2 locks held by lilo/1620:
#0: (&sb->s_type->i_mutex_key#8){+.+.+.}, at: [<d032945a>] reiserfs_unpack+0x6a/0x120 [reiserfs]
#1: (&REISERFS_SB(s)->lock){+.+.+.}, at: [<d032a278>] reiserfs_write_lock+0x28/0x40 [reiserfs]
stack backtrace:
Pid: 1620, comm: lilo Not tainted 2.6.35.4.4a #3
Call Trace:
[<c10560f6>] __lock_acquire+0x1026/0x1180
[<c10562b7>] lock_acquire+0x67/0x80
[<c12facad>] __mutex_lock_common+0x4d/0x410
[<c12fb0c8>] mutex_lock_nested+0x18/0x20
[<d0325bff>] do_journal_begin_r+0x7f/0x340 [reiserfs]
[<d0325f77>] journal_begin+0x77/0x140 [reiserfs]
[<d0326271>] reiserfs_persistent_transaction+0x41/0x90 [reiserfs]
[<d030d06c>] reiserfs_get_block+0x22c/0x1530 [reiserfs]
[<c10db9db>] __block_prepare_write+0x1bb/0x3a0
[<c10dbbe6>] block_prepare_write+0x26/0x40
[<d030b738>] reiserfs_prepare_write+0x88/0x170 [reiserfs]
[<d03294d6>] reiserfs_unpack+0xe6/0x120 [reiserfs]
[<d0329782>] reiserfs_ioctl+0x272/0x320 [reiserfs]
[<c10c3188>] vfs_ioctl+0x28/0xa0
[<c10c3bbd>] do_vfs_ioctl+0x32d/0x5c0
[<c10c3eb3>] sys_ioctl+0x63/0x70
[<c12fca3d>] syscall_call+0x7/0xb
Reported-by: Jarek Poplawski <jarkao2@gmail.com>
Tested-by: Jarek Poplawski <jarkao2@gmail.com>
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jeff Mahoney <jeffm@suse.com>
Cc: All since 2.6.32 <stable@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/reiserfs')
-rw-r--r-- | fs/reiserfs/ioctl.c | 5 |
1 files changed, 3 insertions, 2 deletions
diff --git a/fs/reiserfs/ioctl.c b/fs/reiserfs/ioctl.c index 679d5029f50f..5cbb81e134ac 100644 --- a/fs/reiserfs/ioctl.c +++ b/fs/reiserfs/ioctl.c | |||
@@ -170,6 +170,7 @@ int reiserfs_prepare_write(struct file *f, struct page *page, | |||
170 | int reiserfs_unpack(struct inode *inode, struct file *filp) | 170 | int reiserfs_unpack(struct inode *inode, struct file *filp) |
171 | { | 171 | { |
172 | int retval = 0; | 172 | int retval = 0; |
173 | int depth; | ||
173 | int index; | 174 | int index; |
174 | struct page *page; | 175 | struct page *page; |
175 | struct address_space *mapping; | 176 | struct address_space *mapping; |
@@ -189,7 +190,7 @@ int reiserfs_unpack(struct inode *inode, struct file *filp) | |||
189 | ** us | 190 | ** us |
190 | */ | 191 | */ |
191 | reiserfs_mutex_lock_safe(&inode->i_mutex, inode->i_sb); | 192 | reiserfs_mutex_lock_safe(&inode->i_mutex, inode->i_sb); |
192 | reiserfs_write_lock(inode->i_sb); | 193 | depth = reiserfs_write_lock_once(inode->i_sb); |
193 | 194 | ||
194 | write_from = inode->i_size & (blocksize - 1); | 195 | write_from = inode->i_size & (blocksize - 1); |
195 | /* if we are on a block boundary, we are already unpacked. */ | 196 | /* if we are on a block boundary, we are already unpacked. */ |
@@ -224,6 +225,6 @@ int reiserfs_unpack(struct inode *inode, struct file *filp) | |||
224 | 225 | ||
225 | out: | 226 | out: |
226 | mutex_unlock(&inode->i_mutex); | 227 | mutex_unlock(&inode->i_mutex); |
227 | reiserfs_write_unlock(inode->i_sb); | 228 | reiserfs_write_unlock_once(inode->i_sb, depth); |
228 | return retval; | 229 | return retval; |
229 | } | 230 | } |