Commit aa793e4758 for qemu.org
commit aa793e47583b767a10606a967cdd5a9795f61b95
Author: Marc-André Lureau <marcandre.lureau@redhat.com>
Date: Fri Aug 21 00:42:49 2026 +0400
ui/dmabuf: own and close fds on free
Make qemu_dmabuf_free() call qemu_dmabuf_close(), so the dmabuf always
owns and closes its fds. This removes the need for callers to
explicitly close fds before freeing and simplify the code.
To support this, virtio_gpu_create_dmabuf() now dup()s the resource fd
so each QemuDmaBuf has an independent copy. The scanout-matching loop
in virtio_gpu_fini_udmabuf() is no longer needed and is removed.
Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c
index cd684d6363..c09aca0411 100644
--- a/hw/display/vhost-user-gpu.c
+++ b/hw/display/vhost-user-gpu.c
@@ -293,7 +293,6 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg)
dmabuf = g->dmabuf[m->scanout_id];
if (dmabuf) {
- qemu_dmabuf_close(dmabuf);
qemu_console_gl_release_dmabuf(con, dmabuf);
g_clear_pointer(&dmabuf, qemu_dmabuf_free);
}
diff --git a/hw/display/virtio-gpu-udmabuf-stubs.c b/hw/display/virtio-gpu-udmabuf-stubs.c
index 0883bf05fa..1a9dfbdec1 100644
--- a/hw/display/virtio-gpu-udmabuf-stubs.c
+++ b/hw/display/virtio-gpu-udmabuf-stubs.c
@@ -13,7 +13,7 @@ bool virtio_gpu_init_udmabuf(struct virtio_gpu_simple_resource *res)
return false;
}
-void virtio_gpu_fini_udmabuf(VirtIOGPU *g, struct virtio_gpu_simple_resource *res)
+void virtio_gpu_fini_udmabuf(struct virtio_gpu_simple_resource *res)
{
/* nothing (stub) */
}
diff --git a/hw/display/virtio-gpu-udmabuf.c b/hw/display/virtio-gpu-udmabuf.c
index a38afb24c7..6d2bc8d977 100644
--- a/hw/display/virtio-gpu-udmabuf.c
+++ b/hw/display/virtio-gpu-udmabuf.c
@@ -82,7 +82,7 @@ static void virtio_gpu_remap_udmabuf(struct virtio_gpu_simple_resource *res)
}
}
-static void virtio_gpu_destroy_udmabuf(struct virtio_gpu_simple_resource *res)
+void virtio_gpu_fini_udmabuf(struct virtio_gpu_simple_resource *res)
{
if (res->remapped) {
munmap(res->remapped, res->blob_size);
@@ -148,7 +148,7 @@ bool virtio_gpu_init_udmabuf(struct virtio_gpu_simple_resource *res)
}
virtio_gpu_remap_udmabuf(res);
if (!res->remapped) {
- virtio_gpu_destroy_udmabuf(res);
+ virtio_gpu_fini_udmabuf(res);
return false;
}
res->share_handle = res->dmabuf_fd;
@@ -160,43 +160,28 @@ bool virtio_gpu_init_udmabuf(struct virtio_gpu_simple_resource *res)
return true;
}
-void virtio_gpu_fini_udmabuf(VirtIOGPU *g, struct virtio_gpu_simple_resource *res)
-{
- int max_outputs = g->parent_obj.conf.max_outputs;
- int i;
-
- for (i = 0; i < max_outputs; i++) {
- struct virtio_gpu_scanout *scanout = &g->parent_obj.scanout[i];
-
- if (scanout->dmabuf &&
- qemu_dmabuf_get_num_planes(scanout->dmabuf) > 0 &&
- qemu_dmabuf_get_fds(scanout->dmabuf, NULL)[0] == res->dmabuf_fd &&
- res->dmabuf_fd != -1) {
- qemu_dmabuf_close(scanout->dmabuf);
- res->dmabuf_fd = -1;
- res->share_handle = SHAREABLE_NONE;
- }
- }
-
- virtio_gpu_destroy_udmabuf(res);
-}
-
static QemuDmaBuf *
virtio_gpu_create_dmabuf(struct virtio_gpu_simple_resource *res,
struct virtio_gpu_framebuffer *fb,
struct virtio_gpu_rect *r)
{
uint32_t offset = 0;
+ int fd;
if (res->dmabuf_fd < 0) {
return NULL;
}
+ fd = qemu_dup(res->dmabuf_fd);
+ if (fd < 0) {
+ return NULL;
+ }
+
return qemu_dmabuf_new(r->width, r->height,
&offset, &fb->stride,
r->x, r->y, fb->width, fb->height,
qemu_pixman_to_drm_format(fb->format),
- DRM_FORMAT_MOD_INVALID, &res->dmabuf_fd,
+ DRM_FORMAT_MOD_INVALID, &fd,
1, true, false);
}
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index cb45360e76..ecf3cbc489 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -1077,7 +1077,7 @@ void virtio_gpu_cleanup_mapping(VirtIOGPU *g,
res->addrs = NULL;
if (res->blob) {
- virtio_gpu_fini_udmabuf(g, res);
+ virtio_gpu_fini_udmabuf(res);
}
}
diff --git a/hw/vfio/display.c b/hw/vfio/display.c
index cb83d98e9a..89854eceb4 100644
--- a/hw/vfio/display.c
+++ b/hw/vfio/display.c
@@ -263,7 +263,6 @@ static void vfio_display_free_one_dmabuf(VFIODisplay *dpy, VFIODMABuf *dmabuf)
{
QTAILQ_REMOVE(&dpy->dmabuf.bufs, dmabuf, next);
- qemu_dmabuf_close(dmabuf->buf);
qemu_console_gl_release_dmabuf(dpy->con, dmabuf->buf);
g_clear_pointer(&dmabuf->buf, qemu_dmabuf_free);
g_free(dmabuf);
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index ee5f6f2f23..c2018b4105 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -390,8 +390,7 @@ bool virtio_gpu_scanout_blob_to_fb(struct virtio_gpu_framebuffer *fb,
/* virtio-gpu-udmabuf.c */
bool virtio_gpu_have_udmabuf(void);
bool virtio_gpu_init_udmabuf(struct virtio_gpu_simple_resource *res);
-void virtio_gpu_fini_udmabuf(VirtIOGPU *g,
- struct virtio_gpu_simple_resource *res);
+void virtio_gpu_fini_udmabuf(struct virtio_gpu_simple_resource *res);
int virtio_gpu_update_dmabuf(VirtIOGPU *g,
uint32_t scanout_id,
struct virtio_gpu_simple_resource *res,
diff --git a/include/ui/dmabuf.h b/include/ui/dmabuf.h
index b972099859..968f3f9c8d 100644
--- a/include/ui/dmabuf.h
+++ b/include/ui/dmabuf.h
@@ -27,7 +27,6 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(QemuDmaBuf, qemu_dmabuf_free);
const int *qemu_dmabuf_get_fds(QemuDmaBuf *dmabuf, int *nfds);
void qemu_dmabuf_dup_fds(QemuDmaBuf *dmabuf, int *fds, int nfds);
-void qemu_dmabuf_close(QemuDmaBuf *dmabuf);
uint32_t qemu_dmabuf_get_width(QemuDmaBuf *dmabuf);
uint32_t qemu_dmabuf_get_height(QemuDmaBuf *dmabuf);
const uint32_t *qemu_dmabuf_get_offsets(QemuDmaBuf *dmabuf, int *noffsets);
diff --git a/ui/dbus-listener.c b/ui/dbus-listener.c
index 5a72c7eeae..c1e8664838 100644
--- a/ui/dbus-listener.c
+++ b/ui/dbus-listener.c
@@ -631,7 +631,6 @@ static void dbus_scanout_texture(DisplayChangeListener *dcl,
if (dbus_call_scanout_dmabuf(ddl, dmabuf)) {
ddl->scanout_dmabuf = NULL;
}
- qemu_dmabuf_close(dmabuf);
#endif
#ifdef WIN32
diff --git a/ui/dmabuf.c b/ui/dmabuf.c
index 495270f29b..497f82cc61 100644
--- a/ui/dmabuf.c
+++ b/ui/dmabuf.c
@@ -61,10 +61,18 @@ QemuDmaBuf *qemu_dmabuf_new(uint32_t width, uint32_t height,
void qemu_dmabuf_free(QemuDmaBuf *dmabuf)
{
+ int i;
+
if (dmabuf == NULL) {
return;
}
+ for (i = 0; i < dmabuf->num_planes; i++) {
+ if (dmabuf->fd[i] >= 0) {
+ close(dmabuf->fd[i]);
+ dmabuf->fd[i] = -1;
+ }
+ }
g_free(dmabuf);
}
@@ -91,20 +99,6 @@ void qemu_dmabuf_dup_fds(QemuDmaBuf *dmabuf, int *fds, int nfds)
}
}
-void qemu_dmabuf_close(QemuDmaBuf *dmabuf)
-{
- int i;
-
- assert(dmabuf != NULL);
-
- for (i = 0; i < dmabuf->num_planes; i++) {
- if (dmabuf->fd[i] >= 0) {
- close(dmabuf->fd[i]);
- dmabuf->fd[i] = -1;
- }
- }
-}
-
uint32_t qemu_dmabuf_get_width(QemuDmaBuf *dmabuf)
{
assert(dmabuf != NULL);