aboutsummaryrefslogtreecommitdiff
path: root/sys/kern/uipc_shm.c
diff options
context:
space:
mode:
authorKyle Evans <kevans@FreeBSD.org>2020-01-08 19:08:44 +0000
committerKyle Evans <kevans@FreeBSD.org>2020-01-08 19:08:44 +0000
commitf10405323ab1ac3b4bad100c6e746395d02f392a (patch)
treecf3e58b88d89031f4177cc5050bb458986fd1527 /sys/kern/uipc_shm.c
parent7ce40722673b6392e82abb7330665d3d235e7cac (diff)
downloadsrc-f10405323ab1ac3b4bad100c6e746395d02f392a.tar.gz
src-f10405323ab1ac3b4bad100c6e746395d02f392a.zip
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
Notes
Notes: svn path=/head/; revision=356512
Diffstat (limited to 'sys/kern/uipc_shm.c')
-rw-r--r--sys/kern/uipc_shm.c28
1 files changed, 28 insertions, 0 deletions
diff --git a/sys/kern/uipc_shm.c b/sys/kern/uipc_shm.c
index 435da35a5b28..861e26c85834 100644
--- a/sys/kern/uipc_shm.c
+++ b/sys/kern/uipc_shm.c
@@ -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
};
@@ -1438,6 +1440,32 @@ shm_get_seals(struct file *fp, int *seals)
}
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
sysctl_posix_shm_list(SYSCTL_HANDLER_ARGS)
{
struct shm_mapping *shmm;