virtio-blk: virtqueue_kick() must be ordered with other virtqueue operations
authorShaohua Li <shli@fusionio.com>
Wed, 20 Nov 2013 01:57:24 +0000 (18:57 -0700)
committerJens Axboe <axboe@kernel.dk>
Wed, 20 Nov 2013 02:00:45 +0000 (19:00 -0700)
It isn't safe to call it without holding the vblk->vq_lock.

Reported-by: Dave Chinner <david@fromorbit.com>
Signed-off-by: Shaohua Li <shli@fusionio.com>
Fixed another condition of virtqueue_kick() not holding the lock.

Signed-off-by: Jens Axboe <axboe@kernel.dk>
drivers/block/virtio_blk.c

index 588479d..6a680d4 100644 (file)
@@ -199,15 +199,16 @@ static int virtio_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *req)
 
        spin_lock_irqsave(&vblk->vq_lock, flags);
        if (__virtblk_add_req(vblk->vq, vbr, vbr->sg, num) < 0) {
+               virtqueue_kick(vblk->vq);
                spin_unlock_irqrestore(&vblk->vq_lock, flags);
                blk_mq_stop_hw_queue(hctx);
-               virtqueue_kick(vblk->vq);
                return BLK_MQ_RQ_QUEUE_BUSY;
        }
-       spin_unlock_irqrestore(&vblk->vq_lock, flags);
 
        if (last)
                virtqueue_kick(vblk->vq);
+
+       spin_unlock_irqrestore(&vblk->vq_lock, flags);
        return BLK_MQ_RQ_QUEUE_OK;
 }