linux/block
Lukas Czerner 0aeea18964 block: fix mis-synchronisation in blkdev_issue_zeroout()
BZ29402
https://bugzilla.kernel.org/show_bug.cgi?id=29402

We can hit serious mis-synchronization in bio completion path of
blkdev_issue_zeroout() leading to a panic.

The problem is that when we are going to wait_for_completion() in
blkdev_issue_zeroout() we check if the bb.done equals issued (number of
submitted bios). If it does, we can skip the wait_for_completition()
and just out of the function since there is nothing to wait for.
However, there is a ordering problem because bio_batch_end_io() is
calling atomic_inc(&bb->done) before complete(), hence it might seem to
blkdev_issue_zeroout() that all bios has been completed and exit. At
this point when bio_batch_end_io() is going to call complete(bb->wait),
bb and wait does not longer exist since it was allocated on stack in
blkdev_issue_zeroout() ==> panic!

(thread 1)                      (thread 2)
bio_batch_end_io()              blkdev_issue_zeroout()
  if(bb) {                      ...
    if (bb->end_io)             ...
      bb->end_io(bio, err);     ...
    atomic_inc(&bb->done);      ...
    ...                         while (issued != atomic_read(&bb.done))
    ...                         (let issued == bb.done)
    ...                         (do the rest of the function)
    ...                         return ret;
    complete(bb->wait);
    ^^^^^^^^
    panic

We can fix this easily by simplifying bio_batch and completion counting.

Also remove bio_end_io_t *end_io since it is not used.

Signed-off-by: Lukas Czerner <lczerner@redhat.com>
Reported-by: Eric Whitney <eric.whitney@hp.com>
Tested-by: Eric Whitney <eric.whitney@hp.com>
Reviewed-by: Jeff Moyer <jmoyer@redhat.com>
CC: Dmitry Monakhov <dmonakhov@openvz.org>
Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
2011-03-11 15:36:08 +01:00
..
Kconfig
Kconfig.iosched
Makefile
blk-cgroup.c
blk-cgroup.h
blk-core.c block: add @force_kblockd to __blk_run_queue() 2011-03-02 08:48:05 -05:00
blk-exec.c
blk-flush.c block: blk-flush shouldn't call directly into q->request_fn() __blk_run_queue() 2011-03-02 08:48:06 -05:00
blk-integrity.c
blk-ioc.c
blk-iopoll.c
blk-lib.c block: fix mis-synchronisation in blkdev_issue_zeroout() 2011-03-11 15:36:08 +01:00
blk-map.c
blk-merge.c
blk-settings.c
blk-softirq.c
blk-sysfs.c
blk-tag.c
blk-throttle.c blk-throttle: Do not use kblockd workqueue for throtl work 2011-03-01 13:41:53 -05:00
blk-timeout.c
blk.h
bsg.c
cfq-iosched.c block: add @force_kblockd to __blk_run_queue() 2011-03-02 08:48:05 -05:00
cfq.h
compat_ioctl.c
deadline-iosched.c
elevator.c block: add @force_kblockd to __blk_run_queue() 2011-03-02 08:48:05 -05:00
genhd.c
ioctl.c block: fix refcounting in BLKBSZSET 2011-02-24 08:54:21 -08:00
noop-iosched.c
scsi_ioctl.c