Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/uipc_shm.c
Show First 20 Lines • Show All 67 Lines • ▼ Show 20 Lines | |||||
#include <sys/jail.h> | #include <sys/jail.h> | ||||
#include <sys/ktrace.h> | #include <sys/ktrace.h> | ||||
#include <sys/lock.h> | #include <sys/lock.h> | ||||
#include <sys/malloc.h> | #include <sys/malloc.h> | ||||
#include <sys/mman.h> | #include <sys/mman.h> | ||||
#include <sys/mutex.h> | #include <sys/mutex.h> | ||||
#include <sys/priv.h> | #include <sys/priv.h> | ||||
#include <sys/proc.h> | #include <sys/proc.h> | ||||
#include <sys/racct.h> | |||||
#include <sys/refcount.h> | #include <sys/refcount.h> | ||||
#include <sys/resourcevar.h> | #include <sys/resourcevar.h> | ||||
#include <sys/rwlock.h> | #include <sys/rwlock.h> | ||||
#include <sys/sbuf.h> | #include <sys/sbuf.h> | ||||
#include <sys/stat.h> | #include <sys/stat.h> | ||||
#include <sys/syscallsubr.h> | #include <sys/syscallsubr.h> | ||||
#include <sys/sysctl.h> | #include <sys/sysctl.h> | ||||
#include <sys/sysproto.h> | #include <sys/sysproto.h> | ||||
Show All 36 Lines | |||||
static dev_t shm_dev_ino; | static dev_t shm_dev_ino; | ||||
#define SHM_HASH(fnv) (&shm_dictionary[(fnv) & shm_hash]) | #define SHM_HASH(fnv) (&shm_dictionary[(fnv) & shm_hash]) | ||||
static void shm_init(void *arg); | static void shm_init(void *arg); | ||||
static void shm_insert(char *path, Fnv32_t fnv, struct shmfd *shmfd); | static void shm_insert(char *path, Fnv32_t fnv, struct shmfd *shmfd); | ||||
static struct shmfd *shm_lookup(char *path, Fnv32_t fnv); | static struct shmfd *shm_lookup(char *path, Fnv32_t fnv); | ||||
static int shm_remove(char *path, Fnv32_t fnv, struct ucred *ucred); | static int shm_remove(char *path, Fnv32_t fnv, struct ucred *ucred); | ||||
static int shm_dotruncate_cookie(struct shmfd *shmfd, off_t length, | static int shm_dotruncate_cookie(struct thread *td, struct shmfd *shmfd, | ||||
void *rl_cookie); | off_t length, void *rl_cookie); | ||||
static int shm_dotruncate_locked(struct shmfd *shmfd, off_t length, | static int shm_dotruncate_locked(struct thread *td, struct shmfd *shmfd, | ||||
void *rl_cookie); | off_t length, void *rl_cookie); | ||||
static int shm_copyin_path(struct thread *td, const char *userpath_in, | static int shm_copyin_path(struct thread *td, const char *userpath_in, | ||||
char **path_out); | char **path_out); | ||||
static fo_rdwr_t shm_read; | static fo_rdwr_t shm_read; | ||||
static fo_rdwr_t shm_write; | static fo_rdwr_t shm_write; | ||||
static fo_truncate_t shm_truncate; | static fo_truncate_t shm_truncate; | ||||
static fo_ioctl_t shm_ioctl; | static fo_ioctl_t shm_ioctl; | ||||
static fo_stat_t shm_stat; | static fo_stat_t shm_stat; | ||||
▲ Show 20 Lines • Show All 305 Lines • ▼ Show 20 Lines | rl_cookie = rangelock_wlock(&shmfd->shm_rl, uio->uio_offset, | ||||
size, &shmfd->shm_mtx); | size, &shmfd->shm_mtx); | ||||
} | } | ||||
if ((shmfd->shm_seals & F_SEAL_WRITE) != 0) { | if ((shmfd->shm_seals & F_SEAL_WRITE) != 0) { | ||||
error = EPERM; | error = EPERM; | ||||
} else { | } else { | ||||
error = 0; | error = 0; | ||||
if ((shmfd->shm_flags & SHM_GROW_ON_WRITE) != 0 && | if ((shmfd->shm_flags & SHM_GROW_ON_WRITE) != 0 && | ||||
size > shmfd->shm_size) { | size > shmfd->shm_size) { | ||||
error = shm_dotruncate_cookie(shmfd, size, rl_cookie); | error = shm_dotruncate_cookie(td, shmfd, size, rl_cookie); | ||||
} | } | ||||
if (error == 0) | if (error == 0) | ||||
error = uiomove_object(shmfd->shm_object, | error = uiomove_object(shmfd->shm_object, | ||||
shmfd->shm_size, uio); | shmfd->shm_size, uio); | ||||
} | } | ||||
rangelock_unlock(&shmfd->shm_rl, rl_cookie, &shmfd->shm_mtx); | rangelock_unlock(&shmfd->shm_rl, rl_cookie, &shmfd->shm_mtx); | ||||
foffset_unlock_uio(fp, uio, flags); | foffset_unlock_uio(fp, uio, flags); | ||||
return (error); | return (error); | ||||
Show All 9 Lines | |||||
#endif | #endif | ||||
shmfd = fp->f_data; | shmfd = fp->f_data; | ||||
#ifdef MAC | #ifdef MAC | ||||
error = mac_posixshm_check_truncate(active_cred, fp->f_cred, shmfd); | error = mac_posixshm_check_truncate(active_cred, fp->f_cred, shmfd); | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
#endif | #endif | ||||
return (shm_dotruncate(shmfd, length)); | return (shm_dotruncate(td, shmfd, length)); | ||||
} | } | ||||
int | int | ||||
shm_ioctl(struct file *fp, u_long com, void *data, struct ucred *active_cred, | shm_ioctl(struct file *fp, u_long com, void *data, struct ucred *active_cred, | ||||
struct thread *td) | struct thread *td) | ||||
{ | { | ||||
struct shmfd *shmfd; | struct shmfd *shmfd; | ||||
struct shm_largepage_conf *conf; | struct shm_largepage_conf *conf; | ||||
▲ Show 20 Lines • Show All 134 Lines • ▼ Show 20 Lines | |||||
out: | out: | ||||
if (error != 0) | if (error != 0) | ||||
free(path, M_SHMFD); | free(path, M_SHMFD); | ||||
return (error); | return (error); | ||||
} | } | ||||
static int | static int | ||||
shm_dotruncate_locked(struct shmfd *shmfd, off_t length, void *rl_cookie) | shm_dotruncate_locked(struct thread *td, struct shmfd *shmfd, off_t length, void *rl_cookie) | ||||
{ | { | ||||
vm_object_t object; | vm_object_t object; | ||||
vm_page_t m; | vm_page_t m; | ||||
vm_pindex_t idx, nobjsize; | vm_pindex_t idx, nobjsize; | ||||
vm_ooffset_t delta; | vm_ooffset_t delta; | ||||
int base, rv; | int base, rv; | ||||
KASSERT(length >= 0, ("shm_dotruncate: length < 0")); | KASSERT(length >= 0, ("shm_dotruncate: length < 0")); | ||||
▲ Show 20 Lines • Show All 65 Lines • ▼ Show 20 Lines | retry: | ||||
if (nobjsize < object->size) | if (nobjsize < object->size) | ||||
vm_object_page_remove(object, nobjsize, object->size, | vm_object_page_remove(object, nobjsize, object->size, | ||||
0); | 0); | ||||
/* Free the swap accounted for shm */ | /* Free the swap accounted for shm */ | ||||
swap_release_by_cred(delta, object->cred); | swap_release_by_cred(delta, object->cred); | ||||
object->charge -= delta; | object->charge -= delta; | ||||
#ifdef RACCT | |||||
if (racct_enable) { | |||||
racct_sub_cred(object->cred, RACCT_SHMSIZE, shmfd->shm_size - length); | |||||
} | |||||
#endif | |||||
} else { | } else { | ||||
if ((shmfd->shm_seals & F_SEAL_GROW) != 0) | if ((shmfd->shm_seals & F_SEAL_GROW) != 0) | ||||
return (EPERM); | return (EPERM); | ||||
#ifdef RACCT | |||||
if (racct_enable) { | |||||
PROC_LOCK(td->td_proc); | |||||
if (racct_add(td->td_proc, RACCT_SHMSIZE, length - shmfd->shm_size)) { | |||||
PROC_UNLOCK(td->td_proc); | |||||
return (ENOMEM); | |||||
} | |||||
PROC_UNLOCK(td->td_proc); | |||||
} | |||||
#endif | |||||
/* Try to reserve additional swap space. */ | /* Try to reserve additional swap space. */ | ||||
delta = IDX_TO_OFF(nobjsize - object->size); | delta = IDX_TO_OFF(nobjsize - object->size); | ||||
if (!swap_reserve_by_cred(delta, object->cred)) | if (!swap_reserve_by_cred(delta, object->cred)) { | ||||
#ifdef RACCT | |||||
if (racct_enable) { | |||||
racct_sub_cred(object->cred, RACCT_SHMSIZE, length - shmfd->shm_size); | |||||
} | |||||
#endif | |||||
return (ENOMEM); | return (ENOMEM); | ||||
} | |||||
object->charge += delta; | object->charge += delta; | ||||
} | } | ||||
shmfd->shm_size = length; | shmfd->shm_size = length; | ||||
mtx_lock(&shm_timestamp_lock); | mtx_lock(&shm_timestamp_lock); | ||||
vfs_timestamp(&shmfd->shm_ctime); | vfs_timestamp(&shmfd->shm_ctime); | ||||
shmfd->shm_mtime = shmfd->shm_ctime; | shmfd->shm_mtime = shmfd->shm_ctime; | ||||
mtx_unlock(&shm_timestamp_lock); | mtx_unlock(&shm_timestamp_lock); | ||||
object->size = nobjsize; | object->size = nobjsize; | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
shm_dotruncate_largepage(struct shmfd *shmfd, off_t length, void *rl_cookie) | shm_dotruncate_largepage(struct thread *td, struct shmfd *shmfd, off_t length, void *rl_cookie) | ||||
{ | { | ||||
vm_object_t object; | vm_object_t object; | ||||
vm_page_t m; | vm_page_t m; | ||||
vm_pindex_t newobjsz, oldobjsz; | vm_pindex_t newobjsz, oldobjsz; | ||||
int aflags, error, i, psind, try; | int aflags, error, i, psind, try; | ||||
KASSERT(length >= 0, ("shm_dotruncate: length < 0")); | KASSERT(length >= 0, ("shm_dotruncate: length < 0")); | ||||
object = shmfd->shm_object; | object = shmfd->shm_object; | ||||
Show All 22 Lines | #if 0 | ||||
shmfd->shm_size = length; | shmfd->shm_size = length; | ||||
return (0); | return (0); | ||||
#endif | #endif | ||||
} | } | ||||
if ((shmfd->shm_seals & F_SEAL_GROW) != 0) | if ((shmfd->shm_seals & F_SEAL_GROW) != 0) | ||||
return (EPERM); | return (EPERM); | ||||
#ifdef RACCT | |||||
if (racct_enable) { | |||||
PROC_LOCK(td->td_proc); | |||||
if (racct_add(td->td_proc, RACCT_SHMSIZE, length - shmfd->shm_size)) { | |||||
PROC_UNLOCK(td->td_proc); | |||||
return (ENOMEM); | |||||
} | |||||
PROC_UNLOCK(td->td_proc); | |||||
} | |||||
#endif | |||||
aflags = VM_ALLOC_NORMAL | VM_ALLOC_ZERO; | aflags = VM_ALLOC_NORMAL | VM_ALLOC_ZERO; | ||||
if (shmfd->shm_lp_alloc_policy == SHM_LARGEPAGE_ALLOC_NOWAIT) | if (shmfd->shm_lp_alloc_policy == SHM_LARGEPAGE_ALLOC_NOWAIT) | ||||
aflags |= VM_ALLOC_WAITFAIL; | aflags |= VM_ALLOC_WAITFAIL; | ||||
try = 0; | try = 0; | ||||
/* | /* | ||||
* Extend shmfd and object, keeping all already fully | * Extend shmfd and object, keeping all already fully | ||||
* allocated large pages intact even on error, because dropped | * allocated large pages intact even on error, because dropped | ||||
* object lock might allowed mapping of them. | * object lock might allowed mapping of them. | ||||
*/ | */ | ||||
while (object->size < newobjsz) { | while (object->size < newobjsz) { | ||||
m = vm_page_alloc_contig(object, object->size, aflags, | m = vm_page_alloc_contig(object, object->size, aflags, | ||||
pagesizes[psind] / PAGE_SIZE, 0, ~0, | pagesizes[psind] / PAGE_SIZE, 0, ~0, | ||||
pagesizes[psind], 0, | pagesizes[psind], 0, | ||||
VM_MEMATTR_DEFAULT); | VM_MEMATTR_DEFAULT); | ||||
if (m == NULL) { | if (m == NULL) { | ||||
VM_OBJECT_WUNLOCK(object); | VM_OBJECT_WUNLOCK(object); | ||||
if (shmfd->shm_lp_alloc_policy == | if (shmfd->shm_lp_alloc_policy == | ||||
SHM_LARGEPAGE_ALLOC_NOWAIT || | SHM_LARGEPAGE_ALLOC_NOWAIT || | ||||
(shmfd->shm_lp_alloc_policy == | (shmfd->shm_lp_alloc_policy == | ||||
SHM_LARGEPAGE_ALLOC_DEFAULT && | SHM_LARGEPAGE_ALLOC_DEFAULT && | ||||
try >= largepage_reclaim_tries)) { | try >= largepage_reclaim_tries)) { | ||||
#ifdef RACCT | |||||
if (racct_enable) { | |||||
racct_sub_cred(object->cred, RACCT_SHMSIZE, | |||||
length - shmfd->shm_size); | |||||
} | |||||
#endif | |||||
VM_OBJECT_WLOCK(object); | VM_OBJECT_WLOCK(object); | ||||
return (ENOMEM); | return (ENOMEM); | ||||
} | } | ||||
error = vm_page_reclaim_contig(aflags, | error = vm_page_reclaim_contig(aflags, | ||||
pagesizes[psind] / PAGE_SIZE, 0, ~0, | pagesizes[psind] / PAGE_SIZE, 0, ~0, | ||||
pagesizes[psind], 0) ? 0 : | pagesizes[psind], 0) ? 0 : | ||||
vm_wait_intr(object); | vm_wait_intr(object); | ||||
if (error != 0) { | if (error != 0) { | ||||
VM_OBJECT_WLOCK(object); | VM_OBJECT_WLOCK(object); | ||||
#ifdef RACCT | |||||
if (racct_enable) { | |||||
racct_sub_cred(object->cred, RACCT_SHMSIZE, | |||||
length - shmfd->shm_size); | |||||
} | |||||
#endif | |||||
return (error); | return (error); | ||||
} | } | ||||
try++; | try++; | ||||
VM_OBJECT_WLOCK(object); | VM_OBJECT_WLOCK(object); | ||||
continue; | continue; | ||||
} | } | ||||
try = 0; | try = 0; | ||||
for (i = 0; i < pagesizes[psind] / PAGE_SIZE; i++) { | for (i = 0; i < pagesizes[psind] / PAGE_SIZE; i++) { | ||||
if ((m[i].flags & PG_ZERO) == 0) | if ((m[i].flags & PG_ZERO) == 0) | ||||
pmap_zero_page(&m[i]); | pmap_zero_page(&m[i]); | ||||
vm_page_valid(&m[i]); | vm_page_valid(&m[i]); | ||||
vm_page_xunbusy(&m[i]); | vm_page_xunbusy(&m[i]); | ||||
} | } | ||||
object->size += OFF_TO_IDX(pagesizes[psind]); | object->size += OFF_TO_IDX(pagesizes[psind]); | ||||
shmfd->shm_size += pagesizes[psind]; | shmfd->shm_size += pagesizes[psind]; | ||||
atomic_add_long(&count_largepages[psind], 1); | atomic_add_long(&count_largepages[psind], 1); | ||||
vm_wire_add(atop(pagesizes[psind])); | vm_wire_add(atop(pagesizes[psind])); | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
shm_dotruncate_cookie(struct shmfd *shmfd, off_t length, void *rl_cookie) | shm_dotruncate_cookie(struct thread *td, struct shmfd *shmfd, off_t length, void *rl_cookie) | ||||
{ | { | ||||
int error; | int error; | ||||
VM_OBJECT_WLOCK(shmfd->shm_object); | VM_OBJECT_WLOCK(shmfd->shm_object); | ||||
error = shm_largepage(shmfd) ? shm_dotruncate_largepage(shmfd, | error = shm_largepage(shmfd) ? shm_dotruncate_largepage(td, shmfd, | ||||
length, rl_cookie) : shm_dotruncate_locked(shmfd, length, | length, rl_cookie) : shm_dotruncate_locked(td, shmfd, length, | ||||
rl_cookie); | rl_cookie); | ||||
VM_OBJECT_WUNLOCK(shmfd->shm_object); | VM_OBJECT_WUNLOCK(shmfd->shm_object); | ||||
return (error); | return (error); | ||||
} | } | ||||
int | int | ||||
shm_dotruncate(struct shmfd *shmfd, off_t length) | shm_dotruncate(struct thread *td, struct shmfd *shmfd, off_t length) | ||||
{ | { | ||||
void *rl_cookie; | void *rl_cookie; | ||||
int error; | int error; | ||||
rl_cookie = rangelock_wlock(&shmfd->shm_rl, 0, OFF_MAX, | rl_cookie = rangelock_wlock(&shmfd->shm_rl, 0, OFF_MAX, | ||||
&shmfd->shm_mtx); | &shmfd->shm_mtx); | ||||
error = shm_dotruncate_cookie(shmfd, length, rl_cookie); | error = shm_dotruncate_cookie(td, shmfd, length, rl_cookie); | ||||
rangelock_unlock(&shmfd->shm_rl, rl_cookie, &shmfd->shm_mtx); | rangelock_unlock(&shmfd->shm_rl, rl_cookie, &shmfd->shm_mtx); | ||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
* shmfd object management including creation and reference counting | * shmfd object management including creation and reference counting | ||||
* routines. | * routines. | ||||
*/ | */ | ||||
struct shmfd * | struct shmfd * | ||||
shm_alloc(struct ucred *ucred, mode_t mode, bool largepage) | shm_alloc(struct thread *td, mode_t mode, bool largepage) | ||||
{ | { | ||||
struct shmfd *shmfd; | struct shmfd *shmfd; | ||||
#ifdef RACCT | |||||
if (racct_enable) { | |||||
PROC_LOCK(td->td_proc); | |||||
if (racct_add(td->td_proc, RACCT_NSHM, 1)) { | |||||
PROC_UNLOCK(td->td_proc); | |||||
return (NULL); | |||||
} | |||||
PROC_UNLOCK(td->td_proc); | |||||
} | |||||
#endif | |||||
shmfd = malloc(sizeof(*shmfd), M_SHMFD, M_WAITOK | M_ZERO); | shmfd = malloc(sizeof(*shmfd), M_SHMFD, M_WAITOK | M_ZERO); | ||||
shmfd->shm_size = 0; | shmfd->shm_size = 0; | ||||
shmfd->shm_uid = ucred->cr_uid; | shmfd->shm_uid = td->td_ucred->cr_uid; | ||||
shmfd->shm_gid = ucred->cr_gid; | shmfd->shm_gid = td->td_ucred->cr_gid; | ||||
shmfd->shm_mode = mode; | shmfd->shm_mode = mode; | ||||
if (largepage) { | if (largepage) { | ||||
shmfd->shm_object = phys_pager_allocate(NULL, | shmfd->shm_object = phys_pager_allocate(NULL, | ||||
&shm_largepage_phys_ops, NULL, shmfd->shm_size, | &shm_largepage_phys_ops, NULL, shmfd->shm_size, | ||||
VM_PROT_DEFAULT, 0, ucred); | VM_PROT_DEFAULT, 0, td->td_ucred); | ||||
shmfd->shm_lp_alloc_policy = SHM_LARGEPAGE_ALLOC_DEFAULT; | shmfd->shm_lp_alloc_policy = SHM_LARGEPAGE_ALLOC_DEFAULT; | ||||
} else { | } else { | ||||
shmfd->shm_object = vm_pager_allocate(OBJT_SWAP, NULL, | shmfd->shm_object = vm_pager_allocate(OBJT_SWAP, NULL, | ||||
shmfd->shm_size, VM_PROT_DEFAULT, 0, ucred); | shmfd->shm_size, VM_PROT_DEFAULT, 0, td->td_ucred); | ||||
} | } | ||||
KASSERT(shmfd->shm_object != NULL, ("shm_create: vm_pager_allocate")); | KASSERT(shmfd->shm_object != NULL, ("shm_create: vm_pager_allocate")); | ||||
vfs_timestamp(&shmfd->shm_birthtime); | vfs_timestamp(&shmfd->shm_birthtime); | ||||
shmfd->shm_atime = shmfd->shm_mtime = shmfd->shm_ctime = | shmfd->shm_atime = shmfd->shm_mtime = shmfd->shm_ctime = | ||||
shmfd->shm_birthtime; | shmfd->shm_birthtime; | ||||
shmfd->shm_ino = alloc_unr64(&shm_ino_unr); | shmfd->shm_ino = alloc_unr64(&shm_ino_unr); | ||||
refcount_init(&shmfd->shm_refs, 1); | refcount_init(&shmfd->shm_refs, 1); | ||||
mtx_init(&shmfd->shm_mtx, "shmrl", NULL, MTX_DEF); | mtx_init(&shmfd->shm_mtx, "shmrl", NULL, MTX_DEF); | ||||
rangelock_init(&shmfd->shm_rl); | rangelock_init(&shmfd->shm_rl); | ||||
#ifdef MAC | #ifdef MAC | ||||
mac_posixshm_init(shmfd); | mac_posixshm_init(shmfd); | ||||
mac_posixshm_create(ucred, shmfd); | mac_posixshm_create(td->td_ucred, shmfd); | ||||
#endif | #endif | ||||
return (shmfd); | return (shmfd); | ||||
} | } | ||||
struct shmfd * | struct shmfd * | ||||
shm_hold(struct shmfd *shmfd) | shm_hold(struct shmfd *shmfd) | ||||
{ | { | ||||
refcount_acquire(&shmfd->shm_refs); | refcount_acquire(&shmfd->shm_refs); | ||||
return (shmfd); | return (shmfd); | ||||
} | } | ||||
void | void | ||||
shm_drop(struct shmfd *shmfd) | shm_drop(struct shmfd *shmfd) | ||||
{ | { | ||||
if (refcount_release(&shmfd->shm_refs)) { | if (refcount_release(&shmfd->shm_refs)) { | ||||
#ifdef MAC | #ifdef MAC | ||||
mac_posixshm_destroy(shmfd); | mac_posixshm_destroy(shmfd); | ||||
#endif | #endif | ||||
#ifdef RACCT | |||||
if (racct_enable) { | |||||
racct_sub_cred(shmfd->shm_object->cred, RACCT_NSHM, 1); | |||||
racct_sub_cred(shmfd->shm_object->cred, RACCT_SHMSIZE, shmfd->shm_size); | |||||
} | |||||
#endif | |||||
rangelock_destroy(&shmfd->shm_rl); | rangelock_destroy(&shmfd->shm_rl); | ||||
mtx_destroy(&shmfd->shm_mtx); | mtx_destroy(&shmfd->shm_mtx); | ||||
vm_object_deallocate(shmfd->shm_object); | vm_object_deallocate(shmfd->shm_object); | ||||
free(shmfd, M_SHMFD); | free(shmfd, M_SHMFD); | ||||
} | } | ||||
} | } | ||||
/* | /* | ||||
▲ Show 20 Lines • Show All 186 Lines • ▼ Show 20 Lines | #endif | ||||
/* A SHM_ANON path pointer creates an anonymous object. */ | /* A SHM_ANON path pointer creates an anonymous object. */ | ||||
if (userpath == SHM_ANON) { | if (userpath == SHM_ANON) { | ||||
/* A read-only anonymous object is pointless. */ | /* A read-only anonymous object is pointless. */ | ||||
if ((flags & O_ACCMODE) == O_RDONLY) { | if ((flags & O_ACCMODE) == O_RDONLY) { | ||||
fdclose(td, fp, fd); | fdclose(td, fp, fd); | ||||
fdrop(fp, td); | fdrop(fp, td); | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
shmfd = shm_alloc(td->td_ucred, cmode, largepage); | shmfd = shm_alloc(td, cmode, largepage); | ||||
if (shmfd == NULL) { | |||||
return (ENOSPC); | |||||
} | |||||
shmfd->shm_seals = initial_seals; | shmfd->shm_seals = initial_seals; | ||||
shmfd->shm_flags = shmflags; | shmfd->shm_flags = shmflags; | ||||
} else { | } else { | ||||
error = shm_copyin_path(td, userpath, &path); | error = shm_copyin_path(td, userpath, &path); | ||||
if (error != 0) { | if (error != 0) { | ||||
fdclose(td, fp, fd); | fdclose(td, fp, fd); | ||||
fdrop(fp, td); | fdrop(fp, td); | ||||
return (error); | return (error); | ||||
} | } | ||||
AUDIT_ARG_UPATH1_CANON(path); | AUDIT_ARG_UPATH1_CANON(path); | ||||
fnv = fnv_32_str(path, FNV1_32_INIT); | fnv = fnv_32_str(path, FNV1_32_INIT); | ||||
sx_xlock(&shm_dict_lock); | sx_xlock(&shm_dict_lock); | ||||
shmfd = shm_lookup(path, fnv); | shmfd = shm_lookup(path, fnv); | ||||
if (shmfd == NULL) { | if (shmfd == NULL) { | ||||
/* Object does not yet exist, create it if requested. */ | /* Object does not yet exist, create it if requested. */ | ||||
if (flags & O_CREAT) { | if (flags & O_CREAT) { | ||||
#ifdef MAC | #ifdef MAC | ||||
error = mac_posixshm_check_create(td->td_ucred, | error = mac_posixshm_check_create(td->td_ucred, | ||||
path); | path); | ||||
if (error == 0) { | if (error == 0) { | ||||
#endif | #endif | ||||
shmfd = shm_alloc(td->td_ucred, cmode, | shmfd = shm_alloc(td, cmode, largepage); | ||||
largepage); | if (shmfd == NULL) { | ||||
sx_xunlock(&shm_dict_lock); | |||||
return (ENOSPC); | |||||
} | |||||
shmfd->shm_seals = initial_seals; | shmfd->shm_seals = initial_seals; | ||||
shmfd->shm_flags = shmflags; | shmfd->shm_flags = shmflags; | ||||
shm_insert(path, fnv, shmfd); | shm_insert(path, fnv, shmfd); | ||||
#ifdef MAC | #ifdef MAC | ||||
} | } | ||||
#endif | #endif | ||||
} else { | } else { | ||||
free(path, M_SHMFD); | free(path, M_SHMFD); | ||||
▲ Show 20 Lines • Show All 55 Lines • ▼ Show 20 Lines | #endif | ||||
(flags & (O_ACCMODE | O_TRUNC)) == | (flags & (O_ACCMODE | O_TRUNC)) == | ||||
(O_RDWR | O_TRUNC)) { | (O_RDWR | O_TRUNC)) { | ||||
VM_OBJECT_WLOCK(shmfd->shm_object); | VM_OBJECT_WLOCK(shmfd->shm_object); | ||||
#ifdef MAC | #ifdef MAC | ||||
error = mac_posixshm_check_truncate( | error = mac_posixshm_check_truncate( | ||||
td->td_ucred, fp->f_cred, shmfd); | td->td_ucred, fp->f_cred, shmfd); | ||||
if (error == 0) | if (error == 0) | ||||
#endif | #endif | ||||
error = shm_dotruncate_locked(shmfd, 0, | error = shm_dotruncate_locked(td, shmfd, | ||||
rl_cookie); | 0, rl_cookie); | ||||
VM_OBJECT_WUNLOCK(shmfd->shm_object); | VM_OBJECT_WUNLOCK(shmfd->shm_object); | ||||
} | } | ||||
if (error == 0) { | if (error == 0) { | ||||
/* | /* | ||||
* Currently we only allow F_SEAL_SEAL to be | * Currently we only allow F_SEAL_SEAL to be | ||||
* set initially. As noted above, this would | * set initially. As noted above, this would | ||||
* need to be reworked should that change. | * need to be reworked should that change. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 682 Lines • ▼ Show 20 Lines | shm_fallocate(struct file *fp, off_t offset, off_t len, struct thread *td) | ||||
* 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); | ||||
if (size > shmfd->shm_size) | if (size > shmfd->shm_size) | ||||
error = shm_dotruncate_cookie(shmfd, size, rl_cookie); | error = shm_dotruncate_cookie(td, shmfd, size, rl_cookie); | ||||
rangelock_unlock(&shmfd->shm_rl, rl_cookie, &shmfd->shm_mtx); | rangelock_unlock(&shmfd->shm_rl, rl_cookie, &shmfd->shm_mtx); | ||||
/* Translate to posix_fallocate(2) return value as needed. */ | /* Translate to posix_fallocate(2) return value as needed. */ | ||||
if (error == ENOMEM) | if (error == ENOMEM) | ||||
error = ENOSPC; | error = ENOSPC; | ||||
return (error); | return (error); | ||||
} | } | ||||
static int | static int | ||||
▲ Show 20 Lines • Show All 69 Lines • Show Last 20 Lines |