diff options
Diffstat (limited to 'sys/kern/kern_descrip.c')
-rw-r--r-- | sys/kern/kern_descrip.c | 145 |
1 files changed, 71 insertions, 74 deletions
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index 7848396..8220786 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -109,7 +109,7 @@ static void fdgrowtable(struct filedesc *fdp, int nfd); static void fdgrowtable_exp(struct filedesc *fdp, int nfd); static void fdunused(struct filedesc *fdp, int fd); static void fdused(struct filedesc *fdp, int fd); -static int getmaxfd(struct proc *p); +static int getmaxfd(struct thread *td); /* Flags for do_dup() */ #define DUP_FIXED 0x1 /* Force fixed allocation. */ @@ -178,9 +178,6 @@ volatile int openfiles; /* actual number of open files */ struct mtx sigio_lock; /* mtx to protect pointers to sigio */ void (*mq_fdclose)(struct thread *td, int fd, struct file *fp); -/* A mutex to protect the association between a proc and filedesc. */ -static struct mtx fdesc_mtx; - /* * If low >= size, just return low. Otherwise find the first zero bit in the * given bitmap, starting at low and not exceeding size - 1. Return size if @@ -312,7 +309,7 @@ fdfree(struct filedesc *fdp, int fd) seq_write_begin(&fde->fde_seq); #endif fdefree_last(fde); - bzero(fde, fde_change_size); + fde->fde_file = NULL; fdunused(fdp, fd); #ifdef CAPABILITIES seq_write_end(&fde->fde_seq); @@ -331,16 +328,19 @@ struct getdtablesize_args { int sys_getdtablesize(struct thread *td, struct getdtablesize_args *uap) { - struct proc *p = td->td_proc; +#ifdef RACCT uint64_t lim; +#endif - PROC_LOCK(p); td->td_retval[0] = - min((int)lim_cur(p, RLIMIT_NOFILE), maxfilesperproc); + min((int)lim_cur(td, RLIMIT_NOFILE), maxfilesperproc); +#ifdef RACCT + PROC_LOCK(td->td_proc); lim = racct_get_limit(td->td_proc, RACCT_NOFILE); - PROC_UNLOCK(p); + PROC_UNLOCK(td->td_proc); if (lim < td->td_retval[0]) td->td_retval[0] = lim; +#endif return (0); } @@ -746,7 +746,8 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg) arg = arg ? 128 * 1024: 0; /* FALLTHROUGH */ case F_READAHEAD: - error = fget_unlocked(fdp, fd, NULL, &fp, NULL); + error = fget_unlocked(fdp, fd, + cap_rights_init(&rights), &fp, NULL); if (error != 0) break; if (fp->f_type != DTYPE_VNODE) { @@ -783,15 +784,10 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg) } static int -getmaxfd(struct proc *p) +getmaxfd(struct thread *td) { - int maxfd; - PROC_LOCK(p); - maxfd = min((int)lim_cur(p, RLIMIT_NOFILE), maxfilesperproc); - PROC_UNLOCK(p); - - return (maxfd); + return (min((int)lim_cur(td, RLIMIT_NOFILE), maxfilesperproc)); } /* @@ -819,7 +815,7 @@ do_dup(struct thread *td, int flags, int old, int new) return (EBADF); if (new < 0) return (flags & DUP_FCNTL ? EINVAL : EBADF); - maxfd = getmaxfd(p); + maxfd = getmaxfd(td); if (new >= maxfd) return (flags & DUP_FCNTL ? EINVAL : EBADF); @@ -1619,7 +1615,7 @@ fdalloc(struct thread *td, int minfd, int *result) if (fdp->fd_freefile > minfd) minfd = fdp->fd_freefile; - maxfd = getmaxfd(p); + maxfd = getmaxfd(td); /* * Search the bitmap for a free descriptor starting at minfd. @@ -1656,7 +1652,6 @@ fdalloc(struct thread *td, int minfd, int *result) ("fd_first_free() returned non-free descriptor")); KASSERT(fdp->fd_ofiles[fd].fde_file == NULL, ("file descriptor isn't free")); - KASSERT(fdp->fd_ofiles[fd].fde_flags == 0, ("file flags are set")); fdused(fdp, fd); *result = fd; return (0); @@ -1755,32 +1750,23 @@ falloc_noinstall(struct thread *td, struct file **resultfp) /* * Install a file in a file descriptor table. */ -int -finstall(struct thread *td, struct file *fp, int *fd, int flags, +void +_finstall(struct filedesc *fdp, struct file *fp, int fd, int flags, struct filecaps *fcaps) { - struct filedesc *fdp = td->td_proc->p_fd; struct filedescent *fde; - int error; - KASSERT(fd != NULL, ("%s: fd == NULL", __func__)); - KASSERT(fp != NULL, ("%s: fp == NULL", __func__)); + MPASS(fp != NULL); if (fcaps != NULL) filecaps_validate(fcaps, __func__); + FILEDESC_XLOCK_ASSERT(fdp); - FILEDESC_XLOCK(fdp); - if ((error = fdalloc(td, 0, fd))) { - FILEDESC_XUNLOCK(fdp); - return (error); - } - fhold(fp); - fde = &fdp->fd_ofiles[*fd]; + fde = &fdp->fd_ofiles[fd]; #ifdef CAPABILITIES seq_write_begin(&fde->fde_seq); #endif fde->fde_file = fp; - if ((flags & O_CLOEXEC) != 0) - fde->fde_flags |= UF_EXCLOSE; + fde->fde_flags = (flags & O_CLOEXEC) != 0 ? UF_EXCLOSE : 0; if (fcaps != NULL) filecaps_move(fcaps, &fde->fde_caps); else @@ -1788,6 +1774,24 @@ finstall(struct thread *td, struct file *fp, int *fd, int flags, #ifdef CAPABILITIES seq_write_end(&fde->fde_seq); #endif +} + +int +finstall(struct thread *td, struct file *fp, int *fd, int flags, + struct filecaps *fcaps) +{ + struct filedesc *fdp = td->td_proc->p_fd; + int error; + + MPASS(fd != NULL); + + FILEDESC_XLOCK(fdp); + if ((error = fdalloc(td, 0, fd))) { + FILEDESC_XUNLOCK(fdp); + return (error); + } + fhold(fp); + _finstall(fdp, fp, *fd, flags, fcaps); FILEDESC_XUNLOCK(fdp); return (0); } @@ -1809,8 +1813,8 @@ fdinit(struct filedesc *fdp, bool prepfiles) /* Create the file descriptor table. */ FILEDESC_LOCK_INIT(newfdp); - newfdp->fd_refcnt = 1; - newfdp->fd_holdcnt = 1; + refcount_init(&newfdp->fd_refcnt, 1); + refcount_init(&newfdp->fd_holdcnt, 1); newfdp->fd_cmask = CMASK; newfdp->fd_map = newfdp0->fd_dmap; newfdp->fd_lastfile = -1; @@ -1852,24 +1856,19 @@ fdhold(struct proc *p) { struct filedesc *fdp; - mtx_lock(&fdesc_mtx); + PROC_LOCK_ASSERT(p, MA_OWNED); fdp = p->p_fd; if (fdp != NULL) - fdp->fd_holdcnt++; - mtx_unlock(&fdesc_mtx); + refcount_acquire(&fdp->fd_holdcnt); return (fdp); } static void fddrop(struct filedesc *fdp) { - int i; if (fdp->fd_holdcnt > 1) { - mtx_lock(&fdesc_mtx); - i = --fdp->fd_holdcnt; - mtx_unlock(&fdesc_mtx); - if (i > 0) + if (refcount_release(&fdp->fd_holdcnt) == 0) return; } @@ -1884,9 +1883,7 @@ struct filedesc * fdshare(struct filedesc *fdp) { - FILEDESC_XLOCK(fdp); - fdp->fd_refcnt++; - FILEDESC_XUNLOCK(fdp); + refcount_acquire(&fdp->fd_refcnt); return (fdp); } @@ -2032,6 +2029,7 @@ retry: void fdescfree(struct thread *td) { + struct proc *p; struct filedesc0 *fdp0; struct filedesc *fdp; struct freetable *ft, *tft; @@ -2040,31 +2038,29 @@ fdescfree(struct thread *td) struct vnode *cdir, *jdir, *rdir; int i; - fdp = td->td_proc->p_fd; + p = td->td_proc; + fdp = p->p_fd; MPASS(fdp != NULL); #ifdef RACCT if (racct_enable) { - PROC_LOCK(td->td_proc); - racct_set(td->td_proc, RACCT_NOFILE, 0); - PROC_UNLOCK(td->td_proc); + PROC_LOCK(p); + racct_set(p, RACCT_NOFILE, 0); + PROC_UNLOCK(p); } #endif if (td->td_proc->p_fdtol != NULL) fdclearlocks(td); - mtx_lock(&fdesc_mtx); - td->td_proc->p_fd = NULL; - mtx_unlock(&fdesc_mtx); + PROC_LOCK(p); + p->p_fd = NULL; + PROC_UNLOCK(p); - FILEDESC_XLOCK(fdp); - i = --fdp->fd_refcnt; - if (i > 0) { - FILEDESC_XUNLOCK(fdp); + if (refcount_release(&fdp->fd_refcnt) == 0) return; - } + FILEDESC_XLOCK(fdp); cdir = fdp->fd_cdir; fdp->fd_cdir = NULL; rdir = fdp->fd_rdir; @@ -2373,11 +2369,9 @@ fget_unlocked(struct filedesc *fdp, int fd, cap_rights_t *needrightsp, if (fp == NULL) return (EBADF); #ifdef CAPABILITIES - if (needrightsp != NULL) { - error = cap_check(&haverights, needrightsp); - if (error != 0) - return (error); - } + error = cap_check(&haverights, needrightsp); + if (error != 0) + return (error); #endif retry: count = fp->f_count; @@ -2438,11 +2432,9 @@ _fget(struct thread *td, int fd, struct file **fpp, int flags, *fpp = NULL; fdp = td->td_proc->p_fd; - if (needrightsp != NULL) - needrights = *needrightsp; - else - cap_rights_init(&needrights); - error = fget_unlocked(fdp, fd, &needrights, &fp, seqp); + if (needrightsp == NULL) + needrightsp = cap_rights_init(&needrights); + error = fget_unlocked(fdp, fd, needrightsp, &fp, seqp); if (error != 0) return (error); if (fp->f_ops == &badfileops) { @@ -2855,7 +2847,7 @@ dupfdopen(struct thread *td, struct filedesc *fdp, int dfd, int mode, seq_write_begin(&newfde->fde_seq); #endif memcpy(newfde, oldfde, fde_change_size); - bzero(oldfde, fde_change_size); + oldfde->fde_file = NULL; fdunused(fdp, dfd); #ifdef CAPABILITIES seq_write_end(&newfde->fde_seq); @@ -2884,7 +2876,9 @@ mountcheckdirs(struct vnode *olddp, struct vnode *newdp) nrele = 0; sx_slock(&allproc_lock); FOREACH_PROC_IN_SYSTEM(p) { + PROC_LOCK(p); fdp = fdhold(p); + PROC_UNLOCK(p); if (fdp == NULL) continue; FILEDESC_XLOCK(fdp); @@ -2979,9 +2973,13 @@ sysctl_kern_file(SYSCTL_HANDLER_ARGS) n = 0; sx_slock(&allproc_lock); FOREACH_PROC_IN_SYSTEM(p) { - if (p->p_state == PRS_NEW) + PROC_LOCK(p); + if (p->p_state == PRS_NEW) { + PROC_UNLOCK(p); continue; + } fdp = fdhold(p); + PROC_UNLOCK(p); if (fdp == NULL) continue; /* overestimates sparse tables. */ @@ -3008,8 +3006,8 @@ sysctl_kern_file(SYSCTL_HANDLER_ARGS) } xf.xf_pid = p->p_pid; xf.xf_uid = p->p_ucred->cr_uid; - PROC_UNLOCK(p); fdp = fdhold(p); + PROC_UNLOCK(p); if (fdp == NULL) continue; FILEDESC_SLOCK(fdp); @@ -3644,7 +3642,6 @@ filelistinit(void *dummy) filedesc0_zone = uma_zcreate("filedesc0", sizeof(struct filedesc0), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); mtx_init(&sigio_lock, "sigio lock", NULL, MTX_DEF); - mtx_init(&fdesc_mtx, "fdesc", NULL, MTX_DEF); } SYSINIT(select, SI_SUB_LOCK, SI_ORDER_FIRST, filelistinit, NULL); |