Changeset View
Changeset View
Standalone View
Standalone View
lib/libc/sys/shm_open.c
- This file was copied to lib/libc/gen/memfd_create.c.
Show All 28 Lines | |||||
*/ | */ | ||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/filio.h> | #include <sys/filio.h> | ||||
#include <sys/mman.h> | #include <sys/mman.h> | ||||
#include <errno.h> | #include <errno.h> | ||||
#include <fcntl.h> | #include <fcntl.h> | ||||
#include <limits.h> | |||||
#include <stdlib.h> | |||||
#include <stdio.h> | |||||
#include <string.h> | #include <string.h> | ||||
#include <unistd.h> | #include <unistd.h> | ||||
#include "libc_private.h" | #include "libc_private.h" | ||||
__weak_reference(shm_open, _shm_open); | __weak_reference(shm_open, _shm_open); | ||||
__weak_reference(shm_open, __sys_shm_open); | __weak_reference(shm_open, __sys_shm_open); | ||||
#define MEMFD_NAME_PREFIX "memfd:" | |||||
int | int | ||||
shm_open(const char *path, int flags, mode_t mode) | shm_open(const char *path, int flags, mode_t mode) | ||||
{ | { | ||||
return (__sys_shm_open2(path, flags | O_CLOEXEC, mode, 0, NULL)); | return (__sys_shm_open2(path, flags | O_CLOEXEC, mode, 0, NULL)); | ||||
} | } | ||||
int | int | ||||
shm_create_largepage(const char *path, int flags, int psind, int alloc_policy, | shm_create_largepage(const char *path, int flags, int psind, int alloc_policy, | ||||
mode_t mode) | mode_t mode) | ||||
{ | { | ||||
struct shm_largepage_conf slc; | struct shm_largepage_conf slc; | ||||
Show All 9 Lines | shm_create_largepage(const char *path, int flags, int psind, int alloc_policy, | ||||
error = ioctl(fd, FIOSSHMLPGCNF, &slc); | error = ioctl(fd, FIOSSHMLPGCNF, &slc); | ||||
if (error == -1) { | if (error == -1) { | ||||
saved_errno = errno; | saved_errno = errno; | ||||
close(fd); | close(fd); | ||||
errno = saved_errno; | errno = saved_errno; | ||||
return (-1); | return (-1); | ||||
} | } | ||||
return (fd); | return (fd); | ||||
} | |||||
/* | |||||
* The path argument is passed to the kernel, but the kernel doesn't currently | |||||
* do anything with it. Linux exposes it in linprocfs for debugging purposes | |||||
* only, but our kernel currently will not do the same. | |||||
*/ | |||||
int | |||||
memfd_create(const char *name, unsigned int flags) | |||||
{ | |||||
char memfd_name[NAME_MAX + 1]; | |||||
size_t namelen, *pgs, pgsize; | |||||
struct shm_largepage_conf slc; | |||||
int error, fd, npgs, oflags, pgidx, saved_errno, shmflags; | |||||
if (name == NULL) { | |||||
errno = EBADF; | |||||
return (-1); | |||||
} | |||||
namelen = strlen(name); | |||||
if (namelen + sizeof(MEMFD_NAME_PREFIX) - 1 > NAME_MAX) { | |||||
errno = EINVAL; | |||||
return (-1); | |||||
} | |||||
if ((flags & ~(MFD_CLOEXEC | MFD_ALLOW_SEALING | MFD_HUGETLB | | |||||
MFD_HUGE_MASK)) != 0) { | |||||
errno = EINVAL; | |||||
return (-1); | |||||
} | |||||
/* Size specified but no HUGETLB. */ | |||||
if ((flags & MFD_HUGE_MASK) != 0 && (flags & MFD_HUGETLB) == 0) { | |||||
errno = EINVAL; | |||||
return (-1); | |||||
} | |||||
/* We've already validated that we're sufficiently sized. */ | |||||
snprintf(memfd_name, NAME_MAX + 1, "%s%s", MEMFD_NAME_PREFIX, name); | |||||
oflags = O_RDWR; | |||||
shmflags = 0; | |||||
if ((flags & MFD_CLOEXEC) != 0) | |||||
oflags |= O_CLOEXEC; | |||||
if ((flags & MFD_ALLOW_SEALING) != 0) | |||||
shmflags |= SHM_ALLOW_SEALING; | |||||
if ((flags & MFD_HUGETLB) != 0) | |||||
shmflags |= SHM_LARGEPAGE; | |||||
else | |||||
shmflags |= SHM_GROW_ON_WRITE; | |||||
fd = __sys_shm_open2(SHM_ANON, oflags, 0, shmflags, memfd_name); | |||||
if (fd == -1 || (flags & MFD_HUGETLB) == 0) | |||||
return (fd); | |||||
pgs = NULL; | |||||
npgs = getpagesizes(NULL, 0); | |||||
if (npgs == -1) | |||||
goto clean; | |||||
pgs = calloc(npgs, sizeof(size_t)); | |||||
if (pgs == NULL) | |||||
goto clean; | |||||
error = getpagesizes(pgs, npgs); | |||||
if (error == -1) | |||||
goto clean; | |||||
pgsize = (size_t)1 << ((flags & MFD_HUGE_MASK) >> MFD_HUGE_SHIFT); | |||||
for (pgidx = 0; pgidx < npgs; pgidx++) { | |||||
if (pgsize == pgs[pgidx]) | |||||
break; | |||||
} | |||||
if (pgidx == npgs) { | |||||
errno = EOPNOTSUPP; | |||||
goto clean; | |||||
} | |||||
free(pgs); | |||||
pgs = NULL; | |||||
memset(&slc, 0, sizeof(slc)); | |||||
slc.psind = pgidx; | |||||
slc.alloc_policy = SHM_LARGEPAGE_ALLOC_DEFAULT; | |||||
error = ioctl(fd, FIOSSHMLPGCNF, &slc); | |||||
if (error == -1) | |||||
goto clean; | |||||
return (fd); | |||||
clean: | |||||
saved_errno = errno; | |||||
close(fd); | |||||
free(pgs); | |||||
errno = saved_errno; | |||||
return (-1); | |||||
} | } |