diff options
author | Kyle Evans <kevans@FreeBSD.org> | 2020-01-08 19:08:44 +0000 |
---|---|---|
committer | Kyle Evans <kevans@FreeBSD.org> | 2020-01-08 19:08:44 +0000 |
commit | f10405323ab1ac3b4bad100c6e746395d02f392a (patch) | |
tree | cf3e58b88d89031f4177cc5050bb458986fd1527 /sys/kern/uipc_shm.c | |
parent | 7ce40722673b6392e82abb7330665d3d235e7cac (diff) | |
download | src-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.c | 28 |
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; |