aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2010-08-04 11:59:39 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-08-04 14:17:10 -0400
commite75aa85892b2ee78c79edac720868cbef16e62eb (patch)
tree80b9ce187b207a1a817b9b4b172f86fa71d75212
parentd9b68e5e88248bb24fd4e455588bea1d56108fd6 (diff)
block_dev: always serialize exclusive open attempts
bd_prepare_to_claim() incorrectly allowed multiple attempts for exclusive open to progress in parallel if the attempting holders are identical. This triggered BUG_ON() as reported in the following bug. https://bugzilla.kernel.org/show_bug.cgi?id=16393 __bd_abort_claiming() is used to finish claiming blocks and doesn't work if multiple openers are inside a claiming block. Allowing multiple parallel open attempts to continue doesn't gain anything as those are serialized down in the call chain anyway. Fix it by always allowing only single open attempt in a claiming block. This problem can easily be reproduced by adding a delay after bd_prepare_to_claim() and attempting to mount two partitions of a disk. stable: only applicable to v2.6.35 Signed-off-by: Tejun Heo <tj@kernel.org> Reported-by: Markus Trippelsdorf <markus@trippelsdorf.de> Cc: stable@kernel.org Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--fs/block_dev.c4
1 files changed, 2 insertions, 2 deletions
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 99d6af811747..b3171fb0dc9a 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -681,8 +681,8 @@ retry:
681 if (!bd_may_claim(bdev, whole, holder)) 681 if (!bd_may_claim(bdev, whole, holder))
682 return -EBUSY; 682 return -EBUSY;
683 683
684 /* if someone else is claiming, wait for it to finish */ 684 /* if claiming is already in progress, wait for it to finish */
685 if (whole->bd_claiming && whole->bd_claiming != holder) { 685 if (whole->bd_claiming) {
686 wait_queue_head_t *wq = bit_waitqueue(&whole->bd_claiming, 0); 686 wait_queue_head_t *wq = bit_waitqueue(&whole->bd_claiming, 0);
687 DEFINE_WAIT(wait); 687 DEFINE_WAIT(wait);
688 688