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