linux/drivers/virtio
Yuan Yao 1acfe2c122 virtio_ring: fix avail_wrap_counter in virtqueue_add_packed
In current packed virtqueue implementation, the avail_wrap_counter won't
flip, in the case when the driver supplies a descriptor chain with a
length equals to the queue size; total_sg == vq->packed.vring.num.

Let’s assume the following situation:
vq->packed.vring.num=4
vq->packed.next_avail_idx: 1
vq->packed.avail_wrap_counter: 0

Then the driver adds a descriptor chain containing 4 descriptors.

We expect the following result with avail_wrap_counter flipped:
vq->packed.next_avail_idx: 1
vq->packed.avail_wrap_counter: 1

But, the current implementation gives the following result:
vq->packed.next_avail_idx: 1
vq->packed.avail_wrap_counter: 0

To reproduce the bug, you can set a packed queue size as small as
possible, so that the driver is more likely to provide a descriptor
chain with a length equal to the packed queue size. For example, in
qemu run following commands:
sudo qemu-system-x86_64 \
-enable-kvm \
-nographic \
-kernel "path/to/kernel_image" \
-m 1G \
-drive file="path/to/rootfs",if=none,id=disk \
-device virtio-blk,drive=disk \
-drive file="path/to/disk_image",if=none,id=rwdisk \
-device virtio-blk,drive=rwdisk,packed=on,queue-size=4,\
indirect_desc=off \
-append "console=ttyS0 root=/dev/vda rw init=/bin/bash"

Inside the VM, create a directory and mount the rwdisk device on it. The
rwdisk will hang and mount operation will not complete.

This commit fixes the wrap counter error by flipping the
packed.avail_wrap_counter, when start of descriptor chain equals to the
end of descriptor chain (head == i).

Fixes: 1ce9e6055f ("virtio_ring: introduce packed ring support")
Signed-off-by: Yuan Yao <yuanyaogoog@chromium.org>
Message-Id: <20230808051110.3492693-1-yuanyaogoog@chromium.org>
Acked-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2023-09-03 18:10:24 -04:00
..
Kconfig virtio: fatures, fixes 2022-08-12 09:50:34 -07:00
Makefile virtio: replace restricted mem access flag with callback 2022-08-01 07:42:49 +02:00
virtio_anchor.c virtio: replace restricted mem access flag with callback 2022-08-01 07:42:49 +02:00
virtio_balloon.c mm, treewide: redefine MAX_ORDER sanely 2023-04-05 19:42:46 -07:00
virtio_dma_buf.c dma-buf: move dma-buf symbols into the DMA_BUF module namespace 2021-10-25 14:53:08 +02:00
virtio_input.c virtio: wrap config->reset calls 2022-01-14 18:50:52 -05:00
virtio_mem.c virtio-mem: check if the config changed before fake offlining memory 2023-08-10 15:51:46 -04:00
virtio_mmio.c virtio-mmio: don't break lifecycle of vm_dev 2023-08-10 15:24:27 -04:00
virtio_pci_common.c virtio-pci: Fix legacy device flag setting error in probe 2023-08-10 15:24:28 -04:00
virtio_pci_common.h virtio_pci: Optimize virtio_pci_device structure size 2023-06-27 10:47:08 -04:00
virtio_pci_legacy_dev.c virtio/virtio_pci_legacy_dev: ensure the correct return value 2022-01-14 18:50:53 -05:00
virtio_pci_legacy.c virtio-pci: Fix legacy device flag setting error in probe 2023-08-10 15:24:28 -04:00
virtio_pci_modern_dev.c virtio: allow caller to override device DMA mask in vp_modern 2023-06-27 10:47:08 -04:00
virtio_pci_modern.c virtio: add VIRTIO_F_NOTIFICATION_DATA feature support 2023-04-21 03:02:35 -04:00
virtio_ring.c virtio_ring: fix avail_wrap_counter in virtqueue_add_packed 2023-09-03 18:10:24 -04:00
virtio_vdpa.c virtio_vdpa: build affinity masks conditionally 2023-09-03 18:10:24 -04:00
virtio.c driver core: make struct bus_type.uevent() take a const * 2023-01-27 13:45:52 +01:00