aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrederic Weisbecker <fweisbec@gmail.com>2009-09-16 23:31:37 -0400
committerFrederic Weisbecker <fweisbec@gmail.com>2009-09-16 23:31:37 -0400
commit193be0ee17dd7ea309ddab1093da17e5924d7f36 (patch)
treed57d6a5162311b9f4513f485aca89fe5b992e31a
parent80503185989b2dd84170bb842e23d3fd45ebdf40 (diff)
kill-the-bkl/reiserfs: Fix induced mm->mmap_sem to sysfs_mutex dependency
Alexander Beregalov reported the following warning: ======================================================= [ INFO: possible circular locking dependency detected ] 2.6.31-03149-gdcc030a #1 ------------------------------------------------------- udevadm/716 is trying to acquire lock: (&mm->mmap_sem){++++++}, at: [<c107249a>] might_fault+0x4a/0xa0 but task is already holding lock: (sysfs_mutex){+.+.+.}, at: [<c10cb9aa>] sysfs_readdir+0x5a/0x200 which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> #3 (sysfs_mutex){+.+.+.}: [...] -> #2 (&bdev->bd_mutex){+.+.+.}: [...] -> #1 (&REISERFS_SB(s)->lock){+.+.+.}: [...] -> #0 (&mm->mmap_sem){++++++}: [...] On reiserfs mount path, we take the reiserfs lock and while initializing the journal, we open the device, taking the bdev->bd_mutex. Then rescan_partition() may signal the change to sysfs. We have then the following dependency: reiserfs_lock -> bd_mutex -> sysfs_mutex Later, while entering reiserfs_readpage() after a pagefault in an mmaped reiserfs file, we are holding the mm->mmap_sem, and we are going to take the reiserfs lock too. We have then the following dependency: mm->mmap_sem -> reiserfs_lock which, expanded with the previous dependency gives us: mm->mmap_sem -> reiserfs_lock -> bd_mutex -> sysfs_mutex Now while entering the sysfs readdir path, we are holding the sysfs_mutex. And when we copy a directory entry to the user buffer, we might fault and then take the mm->mmap_sem lock. Which leads to the circular locking dependency reported. We can fix that by relaxing the reiserfs lock during the call to journal_init_dev(), which is the place where we open the mounted device. This is fine to relax the lock here because we are in the begining of the reiserfs mount path and there is nothing to protect at this time, the journal is not intialized. We just keep this lock around for paranoid reasons. Reported-by: Alexander Beregalov <a.beregalov@gmail.com> Tested-by: Alexander Beregalov <a.beregalov@gmail.com> Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Jeff Mahoney <jeffm@suse.com> Cc: Chris Mason <chris.mason@oracle.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Alexander Beregalov <a.beregalov@gmail.com> Cc: Laurent Riffard <laurent.riffard@free.fr>
-rw-r--r--fs/reiserfs/journal.c16
1 files changed, 16 insertions, 0 deletions
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
index d23d6d7a45a6..04e3c42a085f 100644
--- a/fs/reiserfs/journal.c
+++ b/fs/reiserfs/journal.c
@@ -2801,11 +2801,27 @@ int journal_init(struct super_block *sb, const char *j_dev_name,
2801 goto free_and_return; 2801 goto free_and_return;
2802 } 2802 }
2803 2803
2804 /*
2805 * We need to unlock here to avoid creating the following
2806 * dependency:
2807 * reiserfs_lock -> sysfs_mutex
2808 * Because the reiserfs mmap path creates the following dependency:
2809 * mm->mmap -> reiserfs_lock, hence we have
2810 * mm->mmap -> reiserfs_lock ->sysfs_mutex
2811 * This would ends up in a circular dependency with sysfs readdir path
2812 * which does sysfs_mutex -> mm->mmap_sem
2813 * This is fine because the reiserfs lock is useless in mount path,
2814 * at least until we call journal_begin. We keep it for paranoid
2815 * reasons.
2816 */
2817 reiserfs_write_unlock(sb);
2804 if (journal_init_dev(sb, journal, j_dev_name) != 0) { 2818 if (journal_init_dev(sb, journal, j_dev_name) != 0) {
2819 reiserfs_write_lock(sb);
2805 reiserfs_warning(sb, "sh-462", 2820 reiserfs_warning(sb, "sh-462",
2806 "unable to initialize jornal device"); 2821 "unable to initialize jornal device");
2807 goto free_and_return; 2822 goto free_and_return;
2808 } 2823 }
2824 reiserfs_write_lock(sb);
2809 2825
2810 rs = SB_DISK_SUPER_BLOCK(sb); 2826 rs = SB_DISK_SUPER_BLOCK(sb);
2811 2827