#ifdef __NR_memfd_create
return syscall(__NR_memfd_create, name, flags);
#else
+ errno = ENOSYS;
return -1;
#endif
}
#endif
-#ifndef MFD_CLOEXEC
-#define MFD_CLOEXEC 0x0001U
-#endif
-
-#ifndef MFD_ALLOW_SEALING
-#define MFD_ALLOW_SEALING 0x0002U
-#endif
-
-#ifndef MFD_HUGETLB
-#define MFD_HUGETLB 0x0004U
-#endif
-
-#ifndef MFD_HUGE_SHIFT
-#define MFD_HUGE_SHIFT 26
-#endif
-
int qemu_memfd_create(const char *name, size_t size, bool hugetlb,
uint64_t hugetlbsize, unsigned int seals, Error **errp)
{
int htsize = hugetlbsize ? ctz64(hugetlbsize) : 0;
- if (htsize && 1 << htsize != hugetlbsize) {
+ if (htsize && 1ULL << htsize != hugetlbsize) {
error_setg(errp, "Hugepage size must be a power of 2");
return -1;
}
}
mfd = memfd_create(name, flags);
if (mfd < 0) {
+ error_setg_errno(errp, errno,
+ "failed to create memfd with flags 0x%x", flags);
goto err;
}
if (ftruncate(mfd, size) == -1) {
+ error_setg_errno(errp, errno, "failed to resize memfd to %zu", size);
goto err;
}
if (seals && fcntl(mfd, F_ADD_SEALS, seals) == -1) {
+ error_setg_errno(errp, errno, "failed to add seals 0x%x", seals);
goto err;
}
if (mfd >= 0) {
close(mfd);
}
+#else
+ error_setg_errno(errp, ENOSYS, "failed to create memfd");
#endif
- error_setg_errno(errp, errno, "failed to create memfd");
return -1;
}
MEMFD_TODO
};
-bool qemu_memfd_check(void)
+/**
+ * qemu_memfd_alloc_check():
+ *
+ * Check if qemu_memfd_alloc() can allocate, including using a
+ * fallback implementation when host doesn't support memfd.
+ */
+bool qemu_memfd_alloc_check(void)
{
static int memfd_check = MEMFD_TODO;
int fd;
void *ptr;
+ fd = -1;
ptr = qemu_memfd_alloc("test", 4096, 0, &fd, NULL);
memfd_check = ptr ? MEMFD_OK : MEMFD_KO;
qemu_memfd_free(ptr, 4096, fd);
return memfd_check == MEMFD_OK;
}
+
+/**
+ * qemu_memfd_check():
+ *
+ * Check if host supports memfd.
+ */
+bool qemu_memfd_check(unsigned int flags)
+{
+#ifdef CONFIG_LINUX
+ int mfd = memfd_create("test", flags | MFD_CLOEXEC);
+
+ if (mfd >= 0) {
+ close(mfd);
+ return true;
+ }
+#endif
+
+ return false;
+}