block: fix mis-synchronisation in blkdev_issue_zeroout()
Lukas Czerner authored
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: default avatarLukas Czerner <lczerner@redhat.com>
Reported-by: default avatarEric Whitney <eric.whitney@hp.com>
Tested-by: default avatarEric Whitney <eric.whitney@hp.com>
Reviewed-by: default avatarJeff Moyer <jmoyer@redhat.com>
CC: Dmitry Monakhov <dmonakhov@openvz.org>
Signed-off-by: default avatarJens Axboe <jaxboe@fusionio.com>
0aeea189
Name Last commit Last update
..
Kconfig kconfig: rename CONFIG_EMBEDDED to CONFIG_EXPERT
Kconfig.iosched blk-cgroup: config options re-arrangement
Makefile Merge branch 'for-2.6.37/barrier' of git://git.kernel.dk/linux-2.6-block
blk-cgroup.c blk-cgroup: Allow creation of hierarchical cgroups
blk-cgroup.h blkio-throttle: limit max iops value to UINT_MAX
blk-core.c block: add @force_kblockd to __blk_run_queue()
blk-exec.c block: Prevent hang_check firing during long I/O
blk-flush.c block: blk-flush shouldn't call directly into q->request_fn() __blk_run_queue()
blk-integrity.c block: Fix double free in blk_integrity_unregister
blk-ioc.c block: Clean up exit_io_context() source code.
blk-iopoll.c tree-wide: fix assorted typos all over the place
blk-lib.c block: fix mis-synchronisation in blkdev_issue_zeroout()
blk-map.c block: check for proper length of iov entries earlier in blk_rq_map_user_iov()
blk-merge.c Merge branch 'for-2.6.38/core' of git://git.kernel.dk/linux-2.6-block
blk-settings.c block: max hardware sectors limit wrapper
blk-softirq.c generic-ipi: remove CSD_FLAG_WAIT
blk-sysfs.c block: Deprecate QUEUE_FLAG_CLUSTER and use queue_limits instead
blk-tag.c include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit slab.h inclusion from percpu.h
blk-throttle.c blk-throttle: Do not use kblockd workqueue for throtl work
blk-timeout.c block: ensure jiffies wrap is handled correctly in blk_rq_timed_out_timer
blk.h Revert "block: fix accounting bug on cross partition merges"
bsg.c [SCSI] bsg: correct fault if queue object removed while dev_t open
cfq-iosched.c block: add @force_kblockd to __blk_run_queue()
cfq.h blk-cgroup: Prepare the base for supporting more than one IO control policies
compat_ioctl.c BKL: remove extraneous #include <smp_lock.h>
deadline-iosched.c
elevator.c
genhd.c
ioctl.c
noop-iosched.c
scsi_ioctl.c