diff options
author | Shaohua Li <shli@fusionio.com> | 2013-11-19 20:57:24 -0500 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2013-11-19 21:00:45 -0500 |
commit | f02b9ac35a47dff745c7637fbc095f01cc03646e (patch) | |
tree | 3615c099998adb4d8b65681acb16d9b060b1ee89 | |
parent | 94eddfbeaafa3e8040a2c47d370dea0e58e76941 (diff) |
virtio-blk: virtqueue_kick() must be ordered with other virtqueue operations
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>
-rw-r--r-- | drivers/block/virtio_blk.c | 5 |
1 files changed, 3 insertions, 2 deletions
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 588479d58f52..6a680d4de7f1 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c | |||
@@ -199,15 +199,16 @@ static int virtio_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *req) | |||
199 | 199 | ||
200 | spin_lock_irqsave(&vblk->vq_lock, flags); | 200 | spin_lock_irqsave(&vblk->vq_lock, flags); |
201 | if (__virtblk_add_req(vblk->vq, vbr, vbr->sg, num) < 0) { | 201 | if (__virtblk_add_req(vblk->vq, vbr, vbr->sg, num) < 0) { |
202 | virtqueue_kick(vblk->vq); | ||
202 | spin_unlock_irqrestore(&vblk->vq_lock, flags); | 203 | spin_unlock_irqrestore(&vblk->vq_lock, flags); |
203 | blk_mq_stop_hw_queue(hctx); | 204 | blk_mq_stop_hw_queue(hctx); |
204 | virtqueue_kick(vblk->vq); | ||
205 | return BLK_MQ_RQ_QUEUE_BUSY; | 205 | return BLK_MQ_RQ_QUEUE_BUSY; |
206 | } | 206 | } |
207 | spin_unlock_irqrestore(&vblk->vq_lock, flags); | ||
208 | 207 | ||
209 | if (last) | 208 | if (last) |
210 | virtqueue_kick(vblk->vq); | 209 | virtqueue_kick(vblk->vq); |
210 | |||
211 | spin_unlock_irqrestore(&vblk->vq_lock, flags); | ||
211 | return BLK_MQ_RQ_QUEUE_OK; | 212 | return BLK_MQ_RQ_QUEUE_OK; |
212 | } | 213 | } |
213 | 214 | ||