util: add memfd helpers
Add qemu_memfd_alloc/free() helpers. The function helps to allocate and seal shared memory. Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Tested-by: Thibaut Collet <thibaut.collet@6wind.com>
This commit is contained in:
parent
f04cf9239a
commit
d3592199ba
@ -17,4 +17,8 @@
|
||||
#define F_SEAL_WRITE 0x0008 /* prevent writes */
|
||||
#endif
|
||||
|
||||
void *qemu_memfd_alloc(const char *name, size_t size, unsigned int seals,
|
||||
int *fd);
|
||||
void qemu_memfd_free(void *ptr, size_t size, int fd);
|
||||
|
||||
#endif /* QEMU_MEMFD_H */
|
||||
|
72
util/memfd.c
72
util/memfd.c
@ -27,6 +27,11 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib/gprintf.h>
|
||||
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include "qemu/memfd.h"
|
||||
|
||||
#ifdef CONFIG_MEMFD
|
||||
@ -35,7 +40,7 @@
|
||||
#include <sys/syscall.h>
|
||||
#include <asm/unistd.h>
|
||||
|
||||
inline static int memfd_create(const char *name, unsigned int flags)
|
||||
static int memfd_create(const char *name, unsigned int flags)
|
||||
{
|
||||
#ifdef __NR_memfd_create
|
||||
return syscall(__NR_memfd_create, name, flags);
|
||||
@ -52,3 +57,68 @@ inline static int memfd_create(const char *name, unsigned int flags)
|
||||
#ifndef MFD_ALLOW_SEALING
|
||||
#define MFD_ALLOW_SEALING 0x0002U
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
void *ptr;
|
||||
int mfd = -1;
|
||||
|
||||
*fd = -1;
|
||||
|
||||
#ifdef CONFIG_LINUX
|
||||
if (seals) {
|
||||
mfd = memfd_create(name, MFD_ALLOW_SEALING | MFD_CLOEXEC);
|
||||
}
|
||||
|
||||
if (mfd == -1) {
|
||||
/* some systems have memfd without sealing */
|
||||
mfd = memfd_create(name, MFD_CLOEXEC);
|
||||
seals = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (mfd != -1) {
|
||||
if (ftruncate(mfd, size) == -1) {
|
||||
perror("ftruncate");
|
||||
close(mfd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (seals && fcntl(mfd, F_ADD_SEALS, seals) == -1) {
|
||||
perror("fcntl");
|
||||
close(mfd);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
perror("memfd");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ptr = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, mfd, 0);
|
||||
if (ptr == MAP_FAILED) {
|
||||
perror("mmap");
|
||||
close(mfd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*fd = mfd;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void qemu_memfd_free(void *ptr, size_t size, int fd)
|
||||
{
|
||||
if (ptr) {
|
||||
munmap(ptr, size);
|
||||
}
|
||||
|
||||
if (fd != -1) {
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user