svn commit: r365624 - head/lib/libc/sys
Kyle Evans
kevans at FreeBSD.org
Fri Sep 11 02:02:17 UTC 2020
Author: kevans
Date: Fri Sep 11 02:02:15 2020
New Revision: 365624
URL: https://svnweb.freebsd.org/changeset/base/365624
Log:
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)
Modified:
head/lib/libc/sys/shm_open.c
Modified: head/lib/libc/sys/shm_open.c
==============================================================================
--- head/lib/libc/sys/shm_open.c Fri Sep 11 02:02:13 2020 (r365623)
+++ head/lib/libc/sys/shm_open.c Fri Sep 11 02:02:15 2020 (r365624)
@@ -81,27 +81,6 @@ shm_create_largepage(const char *path, int flags, int
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;
More information about the svn-src-all
mailing list