summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_descrip.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/kern_descrip.c')
-rw-r--r--sys/kern/kern_descrip.c145
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);
OpenPOWER on IntegriCloud