static void memfd_backend_memory_alloc(HostMemoryBackend *backend, Error **errp) { HostMemoryBackendMemfd *m = MEMORY_BACKEND_MEMFD(backend); char *name; int fd; if (!backend->size) { error_setg(errp, "can't create backend with size 0"); return; } if (host_memory_backend_mr_inited(backend)) { return; } backend->force_prealloc = mem_prealloc; fd = qemu_memfd_create(TYPE_MEMORY_BACKEND_MEMFD, backend->size, m->hugetlb, m->hugetlbsize, m->seal ? F_SEAL_GROW | F_SEAL_SHRINK | F_SEAL_SEAL : 0, errp); if (fd == -1) { return; } name = object_get_canonical_path(OBJECT(backend)); memory_region_init_ram_from_fd(&backend->mr, OBJECT(backend), name, backend->size, true, fd, errp); g_free(name); }
/* * This is a best-effort helper for shared memory allocation, with * optional sealing. The helper will do his best to allocate using * memfd with sealing, but may fallback on other methods without * sealing. */ void *qemu_memfd_alloc(const char *name, size_t size, unsigned int seals, int *fd, Error **errp) { void *ptr; int mfd = qemu_memfd_create(name, size, false, 0, seals, NULL); /* some systems have memfd without sealing */ if (mfd == -1) { mfd = qemu_memfd_create(name, size, false, 0, 0, NULL); } if (mfd == -1) { const char *tmpdir = g_get_tmp_dir(); gchar *fname; fname = g_strdup_printf("%s/memfd-XXXXXX", tmpdir); mfd = mkstemp(fname); unlink(fname); g_free(fname); if (mfd == -1 || ftruncate(mfd, size) == -1) { goto err; } } ptr = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, mfd, 0); if (ptr == MAP_FAILED) { goto err; } *fd = mfd; return ptr; err: error_setg_errno(errp, errno, "failed to allocate shared memory"); if (mfd >= 0) { close(mfd); } return NULL; }