Re: [PATCH v1 2/2] virtio-blk: mark disk dead on ERS permanent failure
From: Michael S. Tsirkin
Date: Thu Jul 30 2026 - 19:15:10 EST
On Fri, Jun 12, 2026 at 06:00:00PM +0800, Xixin Liu wrote:
> After ERS reports pci_channel_io_perm_failure, virtio-pci must ask the
> virtio driver to tear down the block device — not only mark virtqueues
> broken.
Can you tell me was this written with use of AI? I ask because not many
people go out of their way to put in unicode dashes. Next step is what
emojis? Let's not go there pls.
And if yes pls disclose that as per Documentation.
> Call the virtio driver shutdown hook from virtio-pci on
> perm_failure; virtio-blk implements shutdown with blk_mark_disk_dead().
> Fail new requests early in virtio_queue_rq when the disk is dead or
> virtqueues were removed during frozen reset_prepare.
>
> Signed-off-by: Xixin Liu <liuxixin@xxxxxxxxxx>
> ---
> drivers/block/virtio_blk.c | 39 +++++++++++++++++++++++++++++++++++++++
> drivers/virtio/virtio_pci_common.c | 10 +++++++++-
> 2 files changed, 48 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
> index 32bf3ba07a9d..4740ae91d5be 100644
> --- a/drivers/block/virtio_blk.c
> +++ b/drivers/block/virtio_blk.c
> @@ -435,6 +435,12 @@ static blk_status_t virtio_queue_rq(struct blk_mq_hw_ctx *hctx,
> blk_status_t status;
> int err;
>
> + /* Fail fast if ERS frozen tore down VQs or the disk was marked dead. */
> + if (unlikely(!disk_live(vblk->disk) || !vblk->vqs || !vblk->vdev)) {
> + blk_mq_start_request(req);
> + return BLK_STS_IOERR;
> + }
> +
Do we need this? virtqueue add will fail anyway.
> status = virtblk_prep_rq(hctx, vblk, req, vbr);
> if (unlikely(status))
> return status;
> @@ -1561,6 +1567,29 @@ static int virtblk_probe(struct virtio_device *vdev)
> return err;
> }
>
> +/* Stop I/O and mark the gendisk dead (ERS perm_failure or system shutdown). */
> +static void virtblk_shutdown(struct virtio_device *vdev)
> +{
> + struct virtio_blk *vblk = vdev->priv;
> + struct request_queue *q;
> + unsigned int memflags;
> +
> + if (!vblk || !vblk->disk)
> + return;
> +
> + flush_work(&vblk->config_work);
> + virtio_break_device(vdev);
why not break first?
> + q = vblk->disk->queue;
> + memflags = blk_mq_freeze_queue(q);
> + blk_mq_quiesce_queue_nowait(q);
> +
> + blk_mark_disk_dead(vblk->disk);
> +
> + blk_mq_unquiesce_queue(q);
> + blk_mq_unfreeze_queue(q, memflags);
> +}
> +
> static void virtblk_remove(struct virtio_device *vdev)
> {
> struct virtio_blk *vblk = vdev->priv;
> @@ -1684,6 +1713,7 @@ static struct virtio_driver virtio_blk = {
> .probe = virtblk_probe,
> .remove = virtblk_remove,
> .config_changed = virtblk_config_changed,
> + .shutdown = virtblk_shutdown,
> #ifdef CONFIG_PM_SLEEP
> .freeze = virtblk_freeze,
> .restore = virtblk_restore,
> diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
> index e2dda946e70e..924ceead436b 100644
> --- a/drivers/virtio/virtio_pci_common.c
> +++ b/drivers/virtio/virtio_pci_common.c
> @@ -845,7 +845,15 @@ static pci_ers_result_t virtio_pci_error_detected(struct pci_dev *pci_dev,
> case pci_channel_io_perm_failure:
> dev_warn(&pci_dev->dev,
> "permanent failure, disconnecting device\n");
> - virtio_break_device(&vp_dev->vdev);
> + {
> + struct virtio_driver *drv =
> + drv_to_virtio(vp_dev->vdev.dev.driver);
> +
> + if (drv && drv->shutdown)
> + drv->shutdown(&vp_dev->vdev);
> + else
> + virtio_break_device(&vp_dev->vdev);
> + }
> return PCI_ERS_RESULT_DISCONNECT;
> default:
> break;