backends/hostmem-shm: factor out allocation of "anonymous shared memory with an fd"

Let's factor it out so we can reuse it.

Signed-off-by: David Hildenbrand <david@redhat.com>
Signed-off-by: Steve Sistare <steven.sistare@oracle.com>
Reviewed-by: Peter Xu <peterx@redhat.com>
Link: https://lore.kernel.org/r/1736967650-129648-2-git-send-email-steven.sistare@oracle.com
Signed-off-by: Fabiano Rosas <farosas@suse.de>
This commit is contained in:
Steve Sistare 2025-01-15 11:00:27 -08:00 committed by Fabiano Rosas
parent ed19620846
commit 57ad6ab804
5 changed files with 69 additions and 43 deletions

View file

@ -25,11 +25,9 @@ struct HostMemoryBackendShm {
static bool
shm_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
{
g_autoptr(GString) shm_name = g_string_new(NULL);
g_autofree char *backend_name = NULL;
uint32_t ram_flags;
int fd, oflag;
mode_t mode;
int fd;
if (!backend->size) {
error_setg(errp, "can't create shm backend with size 0");
@ -41,48 +39,13 @@ shm_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
return false;
}
/*
* Let's use `mode = 0` because we don't want other processes to open our
* memory unless we share the file descriptor with them.
*/
mode = 0;
oflag = O_RDWR | O_CREAT | O_EXCL;
backend_name = host_memory_backend_get_name(backend);
/*
* Some operating systems allow creating anonymous POSIX shared memory
* objects (e.g. FreeBSD provides the SHM_ANON constant), but this is not
* defined by POSIX, so let's create a unique name.
*
* From Linux's shm_open(3) man-page:
* For portable use, a shared memory object should be identified
* by a name of the form /somename;"
*/
g_string_printf(shm_name, "/qemu-" FMT_pid "-shm-%s", getpid(),
backend_name);
fd = shm_open(shm_name->str, oflag, mode);
fd = qemu_shm_alloc(backend->size, errp);
if (fd < 0) {
error_setg_errno(errp, errno,
"failed to create POSIX shared memory");
return false;
}
/*
* We have the file descriptor, so we no longer need to expose the
* POSIX shared memory object. However it will remain allocated as long as
* there are file descriptors pointing to it.
*/
shm_unlink(shm_name->str);
if (ftruncate(fd, backend->size) == -1) {
error_setg_errno(errp, errno,
"failed to resize POSIX shared memory to %" PRIu64,
backend->size);
close(fd);
return false;
}
/* Let's do the same as memory-backend-ram,share=on would do. */
backend_name = host_memory_backend_get_name(backend);
ram_flags = RAM_SHARED;
ram_flags |= backend->reserve ? 0 : RAM_NORESERVE;

View file

@ -509,6 +509,7 @@ int qemu_daemon(int nochdir, int noclose);
void *qemu_anon_ram_alloc(size_t size, uint64_t *align, bool shared,
bool noreserve);
void qemu_anon_ram_free(void *ptr, size_t size);
int qemu_shm_alloc(size_t size, Error **errp);
#ifdef _WIN32
#define HAVE_CHARDEV_SERIAL 1

View file

@ -3696,9 +3696,13 @@ libqemuutil = static_library('qemuutil',
build_by_default: false,
sources: util_ss.sources() + stub_ss.sources() + genh,
dependencies: [util_ss.dependencies(), libm, threads, glib, socket, malloc])
qemuutil_deps = [event_loop_base]
if host_os != 'windows'
qemuutil_deps += [rt]
endif
qemuutil = declare_dependency(link_with: libqemuutil,
sources: genh + version_res,
dependencies: [event_loop_base])
dependencies: qemuutil_deps)
if have_system or have_user
decodetree = generator(find_program('scripts/decodetree.py'),
@ -4357,7 +4361,7 @@ if have_tools
subdir('contrib/elf2dmp')
executable('qemu-edid', files('qemu-edid.c', 'hw/display/edid-generate.c'),
dependencies: qemuutil,
dependencies: [qemuutil, rt],
install: true)
if have_vhost_user

View file

@ -931,3 +931,55 @@ void qemu_close_all_open_fd(const int *skip, unsigned int nskip)
qemu_close_all_open_fd_fallback(skip, nskip, open_max);
}
}
int qemu_shm_alloc(size_t size, Error **errp)
{
g_autoptr(GString) shm_name = g_string_new(NULL);
int fd, oflag, cur_sequence;
static int sequence;
mode_t mode;
cur_sequence = qatomic_fetch_inc(&sequence);
/*
* Let's use `mode = 0` because we don't want other processes to open our
* memory unless we share the file descriptor with them.
*/
mode = 0;
oflag = O_RDWR | O_CREAT | O_EXCL;
/*
* Some operating systems allow creating anonymous POSIX shared memory
* objects (e.g. FreeBSD provides the SHM_ANON constant), but this is not
* defined by POSIX, so let's create a unique name.
*
* From Linux's shm_open(3) man-page:
* For portable use, a shared memory object should be identified
* by a name of the form /somename;"
*/
g_string_printf(shm_name, "/qemu-" FMT_pid "-shm-%d", getpid(),
cur_sequence);
fd = shm_open(shm_name->str, oflag, mode);
if (fd < 0) {
error_setg_errno(errp, errno,
"failed to create POSIX shared memory");
return -1;
}
/*
* We have the file descriptor, so we no longer need to expose the
* POSIX shared memory object. However it will remain allocated as long as
* there are file descriptors pointing to it.
*/
shm_unlink(shm_name->str);
if (ftruncate(fd, size) == -1) {
error_setg_errno(errp, errno,
"failed to resize POSIX shared memory to %zu", size);
close(fd);
return -1;
}
return fd;
}

View file

@ -877,3 +877,9 @@ void qemu_win32_map_free(void *ptr, HANDLE h, Error **errp)
}
CloseHandle(h);
}
int qemu_shm_alloc(size_t size, Error **errp)
{
error_setg(errp, "Shared memory is not supported.");
return -1;
}