memfd_create: simplify HUGETLB support a little bit
This also fixes a minor issue that was missed in the initial review; the layout of the MFD_HUGE_* flags is actually not 1:1 bit:flag -- it instead borrowed the Linux convention of how this is laid out since it was originally implemented on Linux, the top 6 bits represent the shift required for the requested page size. This allows us to remove the flag <-> pgsize mapping table and simplify the logic just prior to validation of the requested page size. While we're here, fix two small nits: - HUGETLB memfd shouldn't exhibit the SHM_GROW_ON_WRITE behavior. We can only grow largepage shm by appropriately aligned (i.e. requested pagesize) sizes, so it can't work in the typical/sane fashion. Furthermore, Linux does the same, so let's be compatible. - We don't allow MFD_HUGETLB without specifying a pagesize, so no need to check for that later. Reviewed by: kib (slightly earlier version)
This commit is contained in:
parent
0b39e3448a
commit
8b8cf4ece6
@ -81,27 +81,6 @@ shm_create_largepage(const char *path, int flags, int psind, int alloc_policy,
|
||||
return (fd);
|
||||
}
|
||||
|
||||
#define K(x) ((size_t)(x) * 1024)
|
||||
#define M(x) (K(x) * 1024)
|
||||
#define G(x) (M(x) * 1024)
|
||||
static const struct {
|
||||
int mask;
|
||||
size_t pgsize;
|
||||
} mfd_huge_sizes[] = {
|
||||
{ .mask = MFD_HUGE_64KB, .pgsize = K(64) },
|
||||
{ .mask = MFD_HUGE_512KB, .pgsize = K(512) },
|
||||
{ .mask = MFD_HUGE_1MB, .pgsize = M(1) },
|
||||
{ .mask = MFD_HUGE_2MB, .pgsize = M(2) },
|
||||
{ .mask = MFD_HUGE_8MB, .pgsize = M(8) },
|
||||
{ .mask = MFD_HUGE_16MB, .pgsize = M(16) },
|
||||
{ .mask = MFD_HUGE_32MB, .pgsize = M(32) },
|
||||
{ .mask = MFD_HUGE_256MB, .pgsize = M(256) },
|
||||
{ .mask = MFD_HUGE_512MB, .pgsize = M(512) },
|
||||
{ .mask = MFD_HUGE_1GB, .pgsize = G(1) },
|
||||
{ .mask = MFD_HUGE_2GB, .pgsize = G(2) },
|
||||
{ .mask = MFD_HUGE_16GB, .pgsize = G(16) },
|
||||
};
|
||||
|
||||
/*
|
||||
* 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
|
||||
@ -111,9 +90,9 @@ int
|
||||
memfd_create(const char *name, unsigned int flags)
|
||||
{
|
||||
char memfd_name[NAME_MAX + 1];
|
||||
size_t namelen, *pgs;
|
||||
size_t namelen, *pgs, pgsize;
|
||||
struct shm_largepage_conf slc;
|
||||
int error, fd, i, npgs, oflags, pgidx, saved_errno, shmflags;
|
||||
int error, fd, npgs, oflags, pgidx, saved_errno, shmflags;
|
||||
|
||||
if (name == NULL) {
|
||||
errno = EBADF;
|
||||
@ -130,8 +109,7 @@ memfd_create(const char *name, unsigned int flags)
|
||||
return (-1);
|
||||
}
|
||||
/* Size specified but no HUGETLB. */
|
||||
if (((flags & MFD_HUGE_MASK) != 0 && (flags & MFD_HUGETLB) == 0) ||
|
||||
__bitcount(flags & MFD_HUGE_MASK) > 1) {
|
||||
if ((flags & MFD_HUGE_MASK) != 0 && (flags & MFD_HUGETLB) == 0) {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
@ -139,13 +117,15 @@ memfd_create(const char *name, unsigned int flags)
|
||||
/* 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 = SHM_GROW_ON_WRITE;
|
||||
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);
|
||||
@ -160,25 +140,14 @@ memfd_create(const char *name, unsigned int flags)
|
||||
error = getpagesizes(pgs, npgs);
|
||||
if (error == -1)
|
||||
goto clean;
|
||||
if ((flags & MFD_HUGE_MASK) == 0) {
|
||||
if (npgs == 1) {
|
||||
errno = EOPNOTSUPP;
|
||||
goto clean;
|
||||
}
|
||||
pgidx = 1;
|
||||
} else {
|
||||
for (i = 0; i < nitems(mfd_huge_sizes); i++) {
|
||||
if (mfd_huge_sizes[i].mask == (flags & MFD_HUGE_MASK))
|
||||
break;
|
||||
}
|
||||
for (pgidx = 0; pgidx < npgs; pgidx++) {
|
||||
if (mfd_huge_sizes[i].pgsize == pgs[pgidx])
|
||||
break;
|
||||
}
|
||||
if (pgidx == npgs) {
|
||||
errno = EOPNOTSUPP;
|
||||
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;
|
||||
|
Loading…
Reference in New Issue
Block a user