Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 8 Jan 2020 19:08:44 +0000 (UTC)
From:      Kyle Evans <kevans@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r356512 - in head: sys/kern tests/sys/posixshm
Message-ID:  <202001081908.008J8ioq035968@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kevans
Date: Wed Jan  8 19:08:44 2020
New Revision: 356512
URL: https://svnweb.freebsd.org/changeset/base/356512

Log:
  posixshm: implement posix_fallocate(2)
  
  Linux expects to be able to use posix_fallocate(2) on a memfd. Other places
  would use this with shm_open(2) to act as a smarter ftruncate(2).
  
  Test has been added to go along with this.
  
  Reviewed by:	kib (earlier version)
  Differential Revision:	https://reviews.freebsd.org/D23042

Modified:
  head/sys/kern/uipc_shm.c
  head/tests/sys/posixshm/posixshm_test.c

Modified: head/sys/kern/uipc_shm.c
==============================================================================
--- head/sys/kern/uipc_shm.c	Wed Jan  8 19:06:22 2020	(r356511)
+++ head/sys/kern/uipc_shm.c	Wed Jan  8 19:08:44 2020	(r356512)
@@ -138,6 +138,7 @@ static fo_fill_kinfo_t	shm_fill_kinfo;
 static fo_mmap_t	shm_mmap;
 static fo_get_seals_t	shm_get_seals;
 static fo_add_seals_t	shm_add_seals;
+static fo_fallocate_t	shm_fallocate;
 
 /* File descriptor operations. */
 struct fileops shm_ops = {
@@ -157,6 +158,7 @@ struct fileops shm_ops = {
 	.fo_mmap = shm_mmap,
 	.fo_get_seals = shm_get_seals,
 	.fo_add_seals = shm_add_seals,
+	.fo_fallocate = shm_fallocate,
 	.fo_flags = DFLAG_PASSABLE | DFLAG_SEEKABLE
 };
 
@@ -1435,6 +1437,32 @@ shm_get_seals(struct file *fp, int *seals)
 	shmfd = fp->f_data;
 	*seals = shmfd->shm_seals;
 	return (0);
+}
+
+static int
+shm_fallocate(struct file *fp, off_t offset, off_t len, struct thread *td)
+{
+	void *rl_cookie;
+	struct shmfd *shmfd;
+	size_t size;
+	int error;
+
+	/* This assumes that the caller already checked for overflow. */
+	error = 0;
+	shmfd = fp->f_data;
+	size = offset + len;
+	rl_cookie = rangelock_wlock(&shmfd->shm_rl, 0, OFF_MAX,
+	    &shmfd->shm_mtx);
+	if (size > shmfd->shm_size) {
+		VM_OBJECT_WLOCK(shmfd->shm_object);
+		error = shm_dotruncate_locked(shmfd, size, rl_cookie);
+		VM_OBJECT_WUNLOCK(shmfd->shm_object);
+	}
+	rangelock_unlock(&shmfd->shm_rl, rl_cookie, &shmfd->shm_mtx);
+	/* Translate to posix_fallocate(2) return value as needed. */
+	if (error == ENOMEM)
+		error = ENOSPC;
+	return (error);
 }
 
 static int

Modified: head/tests/sys/posixshm/posixshm_test.c
==============================================================================
--- head/tests/sys/posixshm/posixshm_test.c	Wed Jan  8 19:06:22 2020	(r356511)
+++ head/tests/sys/posixshm/posixshm_test.c	Wed Jan  8 19:08:44 2020	(r356512)
@@ -918,6 +918,44 @@ ATF_TC_BODY(mode, tc)
 	umask(restore_mask);
 }
 
+ATF_TC_WITHOUT_HEAD(fallocate);
+ATF_TC_BODY(fallocate, tc)
+{
+	struct stat st;
+	int error, fd, sz;
+
+	/*
+	 * Primitive test case for posix_fallocate with shmd.  Effectively
+	 * expected to work like a smarter ftruncate that will grow the region
+	 * as needed in a race-free way.
+	 */
+	fd = shm_open(SHM_ANON, O_RDWR, 0666);
+	ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno);
+	/* Set the initial size. */
+	sz = 32;
+	ATF_REQUIRE(ftruncate(fd, sz) == 0);
+
+	/* Now grow it. */
+	error = 0;
+	sz *= 2;
+	ATF_REQUIRE_MSG((error = posix_fallocate(fd, 0, sz)) == 0,
+	    "posix_fallocate failed; error=%d", error);
+	ATF_REQUIRE(fstat(fd, &st) == 0);
+	ATF_REQUIRE(st.st_size == sz);
+	/* Attempt to shrink it; should succeed, but not change the size. */
+	ATF_REQUIRE_MSG((error = posix_fallocate(fd, 0, sz / 2)) == 0,
+	    "posix_fallocate failed; error=%d", error);
+	ATF_REQUIRE(fstat(fd, &st) == 0);
+	ATF_REQUIRE(st.st_size == sz);
+	/* Grow it using an offset of sz and len of sz. */
+	ATF_REQUIRE_MSG((error = posix_fallocate(fd, sz, sz)) == 0,
+	    "posix_fallocate failed; error=%d", error);
+	ATF_REQUIRE(fstat(fd, &st) == 0);
+	ATF_REQUIRE(st.st_size == (sz * 2));
+
+	close(fd);
+}
+
 ATF_TP_ADD_TCS(tp)
 {
 
@@ -951,6 +989,7 @@ ATF_TP_ADD_TCS(tp)
 	ATF_TP_ADD_TC(tp, object_resize);
 	ATF_TP_ADD_TC(tp, cloexec);
 	ATF_TP_ADD_TC(tp, mode);
+	ATF_TP_ADD_TC(tp, fallocate);
 
 	return (atf_no_error());
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202001081908.008J8ioq035968>