Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/uipc_shm.c
Show First 20 Lines • Show All 139 Lines • ▼ Show 20 Lines | |||||
static fo_close_t shm_close; | static fo_close_t shm_close; | ||||
static fo_chmod_t shm_chmod; | static fo_chmod_t shm_chmod; | ||||
static fo_chown_t shm_chown; | static fo_chown_t shm_chown; | ||||
static fo_seek_t shm_seek; | static fo_seek_t shm_seek; | ||||
static fo_fill_kinfo_t shm_fill_kinfo; | static fo_fill_kinfo_t shm_fill_kinfo; | ||||
static fo_mmap_t shm_mmap; | static fo_mmap_t shm_mmap; | ||||
static fo_get_seals_t shm_get_seals; | static fo_get_seals_t shm_get_seals; | ||||
static fo_add_seals_t shm_add_seals; | static fo_add_seals_t shm_add_seals; | ||||
static fo_fallocate_t shm_fallocate; | |||||
static fo_fspacectl_t shm_fspacectl; | static fo_fspacectl_t shm_fspacectl; | ||||
/* File descriptor operations. */ | /* File descriptor operations. */ | ||||
struct fileops shm_ops = { | struct fileops shm_ops = { | ||||
.fo_read = shm_read, | .fo_read = shm_read, | ||||
.fo_write = shm_write, | .fo_write = shm_write, | ||||
.fo_truncate = shm_truncate, | .fo_truncate = shm_truncate, | ||||
.fo_ioctl = shm_ioctl, | .fo_ioctl = shm_ioctl, | ||||
.fo_poll = invfo_poll, | .fo_poll = invfo_poll, | ||||
.fo_kqfilter = invfo_kqfilter, | .fo_kqfilter = invfo_kqfilter, | ||||
.fo_stat = shm_stat, | .fo_stat = shm_stat, | ||||
.fo_close = shm_close, | .fo_close = shm_close, | ||||
.fo_chmod = shm_chmod, | .fo_chmod = shm_chmod, | ||||
.fo_chown = shm_chown, | .fo_chown = shm_chown, | ||||
.fo_sendfile = vn_sendfile, | .fo_sendfile = vn_sendfile, | ||||
.fo_seek = shm_seek, | .fo_seek = shm_seek, | ||||
.fo_fill_kinfo = shm_fill_kinfo, | .fo_fill_kinfo = shm_fill_kinfo, | ||||
.fo_mmap = shm_mmap, | .fo_mmap = shm_mmap, | ||||
.fo_get_seals = shm_get_seals, | .fo_get_seals = shm_get_seals, | ||||
.fo_add_seals = shm_add_seals, | .fo_add_seals = shm_add_seals, | ||||
.fo_fallocate = shm_fallocate, | |||||
.fo_fspacectl = shm_fspacectl, | .fo_fspacectl = shm_fspacectl, | ||||
.fo_flags = DFLAG_PASSABLE | DFLAG_SEEKABLE, | .fo_flags = DFLAG_PASSABLE | DFLAG_SEEKABLE, | ||||
}; | }; | ||||
FEATURE(posix_shm, "POSIX shared memory"); | FEATURE(posix_shm, "POSIX shared memory"); | ||||
static SYSCTL_NODE(_vm, OID_AUTO, largepages, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, | static SYSCTL_NODE(_vm, OID_AUTO, largepages, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, | ||||
""); | ""); | ||||
▲ Show 20 Lines • Show All 1,749 Lines • ▼ Show 20 Lines | shm_fspacectl(struct file *fp, int cmd, off_t offset, off_t len, int flags, | ||||
size_t size; | size_t size; | ||||
int error; | int error; | ||||
/* This assumes that the caller already checked for overflow. */ | /* This assumes that the caller already checked for overflow. */ | ||||
error = 0; | error = 0; | ||||
shmfd = fp->f_data; | shmfd = fp->f_data; | ||||
size = offset + len; | size = offset + len; | ||||
if (cmd != SPACECTL_DEALLOC) | if (cmd != SPACECTL_ALLOC && cmd != SPACECTL_DEALLOC) | ||||
return (EINVAL); | return (EINVAL); | ||||
if (offset < 0 || len < 0 || flags != 0) | if (offset < 0 || len < 0 || (flags & ~SPACECTL_F_SUPPORTED) != 0) | ||||
return (EINVAL); | return (EINVAL); | ||||
if (len == 0) | if (len == 0) | ||||
/* Degenerated case */ | /* Degenerated case */ | ||||
return (0); | return (0); | ||||
/* | /* | ||||
* Just grab the rangelock for the range that we may be attempting to | * Just grab the rangelock for the range that we may be attempting to | ||||
* grow, rather than blocking read/write for regions we won't be | * grow, rather than blocking read/write for regions we won't be | ||||
* touching while this (potential) resize is in progress. Other | * touching while this (potential) resize is in progress. Other | ||||
* attempts to resize the shmfd will have to take a write lock from 0 to | * attempts to resize the shmfd will have to take a write lock from 0 to | ||||
* OFF_MAX, so this being potentially beyond the current usable range of | * OFF_MAX, so this being potentially beyond the current usable range of | ||||
* the shmfd is not necessarily a concern. If other mechanisms are | * the shmfd is not necessarily a concern. If other mechanisms are | ||||
* added to grow a shmfd, this may need to be re-evaluated. | * added to grow a shmfd, this may need to be re-evaluated. | ||||
*/ | */ | ||||
rl_cookie = rangelock_wlock(&shmfd->shm_rl, offset, size, | rl_cookie = rangelock_wlock(&shmfd->shm_rl, offset, size, | ||||
&shmfd->shm_mtx); | &shmfd->shm_mtx); | ||||
switch (cmd) { | switch (cmd) { | ||||
case SPACECTL_ALLOC: | |||||
if (size > shmfd->shm_size && flags & SPACECTL_F_CANEXTEND) { | |||||
error = shm_dotruncate_cookie(shmfd, size, rl_cookie); | |||||
/* | |||||
* Translate to posix_fallocate(2) return value as | |||||
* needed. | |||||
*/ | |||||
if (error == ENOMEM) | |||||
error = ENOSPC; | |||||
} | |||||
break; | |||||
case SPACECTL_DEALLOC: | case SPACECTL_DEALLOC: | ||||
error = shm_deallocate(shmfd, offset, len, flags, rl_cookie, td); | error = shm_deallocate(shmfd, offset, len, flags, rl_cookie, td); | ||||
break; | break; | ||||
default: | default: | ||||
panic("%s: unknown cmd %d", __func__, cmd); | panic("%s: unknown cmd %d", __func__, cmd); | ||||
} | } | ||||
rangelock_unlock(&shmfd->shm_rl, rl_cookie, &shmfd->shm_mtx); | rangelock_unlock(&shmfd->shm_rl, rl_cookie, &shmfd->shm_mtx); | ||||
return (error); | |||||
} | |||||
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; | |||||
/* | |||||
* Just grab the rangelock for the range that we may be attempting to | |||||
* grow, rather than blocking read/write for regions we won't be | |||||
* touching while this (potential) resize is in progress. Other | |||||
* attempts to resize the shmfd will have to take a write lock from 0 to | |||||
* OFF_MAX, so this being potentially beyond the current usable range of | |||||
* the shmfd is not necessarily a concern. If other mechanisms are | |||||
* added to grow a shmfd, this may need to be re-evaluated. | |||||
*/ | |||||
rl_cookie = rangelock_wlock(&shmfd->shm_rl, offset, size, | |||||
&shmfd->shm_mtx); | |||||
if (size > shmfd->shm_size) | |||||
error = shm_dotruncate_cookie(shmfd, size, rl_cookie); | |||||
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); | return (error); | ||||
} | } | ||||
static int | static int | ||||
sysctl_posix_shm_list(SYSCTL_HANDLER_ARGS) | sysctl_posix_shm_list(SYSCTL_HANDLER_ARGS) | ||||
{ | { | ||||
struct shm_mapping *shmm; | struct shm_mapping *shmm; | ||||
struct sbuf sb; | struct sbuf sb; | ||||
▲ Show 20 Lines • Show All 65 Lines • Show Last 20 Lines |