diff --git a/sys/kern/kern_umtx.c b/sys/kern/kern_umtx.c --- a/sys/kern/kern_umtx.c +++ b/sys/kern/kern_umtx.c @@ -4014,9 +4014,9 @@ reg = uma_zalloc(umtx_shm_reg_zone, M_WAITOK | M_ZERO); reg->ushm_refcnt = 1; bcopy(key, ®->ushm_key, sizeof(*key)); - reg->ushm_obj = shm_alloc(td->td_ucred, O_RDWR, false); + reg->ushm_obj = shm_alloc(td, O_RDWR, false); reg->ushm_cred = crhold(cred); - error = shm_dotruncate(reg->ushm_obj, PAGE_SIZE); + error = shm_dotruncate(td, reg->ushm_obj, PAGE_SIZE); if (error != 0) { umtx_shm_free_reg(reg); return (error); diff --git a/sys/kern/uipc_shm.c b/sys/kern/uipc_shm.c --- a/sys/kern/uipc_shm.c +++ b/sys/kern/uipc_shm.c @@ -73,6 +73,7 @@ #include #include #include +#include #include #include #include @@ -125,10 +126,10 @@ static void shm_insert(char *path, Fnv32_t fnv, struct shmfd *shmfd); 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_dotruncate_cookie(struct shmfd *shmfd, off_t length, - void *rl_cookie); -static int shm_dotruncate_locked(struct shmfd *shmfd, off_t length, - void *rl_cookie); +static int shm_dotruncate_cookie(struct thread *td, struct shmfd *shmfd, + off_t length, void *rl_cookie); +static int shm_dotruncate_locked(struct thread *td, struct shmfd *shmfd, + off_t length, void *rl_cookie); static int shm_copyin_path(struct thread *td, const char *userpath_in, char **path_out); @@ -450,7 +451,7 @@ error = 0; if ((shmfd->shm_flags & SHM_GROW_ON_WRITE) != 0 && size > shmfd->shm_size) { - error = shm_dotruncate_cookie(shmfd, size, rl_cookie); + error = shm_dotruncate_cookie(td, shmfd, size, rl_cookie); } if (error == 0) error = uiomove_object(shmfd->shm_object, @@ -476,7 +477,7 @@ if (error) return (error); #endif - return (shm_dotruncate(shmfd, length)); + return (shm_dotruncate(td, shmfd, length)); } int @@ -627,7 +628,7 @@ } 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_page_t m; @@ -709,14 +710,39 @@ /* Free the swap accounted for shm */ swap_release_by_cred(delta, object->cred); object->charge -= delta; +#ifdef RACCT + if (racct_enable) { + racct_sub_cred(object->cred, RACCT_SHMSIZE, + shmfd->shm_size - length); + } +#endif } else { if ((shmfd->shm_seals & F_SEAL_GROW) != 0) return (EPERM); +#ifdef RACCT + if (racct_enable) { + PROC_LOCK(td->td_proc); + if (racct_add_cred_checked(object->cred, 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. */ 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); + } object->charge += delta; } shmfd->shm_size = length; @@ -729,7 +755,7 @@ } 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_page_t m; @@ -768,6 +794,17 @@ if ((shmfd->shm_seals & F_SEAL_GROW) != 0) 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; if (shmfd->shm_lp_alloc_policy == SHM_LARGEPAGE_ALLOC_NOWAIT) aflags |= VM_ALLOC_WAITFAIL; @@ -790,6 +827,12 @@ (shmfd->shm_lp_alloc_policy == SHM_LARGEPAGE_ALLOC_DEFAULT && 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); return (ENOMEM); } @@ -799,6 +842,12 @@ vm_wait_intr(object); if (error != 0) { VM_OBJECT_WLOCK(object); +#ifdef RACCT + if (racct_enable) { + racct_sub_cred(object->cred, RACCT_SHMSIZE, + length - shmfd->shm_size); + } +#endif return (error); } try++; @@ -821,27 +870,27 @@ } 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; VM_OBJECT_WLOCK(shmfd->shm_object); - error = shm_largepage(shmfd) ? shm_dotruncate_largepage(shmfd, - length, rl_cookie) : shm_dotruncate_locked(shmfd, length, + error = shm_largepage(shmfd) ? shm_dotruncate_largepage(td, shmfd, + length, rl_cookie) : shm_dotruncate_locked(td, shmfd, length, rl_cookie); VM_OBJECT_WUNLOCK(shmfd->shm_object); return (error); } int -shm_dotruncate(struct shmfd *shmfd, off_t length) +shm_dotruncate(struct thread *td, struct shmfd *shmfd, off_t length) { void *rl_cookie; int error; rl_cookie = rangelock_wlock(&shmfd->shm_rl, 0, OFF_MAX, &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); return (error); } @@ -851,23 +900,34 @@ * routines. */ 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; +#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->shm_size = 0; - shmfd->shm_uid = ucred->cr_uid; - shmfd->shm_gid = ucred->cr_gid; + shmfd->shm_uid = td->td_ucred->cr_uid; + shmfd->shm_gid = td->td_ucred->cr_gid; shmfd->shm_mode = mode; if (largepage) { shmfd->shm_object = phys_pager_allocate(NULL, &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; } else { 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")); vfs_timestamp(&shmfd->shm_birthtime); @@ -879,7 +939,7 @@ rangelock_init(&shmfd->shm_rl); #ifdef MAC mac_posixshm_init(shmfd); - mac_posixshm_create(ucred, shmfd); + mac_posixshm_create(td->td_ucred, shmfd); #endif return (shmfd); @@ -900,6 +960,13 @@ if (refcount_release(&shmfd->shm_refs)) { #ifdef MAC mac_posixshm_destroy(shmfd); +#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); mtx_destroy(&shmfd->shm_mtx); @@ -1103,7 +1170,10 @@ fdrop(fp, td); 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_flags = shmflags; } else { @@ -1126,8 +1196,11 @@ path); if (error == 0) { #endif - shmfd = shm_alloc(td->td_ucred, cmode, - largepage); + shmfd = shm_alloc(td, cmode, largepage); + if (shmfd == NULL) { + sx_xunlock(&shm_dict_lock); + return (ENOSPC); + } shmfd->shm_seals = initial_seals; shmfd->shm_flags = shmflags; shm_insert(path, fnv, shmfd); @@ -1199,8 +1272,8 @@ td->td_ucred, fp->f_cred, shmfd); if (error == 0) #endif - error = shm_dotruncate_locked(shmfd, 0, - rl_cookie); + error = shm_dotruncate_locked(td, shmfd, + 0, rl_cookie); VM_OBJECT_WUNLOCK(shmfd->shm_object); } if (error == 0) { @@ -1899,7 +1972,7 @@ 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); + error = shm_dotruncate_cookie(td, 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) diff --git a/sys/sys/mman.h b/sys/sys/mman.h --- a/sys/sys/mman.h +++ b/sys/sys/mman.h @@ -304,10 +304,10 @@ int shm_unmap(struct file *fp, void *mem, size_t size); int shm_access(struct shmfd *shmfd, struct ucred *ucred, int flags); -struct shmfd *shm_alloc(struct ucred *ucred, mode_t mode, bool largepage); +struct shmfd *shm_alloc(struct thread *td, mode_t mode, bool largepage); struct shmfd *shm_hold(struct shmfd *shmfd); void shm_drop(struct shmfd *shmfd); -int shm_dotruncate(struct shmfd *shmfd, off_t length); +int shm_dotruncate(struct thread *td, struct shmfd *shmfd, off_t length); bool shm_largepage(struct shmfd *shmfd); extern struct fileops shm_ops; diff --git a/usr.bin/rctl/rctl.8 b/usr.bin/rctl/rctl.8 --- a/usr.bin/rctl/rctl.8 +++ b/usr.bin/rctl/rctl.8 @@ -190,8 +190,8 @@ .It Sy nmsgq Ta "number of SysV message queues" .It Sy nsem Ta "number of SysV semaphores" .It Sy nsemop Ta "number of SysV semaphores modified in a single semop(2) call" -.It Sy nshm Ta "number of SysV shared memory segments" -.It Sy shmsize Ta "SysV shared memory size, in bytes" +.It Sy nshm Ta "number of SysV shared memory segments and POSIX shared memory objects" +.It Sy shmsize Ta "SysV and POSIX shared memory size, in bytes" .It Sy wallclock Ta "wallclock time, in seconds" .It Sy pcpu Ta "%CPU, in percents of a single CPU core" .It Sy readbps Ta "filesystem reads, in bytes per second"