block: make disk_block_events() properly wait for work cancellation
authorTejun Heo <tj@kernel.org>
Thu, 9 Jun 2011 18:43:59 +0000 (20:43 +0200)
committerJens Axboe <jaxboe@fusionio.com>
Thu, 9 Jun 2011 18:43:59 +0000 (20:43 +0200)
commitfdd514e16bb2531c0c61ae8a1f87740ce217f630
tree5d7b6d4f9112b0b6f93f7ce939045fb634abc3fa
parentc3af54afbac3675337cedf326b7b127ffa7f7327
block: make disk_block_events() properly wait for work cancellation

disk_block_events() should guarantee that the event work is not in
flight on return and once blocked it shouldn't issue further
cancellations.

Because there was no synchronization between the first blocker doing
cancel_delayed_work_sync() and the following blockers, the following
blockers could finish before cancellation was complete, which broke
both guarantees - event work could be in flight and cancellation could
happen after return.

This bug triggered WARN_ON_ONCE() in disk_clear_events() reported in
bug#34662.

  https://bugzilla.kernel.org/show_bug.cgi?id=34662

Fix it by adding an outer mutex which protects both block count
manipulation and work cancellation.

-v2: Use outer mutex instead of bit waitqueue per Linus.

Signed-off-by: Tejun Heo <tj@kernel.org>
Tested-by: Sitsofe Wheeler <sitsofe@yahoo.com>
Reported-by: Sitsofe Wheeler <sitsofe@yahoo.com>
Reported-by: Borislav Petkov <bp@alien8.de>
Reported-by: Meelis Roos <mroos@linux.ee>
Reported-by: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Kay Sievers <kay.sievers@vrfy.org>
Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
block/genhd.c