2 * QEMU host POSIX shared memory object backend
4 * Copyright (C) 2024 Red Hat Inc
7 * Stefano Garzarella <sgarzare@redhat.com>
9 * This work is licensed under the terms of the GNU GPL, version 2 or later.
10 * See the COPYING file in the top-level directory.
13 #include "qemu/osdep.h"
14 #include "sysemu/hostmem.h"
15 #include "qapi/error.h"
17 #define TYPE_MEMORY_BACKEND_SHM "memory-backend-shm"
19 OBJECT_DECLARE_SIMPLE_TYPE(HostMemoryBackendShm
, MEMORY_BACKEND_SHM
)
21 struct HostMemoryBackendShm
{
22 HostMemoryBackend parent_obj
;
26 shm_backend_memory_alloc(HostMemoryBackend
*backend
, Error
**errp
)
28 g_autoptr(GString
) shm_name
= g_string_new(NULL
);
29 g_autofree
char *backend_name
= NULL
;
35 error_setg(errp
, "can't create shm backend with size 0");
39 if (!backend
->share
) {
40 error_setg(errp
, "can't create shm backend with `share=off`");
45 * Let's use `mode = 0` because we don't want other processes to open our
46 * memory unless we share the file descriptor with them.
49 oflag
= O_RDWR
| O_CREAT
| O_EXCL
;
50 backend_name
= host_memory_backend_get_name(backend
);
53 * Some operating systems allow creating anonymous POSIX shared memory
54 * objects (e.g. FreeBSD provides the SHM_ANON constant), but this is not
55 * defined by POSIX, so let's create a unique name.
57 * From Linux's shm_open(3) man-page:
58 * For portable use, a shared memory object should be identified
59 * by a name of the form /somename;"
61 g_string_printf(shm_name
, "/qemu-" FMT_pid
"-shm-%s", getpid(),
64 fd
= shm_open(shm_name
->str
, oflag
, mode
);
66 error_setg_errno(errp
, errno
,
67 "failed to create POSIX shared memory");
72 * We have the file descriptor, so we no longer need to expose the
73 * POSIX shared memory object. However it will remain allocated as long as
74 * there are file descriptors pointing to it.
76 shm_unlink(shm_name
->str
);
78 if (ftruncate(fd
, backend
->size
) == -1) {
79 error_setg_errno(errp
, errno
,
80 "failed to resize POSIX shared memory to %" PRIu64
,
86 ram_flags
= RAM_SHARED
;
87 ram_flags
|= backend
->reserve
? 0 : RAM_NORESERVE
;
89 return memory_region_init_ram_from_fd(&backend
->mr
, OBJECT(backend
),
90 backend_name
, backend
->size
,
91 ram_flags
, fd
, 0, errp
);
95 shm_backend_instance_init(Object
*obj
)
97 HostMemoryBackendShm
*m
= MEMORY_BACKEND_SHM(obj
);
99 MEMORY_BACKEND(m
)->share
= true;
103 shm_backend_class_init(ObjectClass
*oc
, void *data
)
105 HostMemoryBackendClass
*bc
= MEMORY_BACKEND_CLASS(oc
);
107 bc
->alloc
= shm_backend_memory_alloc
;
110 static const TypeInfo shm_backend_info
= {
111 .name
= TYPE_MEMORY_BACKEND_SHM
,
112 .parent
= TYPE_MEMORY_BACKEND
,
113 .instance_init
= shm_backend_instance_init
,
114 .class_init
= shm_backend_class_init
,
115 .instance_size
= sizeof(HostMemoryBackendShm
),
118 static void register_types(void)
120 type_register_static(&shm_backend_info
);
123 type_init(register_types
);