* [PATCH 1/8] vhost-user: kick via event_notifier_set()
2026-10-22 13:47 [PATCH 0/8] vhost-user: another try at supporting any POSIX system Tim Pambor
@ 2026-10-22 13:47 ` Tim Pambor
2026-10-29 11:43 ` Stefano Garzarella
2026-10-22 13:47 ` [PATCH 2/8] libvhost-user: self-kick through a library-owned notifier Tim Pambor
` (7 subsequent siblings)
8 siblings, 1 reply; 23+ messages in thread
From: Tim Pambor @ 2026-10-22 13:47 UTC (permalink / raw)
To: qemu-devel
Cc: Michael S. Tsirkin, Stefano Garzarella, Daniel P. Berrangé,
Marc-André Lureau, Paolo Bonzini, Kevin Wolf, Hanna Reitz,
Jason Wang, Pierrick Bouvier, qemu-block, Raphael Norwitz,
Brad Smith, Tim Pambor
vhost-user injects a kick by writing to the fd it has just passed to the
back-end. With an eventfd that fd is writable, but when pipes are used
it is the read end and the write fails.
Instead, kick via event_notifier_set() on the queue's host notifier,
which writes to the correct end in both cases.
Signed-off-by: Tim Pambor <timpambor@gmail.com>
---
hw/virtio/vhost-user.c | 11 ++---------
1 file changed, 2 insertions(+), 9 deletions(-)
diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index 65889b0776..b817b15d0b 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -1527,16 +1527,9 @@ static int vhost_user_set_vring_kick(struct vhost_dev *dev,
* receiving a kick. The spec suggests this to improve compatibility.
*/
if (file->fd != -1) {
- uint64_t val = 1;
- ssize_t nwritten;
+ VirtQueue *vq = virtio_get_queue(dev->vdev, file->index);
- do {
- nwritten = write(file->fd, &val, sizeof(val));
- } while (nwritten < 0 && errno == EINTR);
-
- if (nwritten < 0 && errno != EAGAIN /* back-end can already read */) {
- return -errno;
- }
+ return event_notifier_set(virtio_queue_get_host_notifier(vq));
}
return 0;
--
2.55.0
^ permalink raw reply related [flat|nested] 23+ messages in thread* Re: [PATCH 1/8] vhost-user: kick via event_notifier_set()
2026-10-22 13:47 ` [PATCH 1/8] vhost-user: kick via event_notifier_set() Tim Pambor
@ 2026-10-29 11:43 ` Stefano Garzarella
0 siblings, 0 replies; 23+ messages in thread
From: Stefano Garzarella @ 2026-10-29 11:43 UTC (permalink / raw)
To: Tim Pambor
Cc: qemu-devel, Michael S. Tsirkin, Daniel P. Berrangé,
Marc-André Lureau, Paolo Bonzini, Kevin Wolf, Hanna Reitz,
Jason Wang, Pierrick Bouvier, qemu-block, Raphael Norwitz,
Brad Smith
On Thu, Oct 22, 2026 at 03:47:22PM +0200, Tim Pambor wrote:
> vhost-user injects a kick by writing to the fd it has just passed to the
> back-end. With an eventfd that fd is writable, but when pipes are used
> it is the read end and the write fails.
>
> Instead, kick via event_notifier_set() on the queue's host notifier,
> which writes to the correct end in both cases.
>
> Signed-off-by: Tim Pambor <timpambor@gmail.com>
> ---
> hw/virtio/vhost-user.c | 11 ++---------
> 1 file changed, 2 insertions(+), 9 deletions(-)
>
> diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
> index 65889b0776..b817b15d0b 100644
> --- a/hw/virtio/vhost-user.c
> +++ b/hw/virtio/vhost-user.c
> @@ -1527,16 +1527,9 @@ static int vhost_user_set_vring_kick(struct vhost_dev *dev,
> * receiving a kick. The spec suggests this to improve compatibility.
> */
> if (file->fd != -1) {
> - uint64_t val = 1;
> - ssize_t nwritten;
> + VirtQueue *vq = virtio_get_queue(dev->vdev, file->index);
>
> - do {
> - nwritten = write(file->fd, &val, sizeof(val));
> - } while (nwritten < 0 && errno == EINTR);
> -
> - if (nwritten < 0 && errno != EAGAIN /* back-end can already read */) {
> - return -errno;
> - }
Please add a comment here explaining why we are not using file->fd (like
you correctly did in the commit message), or update the comment before
this block.
Also, should we add an assert to check that file->fd is equal to
event_notifier_get_fd() ?
The rest LGTM.
Stefano
> + return event_notifier_set(virtio_queue_get_host_notifier(vq));
> }
>
> return 0;
>
> --
> 2.55.0
>
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH 2/8] libvhost-user: self-kick through a library-owned notifier
2026-10-22 13:47 [PATCH 0/8] vhost-user: another try at supporting any POSIX system Tim Pambor
2026-10-22 13:47 ` [PATCH 1/8] vhost-user: kick via event_notifier_set() Tim Pambor
@ 2026-10-22 13:47 ` Tim Pambor
2026-10-29 11:43 ` Stefano Garzarella
2026-10-22 13:47 ` [PATCH 3/8] io/channel-socket: only clear O_NONBLOCK on received fds if set Tim Pambor
` (6 subsequent siblings)
8 siblings, 1 reply; 23+ messages in thread
From: Tim Pambor @ 2026-10-22 13:47 UTC (permalink / raw)
To: qemu-devel
Cc: Michael S. Tsirkin, Stefano Garzarella, Daniel P. Berrangé,
Marc-André Lureau, Paolo Bonzini, Kevin Wolf, Hanna Reitz,
Jason Wang, Pierrick Bouvier, qemu-block, Raphael Norwitz,
Brad Smith, Tim Pambor
When a ring is started, it may already hold requests: ones the driver
queued while the back-end was away and ones the previous instance left
in flight. The spec says front-ends SHOULD send a kick after
SET_VRING_KICK and back-ends SHOULD NOT rely on it, so libvhost-user
kicks itself by writing to the kick fd it has received from the
front-end. With an eventfd that fd is writable, but when pipes are used
it is the read end and the write fails.
Replace it with a notifier the library owns. vu_init() creates it, the
embedder watches its read end through set_watch() like a kick fd, and
the library writes it when a started ring has available entries or
in-flight requests to resubmit. The watch callback drains it and runs
the handler of every queue flagged kick_pending. This way the handler
still runs from the event loop after the reply to SET_VRING_KICK has
gone out, as with the kick-fd self-kick.
Signed-off-by: Tim Pambor <timpambor@gmail.com>
---
subprojects/libvhost-user/libvhost-user.c | 145 +++++++++++++++++++++++++++---
subprojects/libvhost-user/libvhost-user.h | 10 +++
2 files changed, 141 insertions(+), 14 deletions(-)
diff --git a/subprojects/libvhost-user/libvhost-user.c b/subprojects/libvhost-user/libvhost-user.c
index 2fed792e85..e323e32cab 100644
--- a/subprojects/libvhost-user/libvhost-user.c
+++ b/subprojects/libvhost-user/libvhost-user.c
@@ -23,6 +23,7 @@
#include <unistd.h>
#include <stdarg.h>
#include <errno.h>
+#include <fcntl.h>
#include <string.h>
#include <assert.h>
#include <inttypes.h>
@@ -40,7 +41,6 @@
#if defined(__linux__)
#include <sys/syscall.h>
-#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/vhost.h>
#include <sys/vfs.h>
@@ -1305,6 +1305,7 @@ vu_get_vring_base_exec(VuDev *dev, VhostUserMsg *vmsg)
vmsg->size = sizeof(vmsg->payload.state);
dev->vq[index].started = false;
+ dev->vq[index].kick_pending = false;
if (dev->iface->queue_set_started) {
dev->iface->queue_set_started(dev, index, false);
}
@@ -1440,6 +1441,121 @@ vu_check_queue_inflights(VuDev *dev, VuVirtq *vq)
return 0;
}
+static bool
+vu_self_kick_init(VuDev *dev)
+{
+#ifdef CONFIG_EVENTFD
+ int fd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
+
+ if (fd < 0) {
+ return false;
+ }
+
+ dev->self_kick_rfd = dev->self_kick_wfd = fd;
+#else
+ int fds[2];
+ int i;
+
+ if (pipe(fds) < 0) {
+ return false;
+ }
+
+ for (i = 0; i < 2; i++) {
+ int flags = fcntl(fds[i], F_GETFL);
+
+ if (flags < 0 ||
+ fcntl(fds[i], F_SETFL, flags | O_NONBLOCK) < 0 ||
+ fcntl(fds[i], F_SETFD, FD_CLOEXEC) < 0) {
+ close(fds[0]);
+ close(fds[1]);
+ return false;
+ }
+ }
+
+ dev->self_kick_rfd = fds[0];
+ dev->self_kick_wfd = fds[1];
+#endif
+
+ return true;
+}
+
+static void
+vu_self_kick_deinit(VuDev *dev)
+{
+ if (dev->self_kick_watched) {
+ dev->remove_watch(dev, dev->self_kick_rfd);
+ dev->self_kick_watched = false;
+ }
+
+ if (dev->self_kick_wfd != -1 && dev->self_kick_wfd != dev->self_kick_rfd) {
+ close(dev->self_kick_wfd);
+ }
+
+ if (dev->self_kick_rfd != -1) {
+ close(dev->self_kick_rfd);
+ }
+
+ dev->self_kick_rfd = dev->self_kick_wfd = -1;
+}
+
+static void
+vu_self_kick_cb(VuDev *dev, int condition, void *data)
+{
+ eventfd_t value;
+ unsigned int i;
+
+ while (eventfd_read(dev->self_kick_rfd, &value) == 0) {
+ continue;
+ }
+
+ for (i = 0; i < dev->max_queues; i++) {
+ VuVirtq *vq = &dev->vq[i];
+
+ if (!vq->kick_pending) {
+ continue;
+ }
+ vq->kick_pending = false;
+
+ DPRINT("Running handler for pending requests on vq: %u\n", i);
+ if (vq->handler) {
+ vq->handler(dev, i);
+ }
+ }
+}
+
+static void
+vu_schedule_pending_requests(VuDev *dev, int index)
+{
+ VuVirtq *vq = &dev->vq[index];
+ int ret;
+
+ if (!vq->handler) {
+ return;
+ }
+
+ if (vq->resubmit_num == 0 && vu_queue_empty(dev, vq)) {
+ return;
+ }
+
+ DPRINT("Scheduling pending requests on vq: %d (resubmit: %d)\n",
+ index, vq->resubmit_num);
+ vq->kick_pending = true;
+
+ if (!dev->self_kick_watched) {
+ dev->set_watch(dev, dev->self_kick_rfd, VU_WATCH_IN,
+ vu_self_kick_cb, NULL);
+ dev->self_kick_watched = true;
+ }
+
+ ret = eventfd_write(dev->self_kick_wfd, 1);
+
+ /* EAGAIN: the notifier is already pending, which is all we need */
+ if (ret < 0 && errno != EAGAIN) {
+ vu_panic(dev, "Failed to kick ourselves for vq: %d: %s\n",
+ index, strerror(errno));
+ }
+}
+
static bool
vu_set_vring_kick_exec(VuDev *dev, VhostUserMsg *vmsg)
{
@@ -1478,19 +1594,7 @@ vu_set_vring_kick_exec(VuDev *dev, VhostUserMsg *vmsg)
vu_panic(dev, "Failed to check inflights for vq: %d\n", index);
}
- /* Inject a kick to look for available vq buffers */
- if (dev->vq[index].kick_fd != -1) {
- int ret;
-
- do {
- ret = eventfd_write(dev->vq[index].kick_fd, 1);
- } while (ret != 0 && errno == EINTR);
-
- if (ret != 0 && errno != EAGAIN /* already readable */) {
- vu_panic(dev, "Failed to inject kick during SET_VRING_KICK "
- "on vq: %d with error: %m\n", index);
- }
- }
+ vu_schedule_pending_requests(dev, index);
return false;
}
@@ -1509,6 +1613,10 @@ void vu_set_queue_handler(VuDev *dev, VuVirtq *vq,
dev->remove_watch(dev, vq->kick_fd);
}
}
+
+ if (handler && vq->started) {
+ vu_schedule_pending_requests(dev, qidx);
+ }
}
bool vu_set_queue_host_notifier(VuDev *dev, VuVirtq *vq, int fd,
@@ -2379,6 +2487,7 @@ vu_deinit(VuDev *dev)
}
vu_close_log(dev);
+ vu_self_kick_deinit(dev);
if (dev->backend_fd != -1) {
close(dev->backend_fd);
dev->backend_fd = -1;
@@ -2426,10 +2535,17 @@ vu_init(VuDev *dev,
pthread_mutex_init(&dev->backend_mutex, NULL);
dev->backend_fd = -1;
dev->max_queues = max_queues;
+ dev->self_kick_rfd = dev->self_kick_wfd = -1;
+
+ if (!vu_self_kick_init(dev)) {
+ DPRINT("%s: failed to create the self-kick notifier\n", __func__);
+ return false;
+ }
dev->regions = malloc(VHOST_USER_MAX_RAM_SLOTS * sizeof(dev->regions[0]));
if (!dev->regions) {
DPRINT("%s: failed to malloc mem regions\n", __func__);
+ vu_self_kick_deinit(dev);
return false;
}
@@ -2438,6 +2554,7 @@ vu_init(VuDev *dev,
DPRINT("%s: failed to malloc virtqueues\n", __func__);
free(dev->regions);
dev->regions = NULL;
+ vu_self_kick_deinit(dev);
return false;
}
diff --git a/subprojects/libvhost-user/libvhost-user.h b/subprojects/libvhost-user/libvhost-user.h
index a534d70771..ddd5cbb90e 100644
--- a/subprojects/libvhost-user/libvhost-user.h
+++ b/subprojects/libvhost-user/libvhost-user.h
@@ -392,6 +392,7 @@ typedef struct VuVirtq {
int err_fd;
unsigned int enable;
bool started;
+ bool kick_pending;
/* Guest addresses of our ring */
struct vhost_vring_addr vra;
@@ -471,6 +472,15 @@ struct VuDev {
/* Postcopy data */
int postcopy_ufd;
bool postcopy_listening;
+
+ /*
+ * Notifier owned by the library, used to run queue handlers from the
+ * event loop when a ring is started with requests already pending.
+ * Either the same eventfd on both sides or the two ends of a pipe.
+ */
+ int self_kick_rfd;
+ int self_kick_wfd;
+ bool self_kick_watched;
};
typedef struct VuVirtqElement {
--
2.55.0
^ permalink raw reply related [flat|nested] 23+ messages in thread* Re: [PATCH 2/8] libvhost-user: self-kick through a library-owned notifier
2026-10-22 13:47 ` [PATCH 2/8] libvhost-user: self-kick through a library-owned notifier Tim Pambor
@ 2026-10-29 11:43 ` Stefano Garzarella
0 siblings, 0 replies; 23+ messages in thread
From: Stefano Garzarella @ 2026-10-29 11:43 UTC (permalink / raw)
To: Tim Pambor
Cc: qemu-devel, Michael S. Tsirkin, Daniel P. Berrangé,
Marc-André Lureau, Paolo Bonzini, Kevin Wolf, Hanna Reitz,
Jason Wang, Pierrick Bouvier, qemu-block, Raphael Norwitz,
Brad Smith
On Thu, Oct 22, 2026 at 03:47:23PM +0200, Tim Pambor wrote:
> When a ring is started, it may already hold requests: ones the driver
> queued while the back-end was away and ones the previous instance left
> in flight. The spec says front-ends SHOULD send a kick after
> SET_VRING_KICK and back-ends SHOULD NOT rely on it, so libvhost-user
> kicks itself by writing to the kick fd it has received from the
> front-end. With an eventfd that fd is writable, but when pipes are used
> it is the read end and the write fails.
This was something we added to clarify the spec, not sure if it's worth
to add all of this code for something like that.
That said, what about only setting kick_pending in
vu_set_vring_kick_exec(), and running the handler of the pending queues
at the end of vu_dispatch(), after the reply is sent?
>
> Replace it with a notifier the library owns. vu_init() creates it, the
> embedder watches its read end through set_watch() like a kick fd, and
> the library writes it when a started ring has available entries or
> in-flight requests to resubmit. The watch callback drains it and runs
> the handler of every queue flagged kick_pending. This way the handler
> still runs from the event loop after the reply to SET_VRING_KICK has
> gone out, as with the kick-fd self-kick.
>
> Signed-off-by: Tim Pambor <timpambor@gmail.com>
> ---
> subprojects/libvhost-user/libvhost-user.c | 145 +++++++++++++++++++++++++++---
> subprojects/libvhost-user/libvhost-user.h | 10 +++
> 2 files changed, 141 insertions(+), 14 deletions(-)
>
> diff --git a/subprojects/libvhost-user/libvhost-user.c b/subprojects/libvhost-user/libvhost-user.c
> index 2fed792e85..e323e32cab 100644
> --- a/subprojects/libvhost-user/libvhost-user.c
> +++ b/subprojects/libvhost-user/libvhost-user.c
> @@ -23,6 +23,7 @@
> #include <unistd.h>
> #include <stdarg.h>
> #include <errno.h>
> +#include <fcntl.h>
> #include <string.h>
> #include <assert.h>
> #include <inttypes.h>
> @@ -40,7 +41,6 @@
>
> #if defined(__linux__)
> #include <sys/syscall.h>
> -#include <fcntl.h>
> #include <sys/ioctl.h>
> #include <linux/vhost.h>
> #include <sys/vfs.h>
> @@ -1305,6 +1305,7 @@ vu_get_vring_base_exec(VuDev *dev, VhostUserMsg *vmsg)
> vmsg->size = sizeof(vmsg->payload.state);
>
> dev->vq[index].started = false;
> + dev->vq[index].kick_pending = false;
> if (dev->iface->queue_set_started) {
> dev->iface->queue_set_started(dev, index, false);
> }
> @@ -1440,6 +1441,121 @@ vu_check_queue_inflights(VuDev *dev, VuVirtq *vq)
> return 0;
> }
>
> +static bool
> +vu_self_kick_init(VuDev *dev)
> +{
> +#ifdef CONFIG_EVENTFD
Can you check if CONFIG_EVENTFD is defined when building libvhost-user?
IIRC I used it, but now I'm thinking if we really have it defined.
Thanks,
Stefano
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH 3/8] io/channel-socket: only clear O_NONBLOCK on received fds if set
2026-10-22 13:47 [PATCH 0/8] vhost-user: another try at supporting any POSIX system Tim Pambor
2026-10-22 13:47 ` [PATCH 1/8] vhost-user: kick via event_notifier_set() Tim Pambor
2026-10-22 13:47 ` [PATCH 2/8] libvhost-user: self-kick through a library-owned notifier Tim Pambor
@ 2026-10-22 13:47 ` Tim Pambor
2026-10-26 11:29 ` Daniel P. Berrangé
2026-10-22 13:47 ` [PATCH 4/8] chardev/char-socket: detect peer close portably Tim Pambor
` (5 subsequent siblings)
8 siblings, 1 reply; 23+ messages in thread
From: Tim Pambor @ 2026-10-22 13:47 UTC (permalink / raw)
To: qemu-devel
Cc: Michael S. Tsirkin, Stefano Garzarella, Daniel P. Berrangé,
Marc-André Lureau, Paolo Bonzini, Kevin Wolf, Hanna Reitz,
Jason Wang, Pierrick Bouvier, qemu-block, Raphael Norwitz,
Brad Smith, Tim Pambor
After receiving descriptors with SCM_RIGHTS the socket channel resets
O_NONBLOCK on each of them with fcntl(F_SETFL). macOS rejects F_SETFL
on POSIX shared memory descriptors, so every message carrying such a
descriptor caused the connection to drop. Those descriptors are passed
in blocking mode anyway, so there is nothing to change on them. Query
the flags with F_GETFL first and only issue F_SETFL when O_NONBLOCK is
actually set.
Signed-off-by: Tim Pambor <timpambor@gmail.com>
---
io/channel-socket.c | 19 +++++++++++++++++--
1 file changed, 17 insertions(+), 2 deletions(-)
diff --git a/io/channel-socket.c b/io/channel-socket.c
index 7920cee639..1785fd5bfe 100644
--- a/io/channel-socket.c
+++ b/io/channel-socket.c
@@ -520,8 +520,23 @@ static bool qio_channel_handle_fds(int *fds, size_t nfds,
}
if (!preserve_blocking) {
- /* O_NONBLOCK is preserved across SCM_RIGHTS so reset it */
- if (!qemu_set_blocking(*fd, true, errp)) {
+ /*
+ * O_NONBLOCK is preserved across SCM_RIGHTS so reset it.
+ *
+ * Some descriptors reject F_SETFL outright, e.g. POSIX
+ * shared memory on macOS. They are passed in blocking
+ * mode anyway, so only touch descriptors that have it set.
+ */
+ int flags = fcntl(*fd, F_GETFL);
+
+ if (flags < 0) {
+ error_setg_errno(errp, errno,
+ "Can't get file descriptor %d flags", *fd);
+ return false;
+ }
+
+ if ((flags & O_NONBLOCK) &&
+ !qemu_set_blocking(*fd, true, errp)) {
return false;
}
}
--
2.55.0
^ permalink raw reply related [flat|nested] 23+ messages in thread* Re: [PATCH 3/8] io/channel-socket: only clear O_NONBLOCK on received fds if set
2026-10-22 13:47 ` [PATCH 3/8] io/channel-socket: only clear O_NONBLOCK on received fds if set Tim Pambor
@ 2026-10-26 11:29 ` Daniel P. Berrangé
0 siblings, 0 replies; 23+ messages in thread
From: Daniel P. Berrangé @ 2026-10-26 11:29 UTC (permalink / raw)
To: Tim Pambor
Cc: qemu-devel, Michael S. Tsirkin, Stefano Garzarella,
Marc-André Lureau, Paolo Bonzini, Kevin Wolf, Hanna Reitz,
Jason Wang, Pierrick Bouvier, qemu-block, Raphael Norwitz,
Brad Smith
On Thu, Oct 22, 2026 at 03:47:24PM +0200, Tim Pambor wrote:
> After receiving descriptors with SCM_RIGHTS the socket channel resets
> O_NONBLOCK on each of them with fcntl(F_SETFL). macOS rejects F_SETFL
> on POSIX shared memory descriptors, so every message carrying such a
> descriptor caused the connection to drop. Those descriptors are passed
> in blocking mode anyway, so there is nothing to change on them. Query
> the flags with F_GETFL first and only issue F_SETFL when O_NONBLOCK is
> actually set.
>
> Signed-off-by: Tim Pambor <timpambor@gmail.com>
> ---
> io/channel-socket.c | 19 +++++++++++++++++--
> 1 file changed, 17 insertions(+), 2 deletions(-)
>
> diff --git a/io/channel-socket.c b/io/channel-socket.c
> index 7920cee639..1785fd5bfe 100644
> --- a/io/channel-socket.c
> +++ b/io/channel-socket.c
> @@ -520,8 +520,23 @@ static bool qio_channel_handle_fds(int *fds, size_t nfds,
> }
>
> if (!preserve_blocking) {
> - /* O_NONBLOCK is preserved across SCM_RIGHTS so reset it */
> - if (!qemu_set_blocking(*fd, true, errp)) {
> + /*
> + * O_NONBLOCK is preserved across SCM_RIGHTS so reset it.
> + *
> + * Some descriptors reject F_SETFL outright, e.g. POSIX
> + * shared memory on macOS. They are passed in blocking
> + * mode anyway, so only touch descriptors that have it set.
> + */
> + int flags = fcntl(*fd, F_GETFL);
> +
> + if (flags < 0) {
> + error_setg_errno(errp, errno,
> + "Can't get file descriptor %d flags", *fd);
> + return false;
> + }
> +
> + if ((flags & O_NONBLOCK) &&
> + !qemu_set_blocking(*fd, true, errp)) {
I'd be inclined to put this logic in qemu_set_blocking itself
so that it does the right thing for all possible callers.
At that point we might as well get rid of the use of
g_unix_set_fd_nonblocking in that function and directly call
fcntl so we avoid the duplicate F_GETFL calls, eg something more
like:
int flags, newflags;
flag = fcntl(fd, F_GETFL);
if (flags < 0) {
error_setg_errno(....)
return -1;
}
if (nonblock)
newflags = flags | O_NONBLOCK;
else
newflags = flags & ~O_NONBLOCK;
if (newflags != flags &&
fcntl(fd, F_SETFL, newflags) < 0) {
error_setg_errno(...);
return -1;
}
With regards,
Daniel
--
|: https://berrange.com ~~ https://hachyderm.io/@berrange :|
|: https://libvirt.org ~~ https://entangle-photo.org :|
|: https://pixelfed.art/berrange ~~ https://fstop138.berrange.com :|
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH 4/8] chardev/char-socket: detect peer close portably
2026-10-22 13:47 [PATCH 0/8] vhost-user: another try at supporting any POSIX system Tim Pambor
` (2 preceding siblings ...)
2026-10-22 13:47 ` [PATCH 3/8] io/channel-socket: only clear O_NONBLOCK on received fds if set Tim Pambor
@ 2026-10-22 13:47 ` Tim Pambor
2026-10-22 13:47 ` [PATCH 5/8] vhost-user: enable frontends on any POSIX system Tim Pambor
` (4 subsequent siblings)
8 siblings, 0 replies; 23+ messages in thread
From: Tim Pambor @ 2026-10-22 13:47 UTC (permalink / raw)
To: qemu-devel
Cc: Michael S. Tsirkin, Stefano Garzarella, Daniel P. Berrangé,
Marc-André Lureau, Paolo Bonzini, Kevin Wolf, Hanna Reitz,
Jason Wang, Pierrick Bouvier, qemu-block, Raphael Norwitz,
Brad Smith, Tim Pambor
A hang-up watch for G_IO_HUP alone is not a portable disconnect
detector. Linux wakes such a poll() when the peer closes, but FreeBSD
registers a wakeup only for read/write interest and macOS drops its
one-shot read filter on any non-EOF event, so as long as nobody polls
the socket for readability the hang-up is not noticed until something
unrelated wakes the main loop. Frontends that never read from the
chardev, such as vhost-user, are the ones without a G_IO_IN watch, and
that is what makes the vhost-user/reconnect qtest fail under load on
FreeBSD with "wait_for_fds: assertion failed: (s->fds_num)".
While the frontend has no read handler at all, also ask for G_IO_IN on
the hang-up watch and treat EOF as a hang-up.
Signed-off-by: Tim Pambor <timpambor@gmail.com>
---
chardev/char-socket.c | 78 ++++++++++++++++++++++++++++++++++++++-------------
1 file changed, 59 insertions(+), 19 deletions(-)
diff --git a/chardev/char-socket.c b/chardev/char-socket.c
index 81bac42a15..62e8871c51 100644
--- a/chardev/char-socket.c
+++ b/chardev/char-socket.c
@@ -36,11 +36,14 @@
#include "trace.h"
#include "chardev/char-io.h"
+#include "chardev/char-fe.h"
#include "chardev/char-socket.h"
static gboolean socket_reconnect_timeout(gpointer opaque);
static void tcp_chr_telnet_init(Chardev *chr);
static char *qemu_chr_compute_filename(SocketChardev *s);
+static gboolean tcp_chr_hup(QIOChannel *channel, GIOCondition cond,
+ void *opaque);
static void tcp_chr_change_state(SocketChardev *s, TCPChardevState state)
{
@@ -345,6 +348,33 @@ static void remove_hup_source(SocketChardev *s)
}
}
+static void add_hup_source(SocketChardev *s, GIOCondition cond)
+{
+ Chardev *chr = CHARDEV(s);
+
+ remove_hup_source(s);
+ s->hup_source = qio_channel_create_watch(s->ioc, cond);
+ /*
+ * poll() is liable to return POLLHUP even when there is
+ * still incoming data available to read on the FD. If
+ * we have the hup_source at the same priority as the
+ * main io_add_watch_poll GSource, then we might end up
+ * processing the POLLHUP event first, closing the FD,
+ * and as a result silently discard data we should have
+ * read.
+ *
+ * By setting the hup_source to G_PRIORITY_DEFAULT + 1,
+ * we ensure that io_add_watch_poll GSource will always
+ * be dispatched first, thus guaranteeing we will be
+ * able to process all incoming data before closing the
+ * FD
+ */
+ g_source_set_priority(s->hup_source, G_PRIORITY_DEFAULT + 1);
+ g_source_set_callback(s->hup_source, (GSourceFunc)tcp_chr_hup,
+ chr, NULL);
+ g_source_attach(s->hup_source, chr->gcontext);
+}
+
static void char_socket_yank_iochannel(void *opaque)
{
QIOChannel *ioc = QIO_CHANNEL(opaque);
@@ -520,6 +550,30 @@ static gboolean tcp_chr_hup(QIOChannel *channel,
void *opaque)
{
Chardev *chr = CHARDEV(opaque);
+ SocketChardev *s = SOCKET_CHARDEV(opaque);
+
+ if (!(cond & G_IO_HUP)) {
+ /* Readable while nobody reads: only EOF counts as a hang-up. */
+ int flags = MSG_PEEK;
+ ssize_t n;
+ char c;
+
+#ifdef MSG_DONTWAIT
+ flags |= MSG_DONTWAIT;
+#endif
+
+ n = recv(s->sioc->fd, &c, 1, flags);
+
+ if (n < 0 && (errno == EAGAIN || errno == EINTR)) {
+ return G_SOURCE_CONTINUE;
+ }
+
+ if (n > 0) {
+ /* Data nobody will read: stop watching for it, or we spin. */
+ add_hup_source(s, G_IO_HUP);
+ return G_SOURCE_REMOVE;
+ }
+ }
trace_chr_socket_hangup(chr, chr->label);
tcp_chr_disconnect(chr);
return G_SOURCE_REMOVE;
@@ -611,27 +665,13 @@ static void update_ioc_handlers(SocketChardev *s)
tcp_chr_read, chr,
chr->gcontext);
- remove_hup_source(s);
- s->hup_source = qio_channel_create_watch(s->ioc, G_IO_HUP);
/*
- * poll() is liable to return POLLHUP even when there is
- * still incoming data available to read on the FD. If
- * we have the hup_source at the same priority as the
- * main io_add_watch_poll GSource, then we might end up
- * processing the POLLHUP event first, closing the FD,
- * and as a result silently discard data we should have
- * read.
- *
- * By setting the hup_source to G_PRIORITY_DEFAULT + 1,
- * we ensure that io_add_watch_poll GSource will always
- * be dispatched first, thus guaranteeing we will be
- * able to process all incoming data before closing the
- * FD
+ * A G_IO_HUP-only poll() is not woken by a peer close on FreeBSD
+ * nor reliably on macOS. Therefore, while nobody reads, ask for
+ * G_IO_IN too and let tcp_chr_hup tell EOF from data.
*/
- g_source_set_priority(s->hup_source, G_PRIORITY_DEFAULT + 1);
- g_source_set_callback(s->hup_source, (GSourceFunc)tcp_chr_hup,
- chr, NULL);
- g_source_attach(s->hup_source, chr->gcontext);
+ add_hup_source(s, G_IO_HUP |
+ (chr->fe && chr->fe->chr_can_read ? 0 : G_IO_IN));
}
static void tcp_chr_connect(void *opaque)
--
2.55.0
^ permalink raw reply related [flat|nested] 23+ messages in thread* [PATCH 5/8] vhost-user: enable frontends on any POSIX system
2026-10-22 13:47 [PATCH 0/8] vhost-user: another try at supporting any POSIX system Tim Pambor
` (3 preceding siblings ...)
2026-10-22 13:47 ` [PATCH 4/8] chardev/char-socket: detect peer close portably Tim Pambor
@ 2026-10-22 13:47 ` Tim Pambor
2026-10-27 19:24 ` Stefan Hajnoczi
2026-10-22 13:47 ` [PATCH 6/8] libvhost-user: enable it " Tim Pambor
` (3 subsequent siblings)
8 siblings, 1 reply; 23+ messages in thread
From: Tim Pambor @ 2026-10-22 13:47 UTC (permalink / raw)
To: qemu-devel
Cc: Michael S. Tsirkin, Stefano Garzarella, Daniel P. Berrangé,
Marc-André Lureau, Paolo Bonzini, Kevin Wolf, Hanna Reitz,
Jason Wang, Pierrick Bouvier, qemu-block, Raphael Norwitz,
Brad Smith, Tim Pambor, Stefan Hajnoczi,
Philippe Mathieu-Daudé, David Hildenbrand
From: Stefano Garzarella <sgarzare@redhat.com>
The vhost-user protocol is not really Linux-specific so let's enable
vhost-user frontends for any POSIX system.
In vhost_net.c we use VHOST_FILE_UNBIND which is defined in a Linux
specific header, let's define it for other systems as well.
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: David Hildenbrand <david@redhat.com>
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
Signed-off-by: Tim Pambor <timpambor@gmail.com>
---
hw/block/Kconfig | 2 +-
hw/net/vhost_net.c | 6 ++++++
meson.build | 1 -
3 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/hw/block/Kconfig b/hw/block/Kconfig
index 737dbcdb3e..7edcd7a8f6 100644
--- a/hw/block/Kconfig
+++ b/hw/block/Kconfig
@@ -28,7 +28,7 @@ config VHOST_USER_BLK
bool
# Only PCI devices are provided for now
default y if VIRTIO_PCI
- depends on VIRTIO && VHOST_USER && LINUX
+ depends on VIRTIO && VHOST_USER
config SWIM
bool
diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index 6e05c995f1..788913953d 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -33,7 +33,13 @@
#include "standard-headers/linux/virtio_ring.h"
#include "hw/virtio/vhost.h"
#include "hw/virtio/virtio-bus.h"
+#if defined(__linux__)
#include "linux-headers/linux/vhost.h"
+#endif
+
+#ifndef VHOST_FILE_UNBIND
+#define VHOST_FILE_UNBIND -1
+#endif
void vhost_net_get_features_ex(struct vhost_net *net, uint64_t *features)
{
diff --git a/meson.build b/meson.build
index b67a97ab45..eb296346a8 100644
--- a/meson.build
+++ b/meson.build
@@ -221,7 +221,6 @@ have_tpm = get_option('tpm') \
# vhost
have_vhost_user = get_option('vhost_user') \
- .disable_auto_if(host_os != 'linux') \
.require(host_os != 'windows',
error_message: 'vhost-user is not available on Windows').allowed()
have_vhost_vdpa = get_option('vhost_vdpa') \
--
2.55.0
^ permalink raw reply related [flat|nested] 23+ messages in thread* Re: [PATCH 5/8] vhost-user: enable frontends on any POSIX system
2026-10-22 13:47 ` [PATCH 5/8] vhost-user: enable frontends on any POSIX system Tim Pambor
@ 2026-10-27 19:24 ` Stefan Hajnoczi
2026-10-28 8:32 ` Stefano Garzarella
0 siblings, 1 reply; 23+ messages in thread
From: Stefan Hajnoczi @ 2026-10-27 19:24 UTC (permalink / raw)
To: Tim Pambor
Cc: qemu-devel, Michael S. Tsirkin, Stefano Garzarella,
Daniel P. Berrangé, Marc-André Lureau, Paolo Bonzini,
Kevin Wolf, Hanna Reitz, Jason Wang, Pierrick Bouvier, qemu-block,
Raphael Norwitz, Brad Smith, Philippe Mathieu-Daudé,
David Hildenbrand
On Thu, Oct 22, 2026 at 03:47:26PM +0200, Tim Pambor wrote:
> diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
> index 6e05c995f1..788913953d 100644
> --- a/hw/net/vhost_net.c
> +++ b/hw/net/vhost_net.c
> @@ -33,7 +33,13 @@
> #include "standard-headers/linux/virtio_ring.h"
> #include "hw/virtio/vhost.h"
> #include "hw/virtio/virtio-bus.h"
> +#if defined(__linux__)
> #include "linux-headers/linux/vhost.h"
> +#endif
> +
> +#ifndef VHOST_FILE_UNBIND
> +#define VHOST_FILE_UNBIND -1
> +#endif
This constant is for hw/virtio/vhost.c's vhost_net_set_backend() API. It
should be defined along with that API. Define it alongside
vhost_net_set_backend() in hw/virtio/vhost.h and call it
VHOST_NET_FILE_UNBIND?
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 5/8] vhost-user: enable frontends on any POSIX system
2026-10-27 19:24 ` Stefan Hajnoczi
@ 2026-10-28 8:32 ` Stefano Garzarella
2026-10-28 12:33 ` Stefan Hajnoczi
0 siblings, 1 reply; 23+ messages in thread
From: Stefano Garzarella @ 2026-10-28 8:32 UTC (permalink / raw)
To: Stefan Hajnoczi
Cc: Tim Pambor, qemu-devel, Michael S. Tsirkin,
Daniel P. Berrangé, Marc-André Lureau, Paolo Bonzini,
Kevin Wolf, Hanna Reitz, Jason Wang, Pierrick Bouvier, qemu-block,
Raphael Norwitz, Brad Smith, Philippe Mathieu-Daudé,
David Hildenbrand
On Tue, Oct 27, 2026 at 03:24:45PM -0400, Stefan Hajnoczi wrote:
>On Thu, Oct 22, 2026 at 03:47:26PM +0200, Tim Pambor wrote:
>> diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
>> index 6e05c995f1..788913953d 100644
>> --- a/hw/net/vhost_net.c
>> +++ b/hw/net/vhost_net.c
>> @@ -33,7 +33,13 @@
>> #include "standard-headers/linux/virtio_ring.h"
>> #include "hw/virtio/vhost.h"
>> #include "hw/virtio/virtio-bus.h"
>> +#if defined(__linux__)
>> #include "linux-headers/linux/vhost.h"
>> +#endif
>> +
>> +#ifndef VHOST_FILE_UNBIND
>> +#define VHOST_FILE_UNBIND -1
>> +#endif
>
>This constant is for hw/virtio/vhost.c's vhost_net_set_backend() API. It
>should be defined along with that API. Define it alongside
>vhost_net_set_backend() in hw/virtio/vhost.h and call it
>VHOST_NET_FILE_UNBIND?
>
That constant is defined by a Linux header (see
linux-headers/linux/vhost.h). Are you suggesting to add another constant
that is defined with VHOST_FILE_UNBIND on Linux and -1 on other
platforms?
Thanks,
Stefano
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 5/8] vhost-user: enable frontends on any POSIX system
2026-10-28 8:32 ` Stefano Garzarella
@ 2026-10-28 12:33 ` Stefan Hajnoczi
2026-10-28 13:23 ` Stefano Garzarella
0 siblings, 1 reply; 23+ messages in thread
From: Stefan Hajnoczi @ 2026-10-28 12:33 UTC (permalink / raw)
To: Stefano Garzarella
Cc: Tim Pambor, qemu-devel, Michael S. Tsirkin,
Daniel P. Berrangé, Marc-André Lureau, Paolo Bonzini,
Kevin Wolf, Hanna Reitz, Jason Wang, Pierrick Bouvier, qemu-block,
Raphael Norwitz, Brad Smith, Philippe Mathieu-Daudé,
David Hildenbrand
On Wed, Oct 28, 2026 at 09:32:05AM +0100, Stefano Garzarella wrote:
> On Tue, Oct 27, 2026 at 03:24:45PM -0400, Stefan Hajnoczi wrote:
> > On Thu, Oct 22, 2026 at 03:47:26PM +0200, Tim Pambor wrote:
> > > diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
> > > index 6e05c995f1..788913953d 100644
> > > --- a/hw/net/vhost_net.c
> > > +++ b/hw/net/vhost_net.c
> > > @@ -33,7 +33,13 @@
> > > #include "standard-headers/linux/virtio_ring.h"
> > > #include "hw/virtio/vhost.h"
> > > #include "hw/virtio/virtio-bus.h"
> > > +#if defined(__linux__)
> > > #include "linux-headers/linux/vhost.h"
> > > +#endif
> > > +
> > > +#ifndef VHOST_FILE_UNBIND
> > > +#define VHOST_FILE_UNBIND -1
> > > +#endif
> >
> > This constant is for hw/virtio/vhost.c's vhost_net_set_backend() API. It
> > should be defined along with that API. Define it alongside
> > vhost_net_set_backend() in hw/virtio/vhost.h and call it
> > VHOST_NET_FILE_UNBIND?
> >
>
> That constant is defined by a Linux header (see
> linux-headers/linux/vhost.h). Are you suggesting to add another constant
> that is defined with VHOST_FILE_UNBIND on Linux and -1 on other platforms?
Looking again, we should probably just use -1 instead of a constant
since include/standard-headers/linux/vhost_types.h doesn't even define a
constant:
struct vhost_vring_file {
unsigned int index;
int fd; /* Pass -1 to unbind from file. */
};
It's strange that VHOST_FILE_UNBIND was defined in <linux/vhost.h>
instead of <linux/vhost_types.h> where struct vhost_vring_file is
defined.
Stefan
^ permalink raw reply [flat|nested] 23+ messages in thread* Re: [PATCH 5/8] vhost-user: enable frontends on any POSIX system
2026-10-28 12:33 ` Stefan Hajnoczi
@ 2026-10-28 13:23 ` Stefano Garzarella
2026-10-28 18:43 ` Stefan Hajnoczi
0 siblings, 1 reply; 23+ messages in thread
From: Stefano Garzarella @ 2026-10-28 13:23 UTC (permalink / raw)
To: Stefan Hajnoczi
Cc: Tim Pambor, qemu-devel, Michael S. Tsirkin,
Daniel P. Berrangé, Marc-André Lureau, Paolo Bonzini,
Kevin Wolf, Hanna Reitz, Jason Wang, Pierrick Bouvier, qemu-block,
Raphael Norwitz, Brad Smith, Philippe Mathieu-Daudé,
David Hildenbrand
On Wed, Oct 28, 2026 at 08:33:46AM -0400, Stefan Hajnoczi wrote:
>On Wed, Oct 28, 2026 at 09:32:05AM +0100, Stefano Garzarella wrote:
>> On Tue, Oct 27, 2026 at 03:24:45PM -0400, Stefan Hajnoczi wrote:
>> > On Thu, Oct 22, 2026 at 03:47:26PM +0200, Tim Pambor wrote:
>> > > diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
>> > > index 6e05c995f1..788913953d 100644
>> > > --- a/hw/net/vhost_net.c
>> > > +++ b/hw/net/vhost_net.c
>> > > @@ -33,7 +33,13 @@
>> > > #include "standard-headers/linux/virtio_ring.h"
>> > > #include "hw/virtio/vhost.h"
>> > > #include "hw/virtio/virtio-bus.h"
>> > > +#if defined(__linux__)
>> > > #include "linux-headers/linux/vhost.h"
>> > > +#endif
>> > > +
>> > > +#ifndef VHOST_FILE_UNBIND
>> > > +#define VHOST_FILE_UNBIND -1
>> > > +#endif
>> >
>> > This constant is for hw/virtio/vhost.c's vhost_net_set_backend() API. It
>> > should be defined along with that API. Define it alongside
>> > vhost_net_set_backend() in hw/virtio/vhost.h and call it
>> > VHOST_NET_FILE_UNBIND?
>> >
>>
>> That constant is defined by a Linux header (see
>> linux-headers/linux/vhost.h). Are you suggesting to add another constant
>> that is defined with VHOST_FILE_UNBIND on Linux and -1 on other platforms?
>
>Looking again, we should probably just use -1 instead of a constant
Yep, this would be fine too.
I don't remember why I did in this way, maybe to keep the diff smaller
enough, but I don't have a strong opinion, we can avoid this ifndef and
use -1 everywhere if you prefer that.
>since include/standard-headers/linux/vhost_types.h doesn't even define a
>constant:
>
> struct vhost_vring_file {
> unsigned int index;
> int fd; /* Pass -1 to unbind from file. */
>
> };
>
>It's strange that VHOST_FILE_UNBIND was defined in <linux/vhost.h>
>instead of <linux/vhost_types.h> where struct vhost_vring_file is
>defined.
Oh, VHOST_FILE_UNBIND was introduced after struct vhost_vring_file, with
commit 776f395004d8 ("vhost_vdpa: Support config interrupt in vdpa").
But I agree that should be moved to vhost_types.h. BTW <linux/vhost.h>
already includes <linux/vhost_types.h>, so maybe we can fix it without
too much trouble.
Thanks,
Stefano
^ permalink raw reply [flat|nested] 23+ messages in thread* Re: [PATCH 5/8] vhost-user: enable frontends on any POSIX system
2026-10-28 13:23 ` Stefano Garzarella
@ 2026-10-28 18:43 ` Stefan Hajnoczi
2026-10-28 19:33 ` Tim Pambor
0 siblings, 1 reply; 23+ messages in thread
From: Stefan Hajnoczi @ 2026-10-28 18:43 UTC (permalink / raw)
To: Stefano Garzarella
Cc: Tim Pambor, qemu-devel, Michael S. Tsirkin,
Daniel P. Berrangé, Marc-André Lureau, Paolo Bonzini,
Kevin Wolf, Hanna Reitz, Jason Wang, Pierrick Bouvier, qemu-block,
Raphael Norwitz, Brad Smith, Philippe Mathieu-Daudé,
David Hildenbrand
On Wed, Oct 28, 2026 at 02:23:55PM +0100, Stefano Garzarella wrote:
> On Wed, Oct 28, 2026 at 08:33:46AM -0400, Stefan Hajnoczi wrote:
> > On Wed, Oct 28, 2026 at 09:32:05AM +0100, Stefano Garzarella wrote:
> > > On Tue, Oct 27, 2026 at 03:24:45PM -0400, Stefan Hajnoczi wrote:
> > > > On Thu, Oct 22, 2026 at 03:47:26PM +0200, Tim Pambor wrote:
> > > > > diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
> > > > > index 6e05c995f1..788913953d 100644
> > > > > --- a/hw/net/vhost_net.c
> > > > > +++ b/hw/net/vhost_net.c
> > > > > @@ -33,7 +33,13 @@
> > > > > #include "standard-headers/linux/virtio_ring.h"
> > > > > #include "hw/virtio/vhost.h"
> > > > > #include "hw/virtio/virtio-bus.h"
> > > > > +#if defined(__linux__)
> > > > > #include "linux-headers/linux/vhost.h"
> > > > > +#endif
> > > > > +
> > > > > +#ifndef VHOST_FILE_UNBIND
> > > > > +#define VHOST_FILE_UNBIND -1
> > > > > +#endif
> > > >
> > > > This constant is for hw/virtio/vhost.c's vhost_net_set_backend() API. It
> > > > should be defined along with that API. Define it alongside
> > > > vhost_net_set_backend() in hw/virtio/vhost.h and call it
> > > > VHOST_NET_FILE_UNBIND?
> > > >
> > >
> > > That constant is defined by a Linux header (see
> > > linux-headers/linux/vhost.h). Are you suggesting to add another constant
> > > that is defined with VHOST_FILE_UNBIND on Linux and -1 on other platforms?
> >
> > Looking again, we should probably just use -1 instead of a constant
>
> Yep, this would be fine too.
> I don't remember why I did in this way, maybe to keep the diff smaller
> enough, but I don't have a strong opinion, we can avoid this ifndef and use
> -1 everywhere if you prefer that.
IMO VHOST_FILE_UNBIND doesn't belong in vhost_net.c, so it would be nice
to avoid the #ifndef.
> > since include/standard-headers/linux/vhost_types.h doesn't even define a
> > constant:
> >
> > struct vhost_vring_file {
> > unsigned int index;
> > int fd; /* Pass -1 to unbind from file. */
> >
> > };
> >
> > It's strange that VHOST_FILE_UNBIND was defined in <linux/vhost.h>
> > instead of <linux/vhost_types.h> where struct vhost_vring_file is
> > defined.
>
> Oh, VHOST_FILE_UNBIND was introduced after struct vhost_vring_file, with
> commit 776f395004d8 ("vhost_vdpa: Support config interrupt in vdpa").
>
> But I agree that should be moved to vhost_types.h. BTW <linux/vhost.h>
> already includes <linux/vhost_types.h>, so maybe we can fix it without too
> much trouble.
Yes, that change seems safe and will improve things in the long term.
Stefan
^ permalink raw reply [flat|nested] 23+ messages in thread* Re: [PATCH 5/8] vhost-user: enable frontends on any POSIX system
2026-10-28 18:43 ` Stefan Hajnoczi
@ 2026-10-28 19:33 ` Tim Pambor
2026-10-29 9:05 ` Stefano Garzarella
2026-10-29 12:10 ` Stefan Hajnoczi
0 siblings, 2 replies; 23+ messages in thread
From: Tim Pambor @ 2026-10-28 19:33 UTC (permalink / raw)
To: Stefan Hajnoczi, Stefano Garzarella
Cc: qemu-devel, Michael S. Tsirkin, Daniel P. Berrangé,
Marc-André Lureau, Paolo Bonzini, Kevin Wolf, Hanna Reitz,
Jason Wang, Pierrick Bouvier, qemu-block, Raphael Norwitz,
Brad Smith, Philippe Mathieu-Daudé, David Hildenbrand
On Wed, Oct 28, 2026 at 7:44 PM Stefan Hajnoczi <stefanha@redhat.com> wrote:
>
> On Wed, Oct 28, 2026 at 02:23:55PM +0100, Stefano Garzarella wrote:
> > On Wed, Oct 28, 2026 at 08:33:46AM -0400, Stefan Hajnoczi wrote:
> > > On Wed, Oct 28, 2026 at 09:32:05AM +0100, Stefano Garzarella wrote:
> > > > On Tue, Oct 27, 2026 at 03:24:45PM -0400, Stefan Hajnoczi wrote:
> > > > > On Thu, Oct 22, 2026 at 03:47:26PM +0200, Tim Pambor wrote:
> > > > > > diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
> > > > > > index 6e05c995f1..788913953d 100644
> > > > > > --- a/hw/net/vhost_net.c
> > > > > > +++ b/hw/net/vhost_net.c
> > > > > > @@ -33,7 +33,13 @@
> > > > > > #include "standard-headers/linux/virtio_ring.h"
> > > > > > #include "hw/virtio/vhost.h"
> > > > > > #include "hw/virtio/virtio-bus.h"
> > > > > > +#if defined(__linux__)
> > > > > > #include "linux-headers/linux/vhost.h"
> > > > > > +#endif
> > > > > > +
> > > > > > +#ifndef VHOST_FILE_UNBIND
> > > > > > +#define VHOST_FILE_UNBIND -1
> > > > > > +#endif
> > > > >
> > > > > This constant is for hw/virtio/vhost.c's vhost_net_set_backend() API. It
> > > > > should be defined along with that API. Define it alongside
> > > > > vhost_net_set_backend() in hw/virtio/vhost.h and call it
> > > > > VHOST_NET_FILE_UNBIND?
> > > > >
> > > >
> > > > That constant is defined by a Linux header (see
> > > > linux-headers/linux/vhost.h). Are you suggesting to add another constant
> > > > that is defined with VHOST_FILE_UNBIND on Linux and -1 on other platforms?
> > >
> > > Looking again, we should probably just use -1 instead of a constant
> >
> > Yep, this would be fine too.
> > I don't remember why I did in this way, maybe to keep the diff smaller
> > enough, but I don't have a strong opinion, we can avoid this ifndef and use
> > -1 everywhere if you prefer that.
>
> IMO VHOST_FILE_UNBIND doesn't belong in vhost_net.c, so it would be nice
> to avoid the #ifndef.
So, for v2, is it ok if I replace the one usage of VHOST_FILE_UNBIND in
vhost_net.c with -1 and remove the #ifndef?
> > > since include/standard-headers/linux/vhost_types.h doesn't even define a
> > > constant:
> > >
> > > struct vhost_vring_file {
> > > unsigned int index;
> > > int fd; /* Pass -1 to unbind from file. */
> > >
> > > };
> > >
> > > It's strange that VHOST_FILE_UNBIND was defined in <linux/vhost.h>
> > > instead of <linux/vhost_types.h> where struct vhost_vring_file is
> > > defined.
> >
> > Oh, VHOST_FILE_UNBIND was introduced after struct vhost_vring_file, with
> > commit 776f395004d8 ("vhost_vdpa: Support config interrupt in vdpa").
> >
> > But I agree that should be moved to vhost_types.h. BTW <linux/vhost.h>
> > already includes <linux/vhost_types.h>, so maybe we can fix it without too
> > much trouble.
>
> Yes, that change seems safe and will improve things in the long term.
Or should I send a patch to linux adding VHOST_FILE_UNBIND to vhost_types.h
and then drop it from vhost.h and remove the #ifndef?
> Stefan
>
^ permalink raw reply [flat|nested] 23+ messages in thread* Re: [PATCH 5/8] vhost-user: enable frontends on any POSIX system
2026-10-28 19:33 ` Tim Pambor
@ 2026-10-29 9:05 ` Stefano Garzarella
2026-10-29 12:10 ` Stefan Hajnoczi
1 sibling, 0 replies; 23+ messages in thread
From: Stefano Garzarella @ 2026-10-29 9:05 UTC (permalink / raw)
To: Tim Pambor
Cc: Stefan Hajnoczi, qemu-devel, Michael S. Tsirkin,
Daniel P. Berrangé, Marc-André Lureau, Paolo Bonzini,
Kevin Wolf, Hanna Reitz, Jason Wang, Pierrick Bouvier, qemu-block,
Raphael Norwitz, Brad Smith, Philippe Mathieu-Daudé,
David Hildenbrand
On Wed, Oct 28, 2026 at 08:33:30PM +0100, Tim Pambor wrote:
>On Wed, Oct 28, 2026 at 7:44 PM Stefan Hajnoczi <stefanha@redhat.com> wrote:
>>
>> On Wed, Oct 28, 2026 at 02:23:55PM +0100, Stefano Garzarella wrote:
>> > On Wed, Oct 28, 2026 at 08:33:46AM -0400, Stefan Hajnoczi wrote:
>> > > On Wed, Oct 28, 2026 at 09:32:05AM +0100, Stefano Garzarella wrote:
>> > > > On Tue, Oct 27, 2026 at 03:24:45PM -0400, Stefan Hajnoczi wrote:
>> > > > > On Thu, Oct 22, 2026 at 03:47:26PM +0200, Tim Pambor wrote:
>> > > > > > diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
>> > > > > > index 6e05c995f1..788913953d 100644
>> > > > > > --- a/hw/net/vhost_net.c
>> > > > > > +++ b/hw/net/vhost_net.c
>> > > > > > @@ -33,7 +33,13 @@
>> > > > > > #include "standard-headers/linux/virtio_ring.h"
>> > > > > > #include "hw/virtio/vhost.h"
>> > > > > > #include "hw/virtio/virtio-bus.h"
>> > > > > > +#if defined(__linux__)
>> > > > > > #include "linux-headers/linux/vhost.h"
>> > > > > > +#endif
>> > > > > > +
>> > > > > > +#ifndef VHOST_FILE_UNBIND
>> > > > > > +#define VHOST_FILE_UNBIND -1
>> > > > > > +#endif
>> > > > >
>> > > > > This constant is for hw/virtio/vhost.c's vhost_net_set_backend() API. It
>> > > > > should be defined along with that API. Define it alongside
>> > > > > vhost_net_set_backend() in hw/virtio/vhost.h and call it
>> > > > > VHOST_NET_FILE_UNBIND?
>> > > > >
>> > > >
>> > > > That constant is defined by a Linux header (see
>> > > > linux-headers/linux/vhost.h). Are you suggesting to add another constant
>> > > > that is defined with VHOST_FILE_UNBIND on Linux and -1 on other platforms?
>> > >
>> > > Looking again, we should probably just use -1 instead of a constant
>> >
>> > Yep, this would be fine too.
>> > I don't remember why I did in this way, maybe to keep the diff smaller
>> > enough, but I don't have a strong opinion, we can avoid this ifndef and use
>> > -1 everywhere if you prefer that.
>>
>> IMO VHOST_FILE_UNBIND doesn't belong in vhost_net.c, so it would be nice
>> to avoid the #ifndef.
>
>So, for v2, is it ok if I replace the one usage of VHOST_FILE_UNBIND in
>vhost_net.c with -1 and remove the #ifndef?
Yep.
>
>> > > since include/standard-headers/linux/vhost_types.h doesn't even define a
>> > > constant:
>> > >
>> > > struct vhost_vring_file {
>> > > unsigned int index;
>> > > int fd; /* Pass -1 to unbind from file. */
>> > >
>> > > };
>> > >
>> > > It's strange that VHOST_FILE_UNBIND was defined in <linux/vhost.h>
>> > > instead of <linux/vhost_types.h> where struct vhost_vring_file is
>> > > defined.
>> >
>> > Oh, VHOST_FILE_UNBIND was introduced after struct vhost_vring_file, with
>> > commit 776f395004d8 ("vhost_vdpa: Support config interrupt in vdpa").
>> >
>> > But I agree that should be moved to vhost_types.h. BTW <linux/vhost.h>
>> > already includes <linux/vhost_types.h>, so maybe we can fix it without too
>> > much trouble.
>>
>> Yes, that change seems safe and will improve things in the long term.
>
>Or should I send a patch to linux adding VHOST_FILE_UNBIND to vhost_types.h
>and then drop it from vhost.h and remove the #ifndef?
This is orthogonal, the issue this patch was fixing was to build on
no-Linux systems, so changing Linux headers will not help.
This is more a cleanup, if you can send also that patch to Linux (which
is unrelated to this work) would be nice, otherwise let me know and I
can do that.
Note: files under linux-headers/ are imported from Linux, can't be
changed here.
Thanks,
Stefano
^ permalink raw reply [flat|nested] 23+ messages in thread* Re: [PATCH 5/8] vhost-user: enable frontends on any POSIX system
2026-10-28 19:33 ` Tim Pambor
2026-10-29 9:05 ` Stefano Garzarella
@ 2026-10-29 12:10 ` Stefan Hajnoczi
1 sibling, 0 replies; 23+ messages in thread
From: Stefan Hajnoczi @ 2026-10-29 12:10 UTC (permalink / raw)
To: Tim Pambor
Cc: Stefano Garzarella, qemu-devel, Michael S. Tsirkin,
Daniel P. Berrangé, Marc-André Lureau, Paolo Bonzini,
Kevin Wolf, Hanna Reitz, Jason Wang, Pierrick Bouvier, qemu-block,
Raphael Norwitz, Brad Smith, Philippe Mathieu-Daudé,
David Hildenbrand
On Wed, Oct 28, 2026 at 08:33:30PM +0100, Tim Pambor wrote:
> On Wed, Oct 28, 2026 at 7:44 PM Stefan Hajnoczi <stefanha@redhat.com> wrote:
> >
> > On Wed, Oct 28, 2026 at 02:23:55PM +0100, Stefano Garzarella wrote:
> > > On Wed, Oct 28, 2026 at 08:33:46AM -0400, Stefan Hajnoczi wrote:
> > > > On Wed, Oct 28, 2026 at 09:32:05AM +0100, Stefano Garzarella wrote:
> > > > > On Tue, Oct 27, 2026 at 03:24:45PM -0400, Stefan Hajnoczi wrote:
> > > > > > On Thu, Oct 22, 2026 at 03:47:26PM +0200, Tim Pambor wrote:
> > > > > > > diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
> > > > > > > index 6e05c995f1..788913953d 100644
> > > > > > > --- a/hw/net/vhost_net.c
> > > > > > > +++ b/hw/net/vhost_net.c
> > > > > > > @@ -33,7 +33,13 @@
> > > > > > > #include "standard-headers/linux/virtio_ring.h"
> > > > > > > #include "hw/virtio/vhost.h"
> > > > > > > #include "hw/virtio/virtio-bus.h"
> > > > > > > +#if defined(__linux__)
> > > > > > > #include "linux-headers/linux/vhost.h"
> > > > > > > +#endif
> > > > > > > +
> > > > > > > +#ifndef VHOST_FILE_UNBIND
> > > > > > > +#define VHOST_FILE_UNBIND -1
> > > > > > > +#endif
> > > > > >
> > > > > > This constant is for hw/virtio/vhost.c's vhost_net_set_backend() API. It
> > > > > > should be defined along with that API. Define it alongside
> > > > > > vhost_net_set_backend() in hw/virtio/vhost.h and call it
> > > > > > VHOST_NET_FILE_UNBIND?
> > > > > >
> > > > >
> > > > > That constant is defined by a Linux header (see
> > > > > linux-headers/linux/vhost.h). Are you suggesting to add another constant
> > > > > that is defined with VHOST_FILE_UNBIND on Linux and -1 on other platforms?
> > > >
> > > > Looking again, we should probably just use -1 instead of a constant
> > >
> > > Yep, this would be fine too.
> > > I don't remember why I did in this way, maybe to keep the diff smaller
> > > enough, but I don't have a strong opinion, we can avoid this ifndef and use
> > > -1 everywhere if you prefer that.
> >
> > IMO VHOST_FILE_UNBIND doesn't belong in vhost_net.c, so it would be nice
> > to avoid the #ifndef.
>
> So, for v2, is it ok if I replace the one usage of VHOST_FILE_UNBIND in
> vhost_net.c with -1 and remove the #ifndef?
Yes, that sounds good.
>
> > > > since include/standard-headers/linux/vhost_types.h doesn't even define a
> > > > constant:
> > > >
> > > > struct vhost_vring_file {
> > > > unsigned int index;
> > > > int fd; /* Pass -1 to unbind from file. */
> > > >
> > > > };
> > > >
> > > > It's strange that VHOST_FILE_UNBIND was defined in <linux/vhost.h>
> > > > instead of <linux/vhost_types.h> where struct vhost_vring_file is
> > > > defined.
> > >
> > > Oh, VHOST_FILE_UNBIND was introduced after struct vhost_vring_file, with
> > > commit 776f395004d8 ("vhost_vdpa: Support config interrupt in vdpa").
> > >
> > > But I agree that should be moved to vhost_types.h. BTW <linux/vhost.h>
> > > already includes <linux/vhost_types.h>, so maybe we can fix it without too
> > > much trouble.
> >
> > Yes, that change seems safe and will improve things in the long term.
>
> Or should I send a patch to linux adding VHOST_FILE_UNBIND to vhost_types.h
> and then drop it from vhost.h and remove the #ifndef?
Fixing the Linux headers is a long-term solution but there is no need
for QEMU to wait for it.
Thanks,
Stefan
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH 6/8] libvhost-user: enable it on any POSIX system
2026-10-22 13:47 [PATCH 0/8] vhost-user: another try at supporting any POSIX system Tim Pambor
` (4 preceding siblings ...)
2026-10-22 13:47 ` [PATCH 5/8] vhost-user: enable frontends on any POSIX system Tim Pambor
@ 2026-10-22 13:47 ` Tim Pambor
2026-10-22 13:47 ` [PATCH 7/8] contrib/vhost-user-blk: " Tim Pambor
` (2 subsequent siblings)
8 siblings, 0 replies; 23+ messages in thread
From: Tim Pambor @ 2026-10-22 13:47 UTC (permalink / raw)
To: qemu-devel
Cc: Michael S. Tsirkin, Stefano Garzarella, Daniel P. Berrangé,
Marc-André Lureau, Paolo Bonzini, Kevin Wolf, Hanna Reitz,
Jason Wang, Pierrick Bouvier, qemu-block, Raphael Norwitz,
Brad Smith, Tim Pambor, Stefan Hajnoczi,
Philippe Mathieu-Daudé
From: Stefano Garzarella <sgarzare@redhat.com>
The vhost-user protocol is not really Linux-specific so let's enable
libvhost-user for any POSIX system.
Compiling it on macOS and FreeBSD some problems came up:
- avoid to include linux/vhost.h which is available only on Linux
(vhost_types.h contains many of the things we need)
- macOS doesn't provide sys/endian.h, so let's define them
(note: libvhost-user doesn't include QEMU's headers, so we can't use
use "qemu/bswap.h")
- define eventfd_[write|read] as write/read wrapper when system doesn't
provide those (e.g. macOS)
- copy SEAL defines from include/qemu/memfd.h to make the code works
on FreeBSD where MFD_ALLOW_SEALING is defined
- define MAP_NORESERVE if it's not defined (e.g. on FreeBSD)
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
Signed-off-by: Tim Pambor <timpambor@gmail.com>
---
meson.build | 2 +-
subprojects/libvhost-user/libvhost-user.c | 59 +++++++++++++++++++++++++++++--
subprojects/libvhost-user/libvhost-user.h | 2 +-
3 files changed, 59 insertions(+), 4 deletions(-)
diff --git a/meson.build b/meson.build
index eb296346a8..4f4068e7a7 100644
--- a/meson.build
+++ b/meson.build
@@ -3468,7 +3468,7 @@ if have_system and vfio_user_server_allowed
endif
vhost_user = not_found
-if host_os == 'linux' and have_vhost_user
+if have_vhost_user
libvhost_user = subproject('libvhost-user')
vhost_user = libvhost_user.get_variable('vhost_user_dep')
endif
diff --git a/subprojects/libvhost-user/libvhost-user.c b/subprojects/libvhost-user/libvhost-user.c
index e323e32cab..7ce73fba19 100644
--- a/subprojects/libvhost-user/libvhost-user.c
+++ b/subprojects/libvhost-user/libvhost-user.c
@@ -29,9 +29,7 @@
#include <inttypes.h>
#include <sys/types.h>
#include <sys/socket.h>
-#include <sys/eventfd.h>
#include <sys/mman.h>
-#include <endian.h>
/* Necessary to provide VIRTIO_F_VERSION_1 on system
* with older linux headers. Must appear before
@@ -40,6 +38,7 @@
#include "standard-headers/linux/virtio_config.h"
#if defined(__linux__)
+#include <endian.h>
#include <sys/syscall.h>
#include <sys/ioctl.h>
#include <linux/vhost.h>
@@ -52,6 +51,62 @@
#endif
+#if defined(__APPLE__) && (__MACH__)
+#include <libkern/OSByteOrder.h>
+#define htobe16(x) OSSwapHostToBigInt16(x)
+#define htole16(x) OSSwapHostToLittleInt16(x)
+#define be16toh(x) OSSwapBigToHostInt16(x)
+#define le16toh(x) OSSwapLittleToHostInt16(x)
+
+#define htobe32(x) OSSwapHostToBigInt32(x)
+#define htole32(x) OSSwapHostToLittleInt32(x)
+#define be32toh(x) OSSwapBigToHostInt32(x)
+#define le32toh(x) OSSwapLittleToHostInt32(x)
+
+#define htobe64(x) OSSwapHostToBigInt64(x)
+#define htole64(x) OSSwapHostToLittleInt64(x)
+#define be64toh(x) OSSwapBigToHostInt64(x)
+#define le64toh(x) OSSwapLittleToHostInt64(x)
+#endif
+
+#ifdef CONFIG_EVENTFD
+#include <sys/eventfd.h>
+#else
+#define eventfd_t uint64_t
+
+int eventfd_write(int fd, eventfd_t value)
+{
+ return (write(fd, &value, sizeof(value)) == sizeof(value)) ? 0 : -1;
+}
+
+int eventfd_read(int fd, eventfd_t *value)
+{
+ return (read(fd, value, sizeof(*value)) == sizeof(*value)) ? 0 : -1;
+}
+#endif
+
+#ifdef MFD_ALLOW_SEALING
+#include <fcntl.h>
+
+#ifndef F_LINUX_SPECIFIC_BASE
+#define F_LINUX_SPECIFIC_BASE 1024
+#endif
+
+#ifndef F_ADD_SEALS
+#define F_ADD_SEALS (F_LINUX_SPECIFIC_BASE + 9)
+#define F_GET_SEALS (F_LINUX_SPECIFIC_BASE + 10)
+
+#define F_SEAL_SEAL 0x0001 /* prevent further seals from being set */
+#define F_SEAL_SHRINK 0x0002 /* prevent file from shrinking */
+#define F_SEAL_GROW 0x0004 /* prevent file from growing */
+#define F_SEAL_WRITE 0x0008 /* prevent writes */
+#endif
+#endif
+
+#ifndef MAP_NORESERVE
+#define MAP_NORESERVE 0
+#endif
+
#include "include/atomic.h"
#include "libvhost-user.h"
diff --git a/subprojects/libvhost-user/libvhost-user.h b/subprojects/libvhost-user/libvhost-user.h
index ddd5cbb90e..f21ba77580 100644
--- a/subprojects/libvhost-user/libvhost-user.h
+++ b/subprojects/libvhost-user/libvhost-user.h
@@ -18,9 +18,9 @@
#include <stdbool.h>
#include <stddef.h>
#include <poll.h>
-#include <linux/vhost.h>
#include <pthread.h>
#include "standard-headers/linux/virtio_ring.h"
+#include "standard-headers/linux/vhost_types.h"
/* Based on qemu/hw/virtio/vhost-user.c */
#define VHOST_USER_F_PROTOCOL_FEATURES 30
--
2.55.0
^ permalink raw reply related [flat|nested] 23+ messages in thread* [PATCH 7/8] contrib/vhost-user-blk: enable it on any POSIX system
2026-10-22 13:47 [PATCH 0/8] vhost-user: another try at supporting any POSIX system Tim Pambor
` (5 preceding siblings ...)
2026-10-22 13:47 ` [PATCH 6/8] libvhost-user: enable it " Tim Pambor
@ 2026-10-22 13:47 ` Tim Pambor
2026-10-22 13:47 ` [PATCH 8/8] libvhost-user: detect memfd support with a link test Tim Pambor
2026-10-23 16:00 ` [PATCH 0/8] vhost-user: another try at supporting any POSIX system Stefano Garzarella
8 siblings, 0 replies; 23+ messages in thread
From: Tim Pambor @ 2026-10-22 13:47 UTC (permalink / raw)
To: qemu-devel
Cc: Michael S. Tsirkin, Stefano Garzarella, Daniel P. Berrangé,
Marc-André Lureau, Paolo Bonzini, Kevin Wolf, Hanna Reitz,
Jason Wang, Pierrick Bouvier, qemu-block, Raphael Norwitz,
Brad Smith, Tim Pambor, Stefan Hajnoczi,
Philippe Mathieu-Daudé
From: Stefano Garzarella <sgarzare@redhat.com>
Let's make the code more portable by adding defines from
block/file-posix.c to support O_DIRECT in other systems (e.g. macOS).
vhost-user-server.c is a dependency, let's enable it for any POSIX
system.
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
Signed-off-by: Tim Pambor <timpambor@gmail.com>
---
contrib/vhost-user-blk/vhost-user-blk.c | 14 ++++++++++++++
meson.build | 2 --
util/meson.build | 4 +++-
3 files changed, 17 insertions(+), 3 deletions(-)
diff --git a/contrib/vhost-user-blk/vhost-user-blk.c b/contrib/vhost-user-blk/vhost-user-blk.c
index 6cc18a1c04..419ad2a10d 100644
--- a/contrib/vhost-user-blk/vhost-user-blk.c
+++ b/contrib/vhost-user-blk/vhost-user-blk.c
@@ -25,6 +25,20 @@
#include <sys/ioctl.h>
#endif
+/* OS X does not have O_DSYNC */
+#ifndef O_DSYNC
+#ifdef O_SYNC
+#define O_DSYNC O_SYNC
+#elif defined(O_FSYNC)
+#define O_DSYNC O_FSYNC
+#endif
+#endif
+
+/* Approximate O_DIRECT with O_DSYNC if O_DIRECT isn't available */
+#ifndef O_DIRECT
+#define O_DIRECT O_DSYNC
+#endif
+
enum {
VHOST_USER_BLK_MAX_QUEUES = 8,
};
diff --git a/meson.build b/meson.build
index 4f4068e7a7..1250d467a0 100644
--- a/meson.build
+++ b/meson.build
@@ -2177,8 +2177,6 @@ osdep_prefix = '''
'''
have_vhost_user_blk_server = get_option('vhost_user_blk_server') \
- .require(host_os == 'linux',
- error_message: 'vhost_user_blk_server requires linux') \
.require(have_vhost_user,
error_message: 'vhost_user_blk_server requires vhost-user support') \
.disable_auto_if(not have_tools and not have_system) \
diff --git a/util/meson.build b/util/meson.build
index fa174c07a5..54ca587362 100644
--- a/util/meson.build
+++ b/util/meson.build
@@ -105,10 +105,12 @@ if have_block
util_ss.add(files('filemonitor-stub.c'))
endif
if host_os == 'linux'
- util_ss.add(files('vhost-user-server.c'), vhost_user)
util_ss.add(files('vfio-helpers.c'))
util_ss.add(files('chardev_open.c'))
endif
+ if host_os != 'windows'
+ util_ss.add(files('vhost-user-server.c'), vhost_user)
+ endif
util_ss.add(files('yank.c'))
endif
--
2.55.0
^ permalink raw reply related [flat|nested] 23+ messages in thread* [PATCH 8/8] libvhost-user: detect memfd support with a link test
2026-10-22 13:47 [PATCH 0/8] vhost-user: another try at supporting any POSIX system Tim Pambor
` (6 preceding siblings ...)
2026-10-22 13:47 ` [PATCH 7/8] contrib/vhost-user-blk: " Tim Pambor
@ 2026-10-22 13:47 ` Tim Pambor
2026-10-29 11:44 ` Stefano Garzarella
2026-10-23 16:00 ` [PATCH 0/8] vhost-user: another try at supporting any POSIX system Stefano Garzarella
8 siblings, 1 reply; 23+ messages in thread
From: Tim Pambor @ 2026-10-22 13:47 UTC (permalink / raw)
To: qemu-devel
Cc: Michael S. Tsirkin, Stefano Garzarella, Daniel P. Berrangé,
Marc-André Lureau, Paolo Bonzini, Kevin Wolf, Hanna Reitz,
Jason Wang, Pierrick Bouvier, qemu-block, Raphael Norwitz,
Brad Smith, Tim Pambor
The inflight fd code is guarded by #ifdef MFD_ALLOW_SEALING, which only
tells us that the headers define the flag, not that memfd_create() is
available in the C library. There are environments where the flag is
defined but the link fails:
ld: error: libvhost-user.a(libvhost-user.c.o): undefined symbol: memfd_create
Probe for memfd_create() with MFD_ALLOW_SEALING in the subproject's
meson.build, using the same test QEMU's top-level meson.build uses for
CONFIG_MEMFD, and guard the code with CONFIG_MEMFD instead.
When memfd is not available, VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD is
masked out as before, so the frontend never sends
VHOST_USER_GET_INFLIGHT_FD.
Signed-off-by: Tim Pambor <timpambor@gmail.com>
---
subprojects/libvhost-user/libvhost-user.c | 17 ++++++++---------
subprojects/libvhost-user/meson.build | 11 ++++++++++-
2 files changed, 18 insertions(+), 10 deletions(-)
diff --git a/subprojects/libvhost-user/libvhost-user.c b/subprojects/libvhost-user/libvhost-user.c
index 7ce73fba19..32b7ae82ce 100644
--- a/subprojects/libvhost-user/libvhost-user.c
+++ b/subprojects/libvhost-user/libvhost-user.c
@@ -85,7 +85,7 @@ int eventfd_read(int fd, eventfd_t *value)
}
#endif
-#ifdef MFD_ALLOW_SEALING
+#ifdef CONFIG_MEMFD
#include <fcntl.h>
#ifndef F_LINUX_SPECIFIC_BASE
@@ -1963,13 +1963,12 @@ vu_get_protocol_features_exec(VuDev *dev, VhostUserMsg *vmsg)
features |= dev->iface->get_protocol_features(dev);
}
-#ifndef MFD_ALLOW_SEALING
+#ifndef CONFIG_MEMFD
/*
- * If MFD_ALLOW_SEALING is not defined, we are not able to handle
- * VHOST_USER_GET_INFLIGHT_FD messages, since we can't create a memfd.
- * Those messages are used only if VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD
- * is negotiated. A device implementation can enable it, so let's mask
- * it to avoid a runtime panic.
+ * Without memfd we are not able to handle VHOST_USER_GET_INFLIGHT_FD
+ * messages. Those messages are used only if
+ * VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD is negotiated. A device
+ * implementation can enable it, so let's mask it to avoid a runtime panic.
*/
features &= ~(1ULL << VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD);
#endif
@@ -2164,7 +2163,7 @@ vu_inflight_queue_size(uint16_t queue_size)
sizeof(uint16_t), INFLIGHT_ALIGNMENT);
}
-#ifdef MFD_ALLOW_SEALING
+#ifdef CONFIG_MEMFD
static void *
memfd_alloc(const char *name, size_t size, unsigned int flags, int *fd)
{
@@ -2231,7 +2230,7 @@ vu_get_inflight_fd(VuDev *dev, VhostUserMsg *vmsg)
mmap_size = vu_inflight_queue_size(queue_size) * num_queues;
-#ifdef MFD_ALLOW_SEALING
+#ifdef CONFIG_MEMFD
addr = memfd_alloc("vhost-inflight", mmap_size,
F_SEAL_GROW | F_SEAL_SHRINK | F_SEAL_SEAL,
&fd);
diff --git a/subprojects/libvhost-user/meson.build b/subprojects/libvhost-user/meson.build
index a18014e7f2..aa5894a642 100644
--- a/subprojects/libvhost-user/meson.build
+++ b/subprojects/libvhost-user/meson.build
@@ -11,10 +11,19 @@ add_project_arguments(cc.get_supported_arguments('-Wsign-compare',
threads = dependency('threads')
glib = dependency('glib-2.0')
+vhost_user_flags = ['-D_GNU_SOURCE']
+
+if cc.links('''
+ #define _GNU_SOURCE
+ #include <sys/mman.h>
+ int main(void) { return memfd_create("foo", MFD_ALLOW_SEALING); }''')
+ vhost_user_flags += '-DCONFIG_MEMFD'
+endif
+
vhost_user = static_library('vhost-user',
files('libvhost-user.c'),
dependencies: threads,
- c_args: '-D_GNU_SOURCE')
+ c_args: vhost_user_flags)
executable('link-test', files('link-test.c'),
link_whole: vhost_user)
--
2.55.0
^ permalink raw reply related [flat|nested] 23+ messages in thread* Re: [PATCH 8/8] libvhost-user: detect memfd support with a link test
2026-10-22 13:47 ` [PATCH 8/8] libvhost-user: detect memfd support with a link test Tim Pambor
@ 2026-10-29 11:44 ` Stefano Garzarella
0 siblings, 0 replies; 23+ messages in thread
From: Stefano Garzarella @ 2026-10-29 11:44 UTC (permalink / raw)
To: Tim Pambor
Cc: qemu-devel, Michael S. Tsirkin, Daniel P. Berrangé,
Marc-André Lureau, Paolo Bonzini, Kevin Wolf, Hanna Reitz,
Jason Wang, Pierrick Bouvier, qemu-block, Raphael Norwitz,
Brad Smith
On Thu, Oct 22, 2026 at 03:47:29PM +0200, Tim Pambor wrote:
> The inflight fd code is guarded by #ifdef MFD_ALLOW_SEALING, which only
> tells us that the headers define the flag, not that memfd_create() is
> available in the C library. There are environments where the flag is
> defined but the link fails:
>
> ld: error: libvhost-user.a(libvhost-user.c.o): undefined symbol: memfd_create
>
> Probe for memfd_create() with MFD_ALLOW_SEALING in the subproject's
> meson.build, using the same test QEMU's top-level meson.build uses for
> CONFIG_MEMFD, and guard the code with CONFIG_MEMFD instead.
>
> When memfd is not available, VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD is
> masked out as before, so the frontend never sends
> VHOST_USER_GET_INFLIGHT_FD.
>
> Signed-off-by: Tim Pambor <timpambor@gmail.com>
> ---
> subprojects/libvhost-user/libvhost-user.c | 17 ++++++++---------
> subprojects/libvhost-user/meson.build | 11 ++++++++++-
> 2 files changed, 18 insertions(+), 10 deletions(-)
Should we move this commit before we enable libvhost-user on any POSIX?
Also, maybe we should do something similar for CONFIG_EVENTFD as I
pointed out in the other commit.
Thanks,
Stefano
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 0/8] vhost-user: another try at supporting any POSIX system
2026-10-22 13:47 [PATCH 0/8] vhost-user: another try at supporting any POSIX system Tim Pambor
` (7 preceding siblings ...)
2026-10-22 13:47 ` [PATCH 8/8] libvhost-user: detect memfd support with a link test Tim Pambor
@ 2026-10-23 16:00 ` Stefano Garzarella
2026-10-26 9:17 ` Tim Pambor
8 siblings, 1 reply; 23+ messages in thread
From: Stefano Garzarella @ 2026-10-23 16:00 UTC (permalink / raw)
To: Tim Pambor
Cc: qemu-devel, Michael S. Tsirkin, Daniel P. Berrangé,
Marc-André Lureau, Paolo Bonzini, Kevin Wolf, Hanna Reitz,
Jason Wang, Pierrick Bouvier, qemu-block, Raphael Norwitz,
Brad Smith, Stefan Hajnoczi, Philippe Mathieu-Daudé,
David Hildenbrand
On Thu, 22 Oct 2026 at 15:48, Tim Pambor <timpambor@gmail.com> wrote:
>
> This series continues the work started by Stefano [1] to add support
> for any POSIX system to vhost-user.
Cool, thanks for doing this!
>
> Three patches from his original series were never applied due to failing
> tests [2]. I was able to reproduce these test failures on current master.
Oh, nice, I'm curious, how did you arrive at the fix?
>
> Patch 4 contains a fix for this problem. Patches 1-3 fix further issues I
> identified on macOS. Patches 5-7 are the three unmodified patches from
> Stefano's patch series. Patch 8 contains another bugfix I came across
> while testing.
Great, I'll review next week.
Thanks,
Stefano
^ permalink raw reply [flat|nested] 23+ messages in thread* Re: [PATCH 0/8] vhost-user: another try at supporting any POSIX system
2026-10-23 16:00 ` [PATCH 0/8] vhost-user: another try at supporting any POSIX system Stefano Garzarella
@ 2026-10-26 9:17 ` Tim Pambor
0 siblings, 0 replies; 23+ messages in thread
From: Tim Pambor @ 2026-10-26 9:17 UTC (permalink / raw)
To: Stefano Garzarella
Cc: qemu-devel, Michael S. Tsirkin, Daniel P. Berrangé,
Marc-André Lureau, Paolo Bonzini, Kevin Wolf, Hanna Reitz,
Jason Wang, Pierrick Bouvier, qemu-block, Raphael Norwitz,
Brad Smith, Stefan Hajnoczi, Philippe Mathieu-Daudé,
David Hildenbrand
Hi Stefano,
On Fri, Oct 23, 2026 at 6:01 PM Stefano Garzarella <sgarzare@redhat.com> wrote:
>
> On Thu, 22 Oct 2026 at 15:48, Tim Pambor <timpambor@gmail.com> wrote:
> >
> > This series continues the work started by Stefano [1] to add support
> > for any POSIX system to vhost-user.
>
> Cool, thanks for doing this!
>
> >
> > Three patches from his original series were never applied due to failing
> > tests [2]. I was able to reproduce these test failures on current master.
>
> Oh, nice, I'm curious, how did you arrive at the fix?
I was only able to reproduce it under high CPU load, so I looked into what
changes with load. Looking at the trace of a failing run, QEMU sat in poll()
waiting for an event from the moment of the disconnect until the test failed.
Only then did it notice the disconnect, because the test’s other sockets,
e.g. the qtest control socket, were closed when the test died. The vhost-user
chardev had no reader, so before the fix its only poll interest was G_IO_HUP,
which does not wake poll() on FreeBSD. The qtest chardev has a front-end
that reads, so it was also polled with G_IO_IN, and that close did wake the
loop.
I also checked why it passes under low load. There, the disconnect coincides
with the DRIVER_OK handshake (virtio_net_setup -> qvirtio_set_driver_ok).
That access wakes the event loop, where the already pending hang-up is
reported in the same poll() return, and the disconnect gets processed in time.
Under high load this no longer lines up: the status read-back is already over
when the close happens, and nothing is left to wake the event loop.
>
> >
> > Patch 4 contains a fix for this problem. Patches 1-3 fix further issues I
> > identified on macOS. Patches 5-7 are the three unmodified patches from
> > Stefano's patch series. Patch 8 contains another bugfix I came across
> > while testing.
>
> Great, I'll review next week.
Thanks,
Tim
^ permalink raw reply [flat|nested] 23+ messages in thread