virtblk_abort_queue() will be called by the block layer when cleans up the queue. blk_cleanup_queue -> blk_drain_queue() -> q->abort_queue_fn(q) virtblk_abort_queue() 1) Abort requests in block which is not dispatched to driver 2) Abort requests already dispatched to driver 3) Wake up processes which is sleeping on get_request_wait() This makes hot-unplug a disk which is busy serving I/O success. Cc: Rusty Russell <rusty@xxxxxxxxxxxxxxx> Cc: "Michael S. Tsirkin" <mst@xxxxxxxxxx> Cc: virtualization@xxxxxxxxxxxxxxxxxxxxxxxxxx Cc: kvm@xxxxxxxxxxxxxxx Cc: Jens Axboe <axboe@xxxxxxxxx> Cc: Tejun Heo <tj@xxxxxxxxxx> Cc: linux-fsdevel@xxxxxxxxxxxxxxx Signed-off-by: Asias He <asias@xxxxxxxxxx> --- drivers/block/virtio_blk.c | 38 +++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 7d5f5b0..ba35509 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -182,6 +182,31 @@ static bool do_req(struct request_queue *q, struct virtio_blk *vblk, return true; } +void virtblk_abort_queue(struct request_queue *q) +{ + struct virtio_blk *vblk = q->queuedata; + struct virtblk_req *vbr; + int i; + + /* Abort requests in block layer. */ + elv_abort_queue(q); + + /* Abort requests dispatched to driver. */ + while ((vbr = virtqueue_detach_unused_buf(vblk->vq))) { + vbr->req->cmd_flags |= REQ_QUIET; + __blk_end_request_all(vbr->req, -EIO); + mempool_free(vbr, vblk->pool); + } + + /* Wake up threads sleeping on get_request_wait() */ + for (i = 0; i < ARRAY_SIZE(q->rq.wait); i++) { + if (waitqueue_active(&q->rq.wait[i])) + wake_up_all(&q->rq.wait[i]); + } + + return; +} + static void do_virtblk_request(struct request_queue *q) { struct virtio_blk *vblk = q->queuedata; @@ -462,6 +487,8 @@ static int __devinit virtblk_probe(struct virtio_device *vdev) goto out_put_disk; } + blk_queue_abort_queue(q, virtblk_abort_queue); + q->queuedata = vblk; virtblk_name_format("vd", index, vblk->disk->disk_name, DISK_NAME_LEN); @@ -576,8 +603,6 @@ static void __devexit virtblk_remove(struct virtio_device *vdev) { struct virtio_blk *vblk = vdev->priv; int index = vblk->index; - struct virtblk_req *vbr; - unsigned long flags; /* Prevent config work handler from accessing the device. */ mutex_lock(&vblk->config_lock); @@ -591,15 +616,6 @@ static void __devexit virtblk_remove(struct virtio_device *vdev) flush_work(&vblk->config_work); - - /* Abort requests dispatched to driver. */ - spin_lock_irqsave(&vblk->lock, flags); - while ((vbr = virtqueue_detach_unused_buf(vblk->vq))) { - __blk_end_request_all(vbr->req, -EIO); - mempool_free(vbr, vblk->pool); - } - spin_unlock_irqrestore(&vblk->lock, flags); - blk_cleanup_queue(vblk->disk->queue); put_disk(vblk->disk); mempool_destroy(vblk->pool); -- 1.7.10.1 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html