svn commit: r356512 - in head: sys/kern tests/sys/posixshm
Kyle Evans
kevans at FreeBSD.org
Wed Jan 8 19:08:45 UTC 2020
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());
}
More information about the svn-src-head
mailing list