diff options
| author | John Levon <john.levon@nutanix.com> | 2025-06-25 20:30:09 +0100 |
|---|---|---|
| committer | Cédric Le Goater <clg@redhat.com> | 2025-06-26 08:55:38 +0200 |
| commit | 1a0c32a9daa39738fffc7de086845b2e54ae7034 (patch) | |
| tree | dee0ce2134639accf6d562d6c9b17b1d352ff2e8 /hw/vfio-user/device.c | |
| parent | 98a906d9e5827b18c51d7d7485be2f21f8900cc7 (diff) | |
| download | focaccia-qemu-1a0c32a9daa39738fffc7de086845b2e54ae7034.tar.gz focaccia-qemu-1a0c32a9daa39738fffc7de086845b2e54ae7034.zip | |
vfio-user: add coalesced posted writes
Add new message to send multiple writes to server in a single message. Prevents the outgoing queue from overflowing when a long latency operation is followed by a series of posted writes. Originally-by: John Johnson <john.g.johnson@oracle.com> Signed-off-by: Elena Ufimtseva <elena.ufimtseva@oracle.com> Signed-off-by: Jagannathan Raman <jag.raman@oracle.com> Signed-off-by: John Levon <john.levon@nutanix.com> Reviewed-by: Cédric Le Goater <clg@redhat.com> Link: https://lore.kernel.org/qemu-devel/20250625193012.2316242-18-john.levon@nutanix.com Signed-off-by: Cédric Le Goater <clg@redhat.com>
Diffstat (limited to 'hw/vfio-user/device.c')
| -rw-r--r-- | hw/vfio-user/device.c | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/hw/vfio-user/device.c b/hw/vfio-user/device.c index aa07eac330..0609a7dc25 100644 --- a/hw/vfio-user/device.c +++ b/hw/vfio-user/device.c @@ -9,6 +9,8 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "qemu/error-report.h" +#include "qemu/lockable.h" +#include "qemu/thread.h" #include "hw/vfio-user/device.h" #include "hw/vfio-user/trace.h" @@ -337,6 +339,7 @@ static int vfio_user_device_io_region_write(VFIODevice *vbasedev, uint8_t index, VFIOUserProxy *proxy = vbasedev->proxy; int size = sizeof(*msgp) + count; Error *local_err = NULL; + bool can_multi; int flags = 0; int ret; @@ -352,6 +355,43 @@ static int vfio_user_device_io_region_write(VFIODevice *vbasedev, uint8_t index, flags |= VFIO_USER_NO_REPLY; } + /* write eligible to be in a WRITE_MULTI msg ? */ + can_multi = (proxy->flags & VFIO_PROXY_USE_MULTI) && post && + count <= VFIO_USER_MULTI_DATA; + + /* + * This should be a rare case, so first check without the lock, + * if we're wrong, vfio_send_queued() will flush any posted writes + * we missed here + */ + if (proxy->wr_multi != NULL || + (proxy->num_outgoing > VFIO_USER_OUT_HIGH && can_multi)) { + + /* + * re-check with lock + * + * if already building a WRITE_MULTI msg, + * add this one if possible else flush pending before + * sending the current one + * + * else if outgoing queue is over the highwater, + * start a new WRITE_MULTI message + */ + WITH_QEMU_LOCK_GUARD(&proxy->lock) { + if (proxy->wr_multi != NULL) { + if (can_multi) { + vfio_user_add_multi(proxy, index, off, count, data); + return count; + } + vfio_user_flush_multi(proxy); + } else if (proxy->num_outgoing > VFIO_USER_OUT_HIGH && can_multi) { + vfio_user_create_multi(proxy); + vfio_user_add_multi(proxy, index, off, count, data); + return count; + } + } + } + msgp = g_malloc0(size); vfio_user_request_msg(&msgp->hdr, VFIO_USER_REGION_WRITE, size, flags); msgp->offset = off; |