linux/drivers/virtio
Jinqian Yang 0d0eff39ce virtio_ring: fix infinite loop in virtnet_poll_cleantx when device is broken
virtnet_poll_cleantx() contains a do-while loop that cleans up
transmitted TX buffers and calls virtqueue_enable_cb_delayed() to check
whether more buffers need processing. When the virtio backend stops
responding during guest reboot, used->idx is never updated, so
virtqueue_enable_cb_delayed() always returns false and the loop never
terminates. Then it will block reboot process, and the guest will hang.

The problem occurs during guest reboot under network traffic:

  1. kernel_restart() -> device_shutdown() traverses the device list
  2. virtio_dev_shutdown() calls virtio_break_device() which sets
     vq->broken = true
  3. virtio_dev_shutdown() then calls virtio_synchronize_cbs() to wait
     for in-flight callbacks to complete
  4. A virtio interrupt fires, softirq is deferred to ksoftirqd which
     calls net_rx_action() -> virtnet_poll() -> virtnet_poll_cleantx()
  5. virtnet_poll_cleantx() enters the do-while loop and never exits
     because the QEMU backend has stopped updating used->idx, despite
     vq->broken having been set to true in step 2.

Since the loop runs inside ksoftirqd (a SCHED_OTHER kthread), it is
visible to the scheduler and does not trigger a hard lockup. However,
the kthread never leaves the loop, so RCU detects it as a CPU stall
and reports it periodically. Meanwhile, the reboot process remains
blocked in device_shutdown() because virtio_dev_shutdown() cannot
complete its synchronization step, and the guest hangs permanently.

This can be reproduced on a guest with a virtio-net device: run iperf3
traffic in the guest, then trigger reboot. The reboot occasionally hangs
permanently with RCU stall on ksoftirqd.

Observed on ARM64 KVM guest:

  CPU#1 RCU stall (ksoftirqd/1), repeated periodically:
    virtqueue_enable_cb_delayed_split <- virtnet_poll <- __napi_poll <-
    net_rx_action <- handle_softirqs <- run_ksoftirqd <-
    smpboot_thread_fn <- kthread

Fix by adding a vq->broken check in virtqueue_enable_cb_delayed(), so
that the loop exits immediately when the device is broken, allowing
the device shutdown to proceed.

Signed-off-by: Jinqian Yang <yangjinqian1@huawei.com>
Reviewed-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260716115940.394832-1-yangjinqian1@huawei.com>
2026-08-19 06:38:47 -04:00
..
Kconfig mm: rename CONFIG_MEMORY_BALLOON -> CONFIG_BALLOON 2026-01-31 14:22:36 -08:00
Makefile virtio_rtc: Add RTC class driver 2025-05-27 10:27:54 -04:00
virtio_anchor.c virtio: replace restricted mem access flag with callback 2022-08-01 07:42:49 +02:00
virtio_balloon.c virtio_balloon: warn on failed buffer add in stats_handle_request() 2026-08-19 06:38:44 -04:00
virtio_debug.c virtio: clean up features qword/dword terms 2025-11-27 02:03:07 -05:00
virtio_dma_buf.c virtio: fix article before virtio in dma-buf comment 2026-08-19 06:38:47 -04:00
virtio_input.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
virtio_mem.c virtio_mem: fix typo in comment 2026-08-19 06:38:47 -04:00
virtio_mmio.c virtio-mmio: add support for transport version 3 2026-08-19 06:38:43 -04:00
virtio_pci_admin_legacy_io.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
virtio_pci_common.c virtio_pci: fix wrong queue index for admin vq in intx path 2026-08-19 06:38:45 -04:00
virtio_pci_common.h VFIO updates for v6.13 2024-11-27 12:57:03 -08:00
virtio_pci_legacy_dev.c virtio_pci: Fix misleading comment for queue vector 2025-08-26 03:38:10 -04:00
virtio_pci_legacy.c virtio: rename find_vqs_info() op to find_vqs() 2024-07-17 05:20:57 -04:00
virtio_pci_modern_dev.c virtio: clean up features qword/dword terms 2025-11-27 02:03:07 -05:00
virtio_pci_modern.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
virtio_ring.c virtio_ring: fix infinite loop in virtnet_poll_cleantx when device is broken 2026-08-19 06:38:47 -04:00
virtio_rtc_arm.c virtio_rtc: Add Arm Generic Timer cross-timestamping 2025-05-27 10:27:54 -04:00
virtio_rtc_class.c virtio_rtc: Add RTC class driver 2025-05-27 10:27:54 -04:00
virtio_rtc_driver.c virtio: rtc: time out alarm requests 2026-08-19 06:38:47 -04:00
virtio_rtc_internal.h virtio_rtc: Add RTC class driver 2025-05-27 10:27:54 -04:00
virtio_rtc_ptp.c virtio_rtc: Use provided clock ID for history snapshot 2026-06-04 11:04:17 +02:00
virtio_vdpa.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
virtio.c virtio: add virtio_device_shutdown() helper 2026-08-19 06:38:44 -04:00