aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAsias He <asias@redhat.com>2012-05-24 22:34:48 -0400
committerRusty Russell <rusty@rustcorp.com.au>2012-07-30 00:00:51 -0400
commit483001c765af6892b3fc3726576cb42f17d1d6b5 (patch)
tree7b600bf8759b51bc1d03c28f5ef92f99041d88b5
parent02e2b124943648fba0a2ccee5c3656a5653e0151 (diff)
virtio-blk: Reset device after blk_cleanup_queue()
blk_cleanup_queue() will call blk_drian_queue() to drain all the requests before queue DEAD marking. If we reset the device before blk_cleanup_queue() the drain would fail. 1) if the queue is stopped in do_virtblk_request() because device is full, the q->request_fn() will not be called. blk_drain_queue() { while(true) { ... if (!list_empty(&q->queue_head)) __blk_run_queue(q) { if (queue is not stoped) q->request_fn() } ... } } Do no reset the device before blk_cleanup_queue() gives the chance to start the queue in interrupt handler blk_done(). 2) In commit b79d866c8b7014a51f611a64c40546109beaf24a, We abort requests dispatched to driver before blk_cleanup_queue(). There is a race if requests are dispatched to driver after the abort and before the queue DEAD mark. To fix this, instead of aborting the requests explicitly, we can just reset the device after after blk_cleanup_queue so that the device can complete all the requests before queue DEAD marking in the drain process. Cc: Rusty Russell <rusty@rustcorp.com.au> Cc: virtualization@lists.linux-foundation.org Cc: kvm@vger.kernel.org Cc: stable@kernel.org Signed-off-by: Asias He <asias@redhat.com> Acked-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
-rw-r--r--drivers/block/virtio_blk.c12
1 files changed, 1 insertions, 11 deletions
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index 1bed51712dd1..b4fa2d71496e 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -576,8 +576,6 @@ static void __devexit virtblk_remove(struct virtio_device *vdev)
576{ 576{
577 struct virtio_blk *vblk = vdev->priv; 577 struct virtio_blk *vblk = vdev->priv;
578 int index = vblk->index; 578 int index = vblk->index;
579 struct virtblk_req *vbr;
580 unsigned long flags;
581 579
582 /* Prevent config work handler from accessing the device. */ 580 /* Prevent config work handler from accessing the device. */
583 mutex_lock(&vblk->config_lock); 581 mutex_lock(&vblk->config_lock);
@@ -585,21 +583,13 @@ static void __devexit virtblk_remove(struct virtio_device *vdev)
585 mutex_unlock(&vblk->config_lock); 583 mutex_unlock(&vblk->config_lock);
586 584
587 del_gendisk(vblk->disk); 585 del_gendisk(vblk->disk);
586 blk_cleanup_queue(vblk->disk->queue);
588 587
589 /* Stop all the virtqueues. */ 588 /* Stop all the virtqueues. */
590 vdev->config->reset(vdev); 589 vdev->config->reset(vdev);
591 590
592 flush_work(&vblk->config_work); 591 flush_work(&vblk->config_work);
593 592
594 /* Abort requests dispatched to driver. */
595 spin_lock_irqsave(&vblk->lock, flags);
596 while ((vbr = virtqueue_detach_unused_buf(vblk->vq))) {
597 __blk_end_request_all(vbr->req, -EIO);
598 mempool_free(vbr, vblk->pool);
599 }
600 spin_unlock_irqrestore(&vblk->lock, flags);
601
602 blk_cleanup_queue(vblk->disk->queue);
603 put_disk(vblk->disk); 593 put_disk(vblk->disk);
604 mempool_destroy(vblk->pool); 594 mempool_destroy(vblk->pool);
605 vdev->config->del_vqs(vdev); 595 vdev->config->del_vqs(vdev);