Skip to content

Commit a9ba673

Browse files
FirstLoveLifeweiny2
authored andcommitted
nvdimm: virtio_pmem: serialize flush requests
Under heavy concurrent flush traffic, virtio-pmem can overflow its request virtqueue (req_vq): virtqueue_add_sgs() starts returning -ENOSPC and the driver logs "no free slots in the virtqueue". Shortly after that the device enters VIRTIO_CONFIG_S_NEEDS_RESET and flush requests fail with "virtio pmem device needs a reset". Serialize virtio_pmem_flush() with a per-device mutex so only one flush request is in-flight at a time. This prevents req_vq descriptor overflow under high concurrency. Reproducer (guest with virtio-pmem): - mkfs.ext4 -F /dev/pmem0 - mount -t ext4 -o dax,noatime /dev/pmem0 /mnt/bench - fio: ioengine=io_uring rw=randwrite bs=4k iodepth=64 numjobs=64 direct=1 fsync=1 runtime=30s time_based=1 - dmesg: "no free slots in the virtqueue" "virtio pmem device needs a reset" Fixes: 6e84200 ("virtio-pmem: Add virtio pmem driver") Signed-off-by: Li Chen <me@linux.beauty> Acked-by: Pankaj Gupta <pankaj.gupta.linux@gmail.com> Acked-by: Michael S. Tsirkin <mst@redhat.com> Link: https://patch.msgid.link/20260203021353.121091-1-me@linux.beauty Signed-off-by: Ira Weiny <ira.weiny@intel.com>
1 parent 9c0fc1d commit a9ba673

3 files changed

Lines changed: 7 additions & 1 deletion

File tree

drivers/nvdimm/nd_virtio.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ static int virtio_pmem_flush(struct nd_region *nd_region)
4444
unsigned long flags;
4545
int err, err1;
4646

47+
guard(mutex)(&vpmem->flush_lock);
48+
4749
/*
4850
* Don't bother to submit the request to the device if the device is
4951
* not activated.
@@ -53,7 +55,6 @@ static int virtio_pmem_flush(struct nd_region *nd_region)
5355
return -EIO;
5456
}
5557

56-
might_sleep();
5758
req_data = kmalloc(sizeof(*req_data), GFP_KERNEL);
5859
if (!req_data)
5960
return -ENOMEM;

drivers/nvdimm/virtio_pmem.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ static int virtio_pmem_probe(struct virtio_device *vdev)
6464
goto out_err;
6565
}
6666

67+
mutex_init(&vpmem->flush_lock);
6768
vpmem->vdev = vdev;
6869
vdev->priv = vpmem;
6970
err = init_vq(vpmem);

drivers/nvdimm/virtio_pmem.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <linux/module.h>
1414
#include <uapi/linux/virtio_pmem.h>
1515
#include <linux/libnvdimm.h>
16+
#include <linux/mutex.h>
1617
#include <linux/spinlock.h>
1718

1819
struct virtio_pmem_request {
@@ -35,6 +36,9 @@ struct virtio_pmem {
3536
/* Virtio pmem request queue */
3637
struct virtqueue *req_vq;
3738

39+
/* Serialize flush requests to the device. */
40+
struct mutex flush_lock;
41+
3842
/* nvdimm bus registers virtio pmem device */
3943
struct nvdimm_bus *nvdimm_bus;
4044
struct nvdimm_bus_descriptor nd_desc;

0 commit comments

Comments
 (0)