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>