android_kernel_samsung_msm8976/drivers/block
Ilya Dryomov dff252b849 rbd: fix copyup completion race
commit 2761713d35e370fd640b5781109f753066b746c4 upstream.

For write/discard obj_requests that involved a copyup method call, the
opcode of the first op is CEPH_OSD_OP_CALL and the ->callback is
rbd_img_obj_copyup_callback().  The latter frees copyup pages, sets
->xferred and delegates to rbd_img_obj_callback(), the "normal" image
object callback, for reporting to block layer and putting refs.

rbd_osd_req_callback() however treats CEPH_OSD_OP_CALL as a trivial op,
which means obj_request is marked done in rbd_osd_trivial_callback(),
*before* ->callback is invoked and rbd_img_obj_copyup_callback() has
a chance to run.  Marking obj_request done essentially means giving
rbd_img_obj_callback() a license to end it at any moment, so if another
obj_request from the same img_request is being completed concurrently,
rbd_img_obj_end_request() may very well be called on such prematurally
marked done request:

<obj_request-1/2 reply>
handle_reply()
  rbd_osd_req_callback()
    rbd_osd_trivial_callback()
    rbd_obj_request_complete()
    rbd_img_obj_copyup_callback()
    rbd_img_obj_callback()
                                    <obj_request-2/2 reply>
                                    handle_reply()
                                      rbd_osd_req_callback()
                                        rbd_osd_trivial_callback()
      for_each_obj_request(obj_request->img_request) {
        rbd_img_obj_end_request(obj_request-1/2)
        rbd_img_obj_end_request(obj_request-2/2) <--
      }

Calling rbd_img_obj_end_request() on such a request leads to trouble,
in particular because its ->xfferred is 0.  We report 0 to the block
layer with blk_update_request(), get back 1 for "this request has more
data in flight" and then trip on

    rbd_assert(more ^ (which == img_request->obj_request_count));

with rhs (which == ...) being 1 because rbd_img_obj_end_request() has
been called for both requests and lhs (more) being 1 because we haven't
got a chance to set ->xfferred in rbd_img_obj_copyup_callback() yet.

To fix this, leverage that rbd wants to call class methods in only two
cases: one is a generic method call wrapper (obj_request is standalone)
and the other is a copyup (obj_request is part of an img_request).  So
make a dedicated handler for CEPH_OSD_OP_CALL and directly invoke
rbd_img_obj_copyup_callback() from it if obj_request is part of an
img_request, similar to how CEPH_OSD_OP_READ handler invokes
rbd_img_obj_request_read_callback().

Since rbd_img_obj_copyup_callback() is now being called from the OSD
request callback (only), it is renamed to rbd_osd_copyup_callback().

Cc: Alex Elder <elder@linaro.org>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Reviewed-by: Alex Elder <elder@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2015-08-16 20:51:39 -07:00
..
aoe mm: close PageTail race 2014-04-03 12:01:05 -07:00
drbd drbd: merge_bvec_fn: properly remap bvm->bi_bdev 2015-01-29 17:40:57 -08:00
mtip32xx mtip32xx: Remove dfs_parent after pci unregister 2014-07-06 18:54:13 -07:00
paride
rsxx
xen-blkback xen/blkback: fix reference counting 2013-12-04 10:56:25 -08:00
amiflop.c
ataflop.c
brd.c
cciss.c
cciss.h
cciss_cmd.h
cciss_scsi.c
cciss_scsi.h
cpqarray.c
cpqarray.h
cryptoloop.c
DAC960.c
DAC960.h
floppy.c floppy: don't write kernel-only members to FDRAWCMD ioctl output 2014-05-13 13:59:40 +02:00
hd.c
ida_cmd.h
ida_ioctl.h
Kconfig
loop.c loop: fix crash when using unassigned loop device 2013-12-04 10:56:20 -08:00
Makefile
mg_disk.c
nbd.c nbd: fix possible memory leak 2015-04-19 10:10:47 +02:00
nvme-core.c
nvme-scsi.c
osdblk.c
pktcdvd.c
ps3disk.c
ps3vram.c
rbd.c rbd: fix copyup completion race 2015-08-16 20:51:39 -07:00
rbd_types.h
smart1,2.h
sunvdc.c sunvdc: don't call VD_OP_GET_VTOC 2014-11-21 09:22:52 -08:00
swim.c
swim3.c
swim_asm.S
sx8.c
umem.c
umem.h
virtio_blk.c
xen-blkfront.c xen-blkfront: restore the non-persistent data path 2014-06-07 13:25:37 -07:00
xsysace.c
z2ram.c