hostmem-shm.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. /*
  2. * QEMU host POSIX shared memory object backend
  3. *
  4. * Copyright (C) 2024 Red Hat Inc
  5. *
  6. * Authors:
  7. * Stefano Garzarella <sgarzare@redhat.com>
  8. *
  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.
  11. */
  12. #include "qemu/osdep.h"
  13. #include "system/hostmem.h"
  14. #include "qapi/error.h"
  15. #define TYPE_MEMORY_BACKEND_SHM "memory-backend-shm"
  16. OBJECT_DECLARE_SIMPLE_TYPE(HostMemoryBackendShm, MEMORY_BACKEND_SHM)
  17. struct HostMemoryBackendShm {
  18. HostMemoryBackend parent_obj;
  19. };
  20. static bool
  21. shm_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
  22. {
  23. g_autoptr(GString) shm_name = g_string_new(NULL);
  24. g_autofree char *backend_name = NULL;
  25. uint32_t ram_flags;
  26. int fd, oflag;
  27. mode_t mode;
  28. if (!backend->size) {
  29. error_setg(errp, "can't create shm backend with size 0");
  30. return false;
  31. }
  32. if (!backend->share) {
  33. error_setg(errp, "can't create shm backend with `share=off`");
  34. return false;
  35. }
  36. /*
  37. * Let's use `mode = 0` because we don't want other processes to open our
  38. * memory unless we share the file descriptor with them.
  39. */
  40. mode = 0;
  41. oflag = O_RDWR | O_CREAT | O_EXCL;
  42. backend_name = host_memory_backend_get_name(backend);
  43. /*
  44. * Some operating systems allow creating anonymous POSIX shared memory
  45. * objects (e.g. FreeBSD provides the SHM_ANON constant), but this is not
  46. * defined by POSIX, so let's create a unique name.
  47. *
  48. * From Linux's shm_open(3) man-page:
  49. * For portable use, a shared memory object should be identified
  50. * by a name of the form /somename;"
  51. */
  52. g_string_printf(shm_name, "/qemu-" FMT_pid "-shm-%s", getpid(),
  53. backend_name);
  54. fd = shm_open(shm_name->str, oflag, mode);
  55. if (fd < 0) {
  56. error_setg_errno(errp, errno,
  57. "failed to create POSIX shared memory");
  58. return false;
  59. }
  60. /*
  61. * We have the file descriptor, so we no longer need to expose the
  62. * POSIX shared memory object. However it will remain allocated as long as
  63. * there are file descriptors pointing to it.
  64. */
  65. shm_unlink(shm_name->str);
  66. if (ftruncate(fd, backend->size) == -1) {
  67. error_setg_errno(errp, errno,
  68. "failed to resize POSIX shared memory to %" PRIu64,
  69. backend->size);
  70. close(fd);
  71. return false;
  72. }
  73. ram_flags = RAM_SHARED;
  74. ram_flags |= backend->reserve ? 0 : RAM_NORESERVE;
  75. return memory_region_init_ram_from_fd(&backend->mr, OBJECT(backend),
  76. backend_name, backend->size,
  77. ram_flags, fd, 0, errp);
  78. }
  79. static void
  80. shm_backend_instance_init(Object *obj)
  81. {
  82. HostMemoryBackendShm *m = MEMORY_BACKEND_SHM(obj);
  83. MEMORY_BACKEND(m)->share = true;
  84. }
  85. static void
  86. shm_backend_class_init(ObjectClass *oc, void *data)
  87. {
  88. HostMemoryBackendClass *bc = MEMORY_BACKEND_CLASS(oc);
  89. bc->alloc = shm_backend_memory_alloc;
  90. }
  91. static const TypeInfo shm_backend_info = {
  92. .name = TYPE_MEMORY_BACKEND_SHM,
  93. .parent = TYPE_MEMORY_BACKEND,
  94. .instance_init = shm_backend_instance_init,
  95. .class_init = shm_backend_class_init,
  96. .instance_size = sizeof(HostMemoryBackendShm),
  97. };
  98. static void register_types(void)
  99. {
  100. type_register_static(&shm_backend_info);
  101. }
  102. type_init(register_types);