This flag should be set by a virtio transport driver, when it was notified about a lost device, before the remove callback of a backend driver is triggered. A backend driver can test this flag in order to perform specific actions that might be appropriate wrt the device loss. In case of a device loss further request queueing should be prevented by setting appropriate queue flags prior to invoking del_gendisk(). Blocking of request queueing leads to appropriate I/O errors when data are tried to be synched. Trying to synch data to a lost block device doesn't make too much sense. Calling blk_cleanup_queue() when the device_lost flag is set due to a disappeared device. It avoid hangs due to incomplete requests (e.g. in-flight requests). Such requests must be considered as lost. Signed-off-by: Heinz Graalfs <graalfs@xxxxxxxxxxxxxxxxxx> Acked-by: Cornelia Huck <cornelia.huck@xxxxxxxxxx> --- drivers/block/virtio_blk.c | 14 +++++++++++++- include/linux/virtio.h | 2 ++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 2d43be4..e5b4947 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -876,14 +876,26 @@ static void virtblk_remove(struct virtio_device *vdev) struct virtio_blk *vblk = vdev->priv; int index = vblk->index; int refc; + int device_lost; + unsigned long flags; /* Prevent config work handler from accessing the device. */ mutex_lock(&vblk->config_lock); vblk->config_enable = false; mutex_unlock(&vblk->config_lock); + device_lost = atomic_read(&vdev->device_lost); + if (device_lost) { + spin_lock_irqsave(vblk->disk->queue->queue_lock, flags); + queue_flag_set(QUEUE_FLAG_DYING, vblk->disk->queue); + queue_flag_set(QUEUE_FLAG_NOMERGES, vblk->disk->queue); + queue_flag_set(QUEUE_FLAG_NOXMERGES, vblk->disk->queue); + spin_unlock_irqrestore(vblk->disk->queue->queue_lock, flags); + } + del_gendisk(vblk->disk); - blk_cleanup_queue(vblk->disk->queue); + if (!device_lost) + blk_cleanup_queue(vblk->disk->queue); /* Stop all the virtqueues. */ vdev->config->reset(vdev); diff --git a/include/linux/virtio.h b/include/linux/virtio.h index f15f6e7..c18db21 100644 --- a/include/linux/virtio.h +++ b/include/linux/virtio.h @@ -87,6 +87,7 @@ bool virtqueue_is_broken(struct virtqueue *vq); * @vringh_config: configuration ops for host vrings. * @vqs: the list of virtqueues for this device. * @features: the features supported by both driver and device. + * @device_lost: to flag a device loss. * @priv: private pointer for the driver's use. */ struct virtio_device { @@ -98,6 +99,7 @@ struct virtio_device { struct list_head vqs; /* Note that this is a Linux set_bit-style bitmap. */ unsigned long features[1]; + atomic_t device_lost; void *priv; }; -- 1.8.3.1 _______________________________________________ Virtualization mailing list Virtualization@xxxxxxxxxxxxxxxxxxxxxxxxxx https://lists.linuxfoundation.org/mailman/listinfo/virtualization