More changes to improve kern_descrip.c.

- Avoid atomics in more places.
- Remove the per-descriptor mutex, and just use filedesc_t::fd_lock.
  It was only being used to synchronize close, and in any case we needed
  to take fd_lock to free the descriptor slot.
- Optimize certain paths for the <NDFDFILE case.
- Sprinkle more comments and assertions.
- Cache more stuff in filedesc_t.
- Fix numerous minor bugs spotted along the way.
- Restructure how the open files array is maintained, for clarity and so
  that we can eliminate the membar_consumer() call in fd_getfile().  This is
  mostly syntactic sugar; the main functional change is that fd_nfiles now
  lives alongside the open file array.

Some measurements with libmicro:

- simple file syscalls are like close() are between 1 to 10% faster.
- some nice improvements, e.g. poll(1000) which is ~50% faster.
This commit is contained in:
ad 2009-05-24 21:41:25 +00:00
parent 13573078f8
commit d991fcb3b6
21 changed files with 480 additions and 442 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: sock.c,v 1.14 2008/05/20 07:08:06 darrenr Exp $ */
/* $NetBSD: sock.c,v 1.15 2009/05/24 21:41:44 ad Exp $ */
/*
* sock.c (C) 1995-1998 Darren Reed
@ -329,12 +329,21 @@ struct tcpiphdr *ti;
t = NULL;
o = (struct file **)calloc(1, sizeof(*o) * (fd->fd_lastfile + 1));
#if defined(__NetBSD_Version__) && __NetBSD__Version__ >= 599001200
if (KMCPY(o, fd->fd_ofiles, (fd->fd_lastfile + 1) * sizeof(*o)) == -1)
{
fprintf(stderr, "read(%#lx,%#lx,%lu) - u_ofile - failed\n",
(u_long)fd->fd_ofiles, (u_long)o, (u_long)sizeof(*o));
goto finderror;
}
#else
if (KMCPY(o, &fd->fd_dt->dt_ff, (fd->fd_lastfile + 1) * sizeof(*o)) == -1)
{
fprintf(stderr, "read(%#lx,%#lx,%lu) - u_ofile - failed\n",
(u_long)fd->fd_dt->dt_ff, (u_long)o, (u_long)sizeof(*o));
goto finderror;
}
#endif
f = (struct file *)calloc(1, sizeof(*f));
if (KMCPY(f, o[tfd], sizeof(*f)) == -1)
{

View File

@ -1,4 +1,4 @@
/* $NetBSD: netbsd32_ioctl.c,v 1.41 2008/07/02 16:45:20 matt Exp $ */
/* $NetBSD: netbsd32_ioctl.c,v 1.42 2009/05/24 21:41:25 ad Exp $ */
/*
* Copyright (c) 1998, 2001 Matthew R. Green
@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: netbsd32_ioctl.c,v 1.41 2008/07/02 16:45:20 matt Exp $");
__KERNEL_RCSID(0, "$NetBSD: netbsd32_ioctl.c,v 1.42 2009/05/24 21:41:25 ad Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -349,7 +349,7 @@ printf("netbsd32_ioctl(%d, %x, %x): %s group %c base %d len %d\n",
goto out;
}
ff = fdp->fd_ofiles[SCARG(uap, fd)];
ff = fdp->fd_dt->dt_ff[SCARG(uap, fd)];
switch (com = SCARG(uap, com)) {
case FIOCLEX:
ff->ff_exclose = true;

View File

@ -1,4 +1,4 @@
/* $NetBSD: svr4_filio.c,v 1.22 2008/07/02 16:45:20 matt Exp $ */
/* $NetBSD: svr4_filio.c,v 1.23 2009/05/24 21:41:25 ad Exp $ */
/*-
* Copyright (c) 1994, 2008 The NetBSD Foundation, Inc.
@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: svr4_filio.c,v 1.22 2008/07/02 16:45:20 matt Exp $");
__KERNEL_RCSID(0, "$NetBSD: svr4_filio.c,v 1.23 2009/05/24 21:41:25 ad Exp $");
#include <sys/param.h>
#include <sys/proc.h>
@ -73,7 +73,7 @@ svr4_fil_ioctl(file_t *fp, struct lwp *l, register_t *retval, int fd, u_long cmd
if ((fp = fd_getfile(fd)) == NULL)
return EBADF;
ff = fdp->fd_ofiles[fd];
ff = fdp->fd_dt->dt_ff[fd];
switch (cmd) {
case SVR4_FIOCLEX:
ff->ff_exclose = true;

View File

@ -1,7 +1,7 @@
/* $NetBSD: svr4_32_filio.c,v 1.16 2008/07/02 16:45:20 matt Exp $ */
/* $NetBSD: svr4_32_filio.c,v 1.17 2009/05/24 21:41:25 ad Exp $ */
/*-
* Copyright (c) 1994, 2008 The NetBSD Foundation, Inc.
* Copyright (c) 1994, 2008, 2009 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: svr4_32_filio.c,v 1.16 2008/07/02 16:45:20 matt Exp $");
__KERNEL_RCSID(0, "$NetBSD: svr4_32_filio.c,v 1.17 2009/05/24 21:41:25 ad Exp $");
#include <sys/param.h>
#include <sys/proc.h>
@ -72,7 +72,7 @@ svr4_32_fil_ioctl(file_t *fp, struct lwp *l, register_t *retval, int fd, u_long
if ((fp = fd_getfile(fd)) == NULL)
return EBADF;
fdp = curlwp->l_fd;
ff = fdp->fd_ofiles[fd];
ff = fdp->fd_dt->dt_ff[fd];
error = 0;
switch (cmd) {

View File

@ -1,4 +1,4 @@
/* $NetBSD: db_xxx.c,v 1.60 2009/03/21 13:06:39 ad Exp $ */
/* $NetBSD: db_xxx.c,v 1.61 2009/05/24 21:41:25 ad Exp $ */
/*
* Copyright (c) 1982, 1986, 1989, 1991, 1993
@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: db_xxx.c,v 1.60 2009/03/21 13:06:39 ad Exp $");
__KERNEL_RCSID(0, "$NetBSD: db_xxx.c,v 1.61 2009/05/24 21:41:25 ad Exp $");
#ifdef _KERNEL_OPT
#include "opt_kgdb.h"
@ -106,6 +106,7 @@ db_show_files_cmd(db_expr_t addr, bool haddr,
file_t *fp;
struct vnode *vn;
bool full = false;
fdtab_t *dt;
if (modif[0] == 'f')
full = true;
@ -113,8 +114,9 @@ db_show_files_cmd(db_expr_t addr, bool haddr,
p = (struct proc *) (uintptr_t) addr;
fdp = p->p_fd;
for (i = 0; i < fdp->fd_nfiles; i++) {
if ((ff = fdp->fd_ofiles[i]) == NULL)
dt = fdp->fd_dt;
for (i = 0; i < dt->dt_nfiles; i++) {
if ((ff = dt->dt_ff[i]) == NULL)
continue;
fp = ff->ff_file;

View File

@ -1,7 +1,7 @@
/* $NetBSD: init_sysctl.c,v 1.163 2009/05/16 12:02:00 yamt Exp $ */
/* $NetBSD: init_sysctl.c,v 1.164 2009/05/24 21:41:26 ad Exp $ */
/*-
* Copyright (c) 2003, 2007, 2008 The NetBSD Foundation, Inc.
* Copyright (c) 2003, 2007, 2008, 2009 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: init_sysctl.c,v 1.163 2009/05/16 12:02:00 yamt Exp $");
__KERNEL_RCSID(0, "$NetBSD: init_sysctl.c,v 1.164 2009/05/24 21:41:26 ad Exp $");
#include "opt_sysv.h"
#include "opt_compat_netbsd32.h"
@ -1970,6 +1970,7 @@ sysctl_kern_file2(SYSCTLFN_ARGS)
size_t len, needed, elem_size, out_size;
int error, arg, elem_count;
fdfile_t *ff;
fdtab_t *dt;
if (namelen == 1 && name[0] == CTL_QUERY)
return (sysctl_query(SYSCTLFN_CALL(rnode)));
@ -2089,20 +2090,18 @@ sysctl_kern_file2(SYSCTLFN_ARGS)
/* XXX Do we need to check permission per file? */
fd = p->p_fd;
mutex_enter(&fd->fd_lock);
for (i = 0; i < fd->fd_nfiles; i++) {
if ((ff = fd->fd_ofiles[i]) == NULL) {
dt = fd->fd_dt;
for (i = 0; i < dt->dt_nfiles; i++) {
if ((ff = dt->dt_ff[i]) == NULL) {
continue;
}
mutex_enter(&ff->ff_lock);
if ((fp = ff->ff_file) == NULL) {
mutex_exit(&ff->ff_lock);
continue;
}
if (len >= elem_size && elem_count > 0) {
mutex_enter(&fp->f_lock);
fill_file(&kf, fp, ff, i, p->p_pid);
mutex_exit(&fp->f_lock);
mutex_exit(&ff->ff_lock);
mutex_exit(&fd->fd_lock);
error = dcopyout(l, &kf, dp, out_size);
mutex_enter(&fd->fd_lock);
@ -2110,8 +2109,6 @@ sysctl_kern_file2(SYSCTLFN_ARGS)
break;
dp += elem_size;
len -= elem_size;
} else {
mutex_exit(&ff->ff_lock);
}
needed += elem_size;
if (elem_count > 0 && elem_count != INT_MAX)

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
/* $NetBSD: kern_event.c,v 1.64 2009/04/04 10:12:51 ad Exp $ */
/* $NetBSD: kern_event.c,v 1.65 2009/05/24 21:41:26 ad Exp $ */
/*-
* Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@ -58,7 +58,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: kern_event.c,v 1.64 2009/04/04 10:12:51 ad Exp $");
__KERNEL_RCSID(0, "$NetBSD: kern_event.c,v 1.65 2009/05/24 21:41:26 ad Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -879,7 +879,7 @@ kqueue_register(struct kqueue *kq, struct kevent *kev)
kmem_free(newkn, sizeof(*newkn));
return EBADF;
}
ff = fdp->fd_ofiles[fd];
ff = fdp->fd_dt->dt_ff[fd];
if (fd <= fdp->fd_lastkqfile) {
SLIST_FOREACH(kn, &ff->ff_knlist, kn_link) {
if (kq == kn->kn_kq &&
@ -944,7 +944,7 @@ kqueue_register(struct kqueue *kq, struct kevent *kev)
} else {
/* Otherwise, knote is on an fd. */
list = (struct klist *)
&fdp->fd_ofiles[kn->kn_id]->ff_knlist;
&fdp->fd_dt->dt_ff[kn->kn_id]->ff_knlist;
if ((int)kn->kn_id > fdp->fd_lastkqfile)
fdp->fd_lastkqfile = kn->kn_id;
}
@ -1377,7 +1377,7 @@ kqueue_close(file_t *fp)
mutex_enter(&fdp->fd_lock);
for (i = 0; i <= fdp->fd_lastkqfile; i++) {
if ((ff = fdp->fd_ofiles[i]) == NULL)
if ((ff = fdp->fd_dt->dt_ff[i]) == NULL)
continue;
kqueue_doclose(kq, (struct klist *)&ff->ff_knlist, i);
}
@ -1452,7 +1452,7 @@ knote_fdclose(int fd)
filedesc_t *fdp;
fdp = curlwp->l_fd;
list = (struct klist *)&fdp->fd_ofiles[fd]->ff_knlist;
list = (struct klist *)&fdp->fd_dt->dt_ff[fd]->ff_knlist;
mutex_enter(&fdp->fd_lock);
while ((kn = SLIST_FIRST(list)) != NULL) {
knote_detach(kn, fdp, true);
@ -1485,7 +1485,7 @@ knote_detach(struct knote *kn, filedesc_t *fdp, bool dofop)
/* Remove from descriptor table. */
if (kn->kn_fop->f_isfd)
list = (struct klist *)&fdp->fd_ofiles[kn->kn_id]->ff_knlist;
list = (struct klist *)&fdp->fd_dt->dt_ff[kn->kn_id]->ff_knlist;
else
list = &fdp->fd_knhash[KN_HASH(kn->kn_id, fdp->fd_knhashmask)];

View File

@ -1,4 +1,4 @@
/* $NetBSD: kern_sig.c,v 1.297 2009/03/29 05:02:46 rmind Exp $ */
/* $NetBSD: kern_sig.c,v 1.298 2009/05/24 21:41:26 ad Exp $ */
/*-
* Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc.
@ -66,7 +66,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: kern_sig.c,v 1.297 2009/03/29 05:02:46 rmind Exp $");
__KERNEL_RCSID(0, "$NetBSD: kern_sig.c,v 1.298 2009/05/24 21:41:26 ad Exp $");
#include "opt_ptrace.h"
#include "opt_compat_sunos.h"
@ -986,6 +986,7 @@ kpsignal(struct proc *p, ksiginfo_t *ksi, void *data)
{
fdfile_t *ff;
file_t *fp;
fdtab_t *dt;
KASSERT(!cpu_intr_p());
KASSERT(mutex_owned(proc_lock));
@ -996,8 +997,9 @@ kpsignal(struct proc *p, ksiginfo_t *ksi, void *data)
/* XXXSMP locking */
ksi->ksi_fd = -1;
for (fd = 0; fd < fdp->fd_nfiles; fd++) {
if ((ff = fdp->fd_ofiles[fd]) == NULL)
dt = fdp->fd_dt;
for (fd = 0; fd < dt->dt_nfiles; fd++) {
if ((ff = dt->dt_ff[fd]) == NULL)
continue;
if ((fp = ff->ff_file) == NULL)
continue;

View File

@ -1,4 +1,4 @@
/* $NetBSD: subr_exec_fd.c,v 1.1 2008/11/18 13:01:41 pooka Exp $ */
/* $NetBSD: subr_exec_fd.c,v 1.2 2009/05/24 21:41:26 ad Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc.
@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: subr_exec_fd.c,v 1.1 2008/11/18 13:01:41 pooka Exp $");
__KERNEL_RCSID(0, "$NetBSD: subr_exec_fd.c,v 1.2 2009/05/24 21:41:26 ad Exp $");
#include <sys/param.h>
#include <sys/file.h>
@ -51,6 +51,7 @@ fd_closeexec(void)
filedesc_t *fdp;
fdfile_t *ff;
lwp_t *l;
fdtab_t *dt;
int fd;
l = curlwp;
@ -73,9 +74,10 @@ fd_closeexec(void)
return;
}
fdp->fd_exclose = false;
dt = fdp->fd_dt;
for (fd = 0; fd <= fdp->fd_lastfile; fd++) {
if ((ff = fdp->fd_ofiles[fd]) == NULL) {
if ((ff = dt->dt_ff[fd]) == NULL) {
KASSERT(fd >= NDFDFILE);
continue;
}
@ -111,6 +113,7 @@ fd_checkstd(void)
struct nameidata nd;
filedesc_t *fdp;
file_t *fp;
fdtab_t *dt;
struct proc *pp;
int fd, i, error, flags = FREAD|FWRITE;
char closed[CHECK_UPTO * 3 + 1], which[3 + 1];
@ -119,10 +122,11 @@ fd_checkstd(void)
closed[0] = '\0';
if ((fdp = p->p_fd) == NULL)
return (0);
dt = fdp->fd_dt;
for (i = 0; i < CHECK_UPTO; i++) {
KASSERT(i >= NDFDFILE ||
fdp->fd_ofiles[i] == (fdfile_t *)fdp->fd_dfdfile[i]);
if (fdp->fd_ofiles[i]->ff_file != NULL)
dt->dt_ff[i] == (fdfile_t *)fdp->fd_dfdfile[i]);
if (dt->dt_ff[i]->ff_file != NULL)
continue;
snprintf(which, sizeof(which), ",%d", i);
strlcat(closed, which, sizeof(closed));

View File

@ -1,4 +1,4 @@
/* $NetBSD: sys_aio.c,v 1.23 2009/02/22 20:28:06 ad Exp $ */
/* $NetBSD: sys_aio.c,v 1.24 2009/05/24 21:41:26 ad Exp $ */
/*
* Copyright (c) 2007, Mindaugas Rasiukevicius <rmind at NetBSD org>
@ -32,7 +32,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: sys_aio.c,v 1.23 2009/02/22 20:28:06 ad Exp $");
__KERNEL_RCSID(0, "$NetBSD: sys_aio.c,v 1.24 2009/05/24 21:41:26 ad Exp $");
#ifdef _KERNEL_OPT
#include "opt_ddb.h"
@ -622,15 +622,16 @@ sys_aio_cancel(struct lwp *l, const struct sys_aio_cancel_args *uap, register_t
struct lio_req *lio;
struct filedesc *fdp = p->p_fd;
unsigned int cn, errcnt, fildes;
fdtab_t *dt;
TAILQ_HEAD(, aio_job) tmp_jobs_list;
/* Check for invalid file descriptor */
fildes = (unsigned int)SCARG(uap, fildes);
if (fildes >= fdp->fd_nfiles)
dt = fdp->fd_dt;
if (fildes >= dt->dt_nfiles)
return EBADF;
membar_consumer();
if (fdp->fd_ofiles[fildes] == NULL || fdp->fd_ofiles[fildes]->ff_file == NULL)
if (dt->dt_ff[fildes] == NULL || dt->dt_ff[fildes]->ff_file == NULL)
return EBADF;
/* Check if AIO structure is initialized */

View File

@ -1,4 +1,4 @@
/* $NetBSD: sys_descrip.c,v 1.12 2009/03/28 21:42:19 rmind Exp $ */
/* $NetBSD: sys_descrip.c,v 1.13 2009/05/24 21:41:26 ad Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc.
@ -67,7 +67,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: sys_descrip.c,v 1.12 2009/03/28 21:42:19 rmind Exp $");
__KERNEL_RCSID(0, "$NetBSD: sys_descrip.c,v 1.13 2009/05/24 21:41:26 ad Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -356,7 +356,7 @@ sys_fcntl(struct lwp *l, const struct sys_fcntl_args *uap, register_t *retval)
if ((fp = fd_getfile(fd)) == NULL)
return (EBADF);
ff = fdp->fd_ofiles[fd];
ff = fdp->fd_dt->dt_ff[fd];
if ((cmd & F_FSCTL)) {
error = fcntl_forfs(fd, fp, cmd, SCARG(uap, arg));

View File

@ -1,4 +1,4 @@
/* $NetBSD: sys_generic.c,v 1.122 2009/05/17 10:08:38 ad Exp $ */
/* $NetBSD: sys_generic.c,v 1.123 2009/05/24 21:41:26 ad Exp $ */
/*-
* Copyright (c) 2007, 2008, 2009 The NetBSD Foundation, Inc.
@ -70,7 +70,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: sys_generic.c,v 1.122 2009/05/17 10:08:38 ad Exp $");
__KERNEL_RCSID(0, "$NetBSD: sys_generic.c,v 1.123 2009/05/24 21:41:26 ad Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -543,7 +543,7 @@ sys_ioctl(struct lwp *l, const struct sys_ioctl_args *uap, register_t *retval)
goto out;
}
ff = fdp->fd_ofiles[SCARG(uap, fd)];
ff = fdp->fd_dt->dt_ff[SCARG(uap, fd)];
switch (com = SCARG(uap, com)) {
case FIONCLEX:
ff->ff_exclose = false;

View File

@ -1,4 +1,4 @@
/* $NetBSD: sys_select.c,v 1.14 2009/03/29 19:21:19 christos Exp $ */
/* $NetBSD: sys_select.c,v 1.15 2009/05/24 21:41:26 ad Exp $ */
/*-
* Copyright (c) 2007, 2008, 2009 The NetBSD Foundation, Inc.
@ -70,7 +70,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: sys_select.c,v 1.14 2009/03/29 19:21:19 christos Exp $");
__KERNEL_RCSID(0, "$NetBSD: sys_select.c,v 1.15 2009/05/24 21:41:26 ad Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -218,7 +218,7 @@ selcommon(lwp_t *l, register_t *retval, int nd, fd_set *u_in,
sizeof(fd_mask) * 6];
proc_t * const p = l->l_proc;
char *bits;
int ncoll, error, timo;
int ncoll, error, timo, nf;
size_t ni;
sigset_t oldmask;
struct timespec sleepts;
@ -228,9 +228,10 @@ selcommon(lwp_t *l, register_t *retval, int nd, fd_set *u_in,
error = 0;
if (nd < 0)
return (EINVAL);
if (nd > p->p_fd->fd_nfiles) {
nf = p->p_fd->fd_dt->dt_nfiles;
if (nd > nf) {
/* forgiving; slightly wrong */
nd = p->p_fd->fd_nfiles;
nd = nf;
}
ni = howmany(nd, NFDBITS) * sizeof(fd_mask);
if (ni * 6 > sizeof(smallbits)) {
@ -427,14 +428,15 @@ pollcommon(lwp_t *l, register_t *retval, struct pollfd *u_fds, u_int nfds,
proc_t * const p = l->l_proc;
sigset_t oldmask;
int ncoll, error, timo;
size_t ni;
size_t ni, nf;
struct timespec sleepts;
selcpu_t *sc;
kmutex_t *lock;
if (nfds > p->p_fd->fd_nfiles) {
nf = p->p_fd->fd_dt->dt_nfiles;
if (nfds > nf) {
/* forgiving; slightly wrong */
nfds = p->p_fd->fd_nfiles;
nfds = nf;
}
ni = nfds * sizeof(struct pollfd);
if (ni > sizeof(smallfds)) {

View File

@ -1,4 +1,4 @@
/* $NetBSD: uipc_usrreq.c,v 1.125 2009/05/04 06:02:40 yamt Exp $ */
/* $NetBSD: uipc_usrreq.c,v 1.126 2009/05/24 21:41:26 ad Exp $ */
/*-
* Copyright (c) 1998, 2000, 2004, 2008, 2009 The NetBSD Foundation, Inc.
@ -96,7 +96,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: uipc_usrreq.c,v 1.125 2009/05/04 06:02:40 yamt Exp $");
__KERNEL_RCSID(0, "$NetBSD: uipc_usrreq.c,v 1.126 2009/05/24 21:41:26 ad Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -1338,7 +1338,7 @@ unp_internalize(struct mbuf **controlp)
fdp = (int *)CMSG_DATA(cm) + nfds;
rp = files + nfds;
for (i = 0; i < nfds; i++) {
fp = fdescp->fd_ofiles[*--fdp]->ff_file;
fp = fdescp->fd_dt->dt_ff[*--fdp]->ff_file;
KASSERT(fp != NULL);
mutex_enter(&fp->f_lock);
*--rp = fp;

View File

@ -1,4 +1,4 @@
/* $NetBSD: fdesc_vfsops.c,v 1.79 2009/03/14 15:36:22 dsl Exp $ */
/* $NetBSD: fdesc_vfsops.c,v 1.80 2009/05/24 21:41:26 ad Exp $ */
/*
* Copyright (c) 1992, 1993, 1995
@ -41,7 +41,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: fdesc_vfsops.c,v 1.79 2009/03/14 15:36:22 dsl Exp $");
__KERNEL_RCSID(0, "$NetBSD: fdesc_vfsops.c,v 1.80 2009/05/24 21:41:26 ad Exp $");
#if defined(_KERNEL_OPT)
#include "opt_compat_netbsd.h"
@ -164,13 +164,13 @@ fdesc_root(struct mount *mp, struct vnode **vpp)
int
fdesc_statvfs(struct mount *mp, struct statvfs *sbp)
{
struct lwp *l = curlwp;
struct filedesc *fdp;
struct proc *p;
lwp_t *l = curlwp;
proc_t *p;
int lim;
int i;
int last;
int freefd;
fdtab_t *dt;
/*
* Compute number of free file descriptors.
@ -179,20 +179,20 @@ fdesc_statvfs(struct mount *mp, struct statvfs *sbp)
* of open files... ]
*/
p = l->l_proc;
dt = l->l_fd->fd_dt;
lim = p->p_rlimit[RLIMIT_NOFILE].rlim_cur;
fdp = p->p_fd;
last = min(fdp->fd_nfiles, lim);
last = min(dt->dt_nfiles, lim);
freefd = 0;
for (i = fdp->fd_freefile; i < last; i++)
if (fdp->fd_ofiles[i] == NULL)
for (i = l->l_fd->fd_freefile; i < last; i++)
if (dt->dt_ff[i]->ff_file == NULL)
freefd++;
/*
* Adjust for the fact that the fdesc array may not
* have been fully allocated yet.
*/
if (fdp->fd_nfiles < lim)
freefd += (lim - fdp->fd_nfiles);
if (dt->dt_nfiles < lim)
freefd += (lim - dt->dt_nfiles);
sbp->f_bsize = DEV_BSIZE;
sbp->f_frsize = DEV_BSIZE;

View File

@ -1,4 +1,4 @@
/* $NetBSD: fdesc_vnops.c,v 1.106 2009/03/15 17:22:37 cegger Exp $ */
/* $NetBSD: fdesc_vnops.c,v 1.107 2009/05/24 21:41:26 ad Exp $ */
/*
* Copyright (c) 1992, 1993
@ -41,7 +41,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: fdesc_vnops.c,v 1.106 2009/03/15 17:22:37 cegger Exp $");
__KERNEL_RCSID(0, "$NetBSD: fdesc_vnops.c,v 1.107 2009/05/24 21:41:26 ad Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -276,12 +276,13 @@ fdesc_lookup(void *v)
struct lwp *l = curlwp;
const char *pname = cnp->cn_nameptr;
struct proc *p = l->l_proc;
filedesc_t *fdp = p->p_fd;
int numfiles = fdp->fd_nfiles;
unsigned fd = 0;
int error;
struct vnode *fvp;
const char *ln;
fdtab_t *dt;
dt = curlwp->l_fd->fd_dt;
if (cnp->cn_namelen == 1 && *pname == '.') {
*vpp = dvp;
@ -370,7 +371,7 @@ fdesc_lookup(void *v)
fd = 0;
while (*pname >= '0' && *pname <= '9') {
fd = 10 * fd + *pname++ - '0';
if (fd >= numfiles)
if (fd >= dt->dt_nfiles)
break;
}
@ -379,14 +380,11 @@ fdesc_lookup(void *v)
goto bad;
}
mutex_enter(&fdp->fd_lock);
if (fd >= numfiles ||fdp->fd_ofiles[fd] == NULL ||
fdp->fd_ofiles[fd]->ff_file == NULL) {
mutex_exit(&fdp->fd_lock);
if (fd >= dt->dt_nfiles || dt->dt_ff[fd] == NULL ||
dt->dt_ff[fd]->ff_file == NULL) {
error = EBADF;
goto bad;
}
mutex_exit(&fdp->fd_lock);
error = fdesc_allocvp(Fdesc, FD_DESC+fd, dvp->v_mount, &fvp);
if (error)
@ -650,12 +648,12 @@ fdesc_readdir(void *v)
} */ *ap = v;
struct uio *uio = ap->a_uio;
struct dirent d;
filedesc_t *fdp;
off_t i;
int j;
int error;
off_t *cookies = NULL;
int ncookies;
fdtab_t *dt;
switch (VTOFDESC(ap->a_vp)->fd_type) {
case Fctty:
@ -668,7 +666,7 @@ fdesc_readdir(void *v)
break;
}
fdp = curproc->p_fd;
dt = curlwp->l_fd->fd_dt;
if (uio->uio_resid < UIO_MX)
return EINVAL;
@ -709,14 +707,11 @@ fdesc_readdir(void *v)
case FD_STDIN:
case FD_STDOUT:
case FD_STDERR:
if (fdp == NULL)
continue;
if ((ft->ft_fileno - FD_STDIN) >=
fdp->fd_nfiles)
dt->dt_nfiles)
continue;
membar_consumer();
if (fdp->fd_ofiles[ft->ft_fileno - FD_STDIN]
== NULL || fdp->fd_ofiles[ft->ft_fileno -
if (dt->dt_ff[ft->ft_fileno - FD_STDIN]
== NULL || dt->dt_ff[ft->ft_fileno -
FD_STDIN]->ff_file == NULL)
continue;
break;
@ -733,16 +728,15 @@ fdesc_readdir(void *v)
*cookies++ = i + 1;
}
} else {
int nfdp = fdp ? fdp->fd_nfiles : 0;
membar_consumer();
if (ap->a_ncookies) {
ncookies = min(ncookies, nfdp + 2);
ncookies = min(ncookies, dt->dt_nfiles + 2);
cookies = malloc(ncookies * sizeof(off_t),
M_TEMP, M_WAITOK);
*ap->a_cookies = cookies;
*ap->a_ncookies = ncookies;
}
for (; i - 2 < nfdp && uio->uio_resid >= UIO_MX; i++) {
for (; i - 2 < dt->dt_nfiles && uio->uio_resid >= UIO_MX; i++) {
switch (i) {
case 0:
case 1:
@ -754,10 +748,9 @@ fdesc_readdir(void *v)
break;
default:
KASSERT(fdp != NULL);
j = (int)i - 2;
if (fdp == NULL || fdp->fd_ofiles[j] == NULL ||
fdp->fd_ofiles[j]->ff_file == NULL)
if (dt->dt_ff[j] == NULL ||
dt->dt_ff[j]->ff_file == NULL)
continue;
d.d_fileno = j + FD_STDIN;
d.d_namlen = sprintf(d.d_name, "%d", j);

View File

@ -1,4 +1,4 @@
/* $NetBSD: portal_vnops.c,v 1.82 2009/03/14 15:36:23 dsl Exp $ */
/* $NetBSD: portal_vnops.c,v 1.83 2009/05/24 21:41:26 ad Exp $ */
/*
* Copyright (c) 1992, 1993
@ -40,7 +40,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: portal_vnops.c,v 1.82 2009/03/14 15:36:23 dsl Exp $");
__KERNEL_RCSID(0, "$NetBSD: portal_vnops.c,v 1.83 2009/05/24 21:41:26 ad Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -483,7 +483,7 @@ portal_open(void *v)
* Check that the mode the file is being opened for is a subset
* of the mode of the existing descriptor.
*/
fp = l->l_proc->p_fd->fd_ofiles[fd]->ff_file;
fp = l->l_fd->fd_dt->dt_ff[fd]->ff_file;
if (((ap->a_mode & (FREAD|FWRITE)) | fp->f_flag) != fp->f_flag) {
portal_closefd(l, fd); /* XXXNJWLWP */
error = EACCES;

View File

@ -1,4 +1,4 @@
/* $NetBSD: procfs_vnops.c,v 1.173 2008/12/17 20:51:36 cegger Exp $ */
/* $NetBSD: procfs_vnops.c,v 1.174 2009/05/24 21:41:26 ad Exp $ */
/*-
* Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc.
@ -105,7 +105,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: procfs_vnops.c,v 1.173 2008/12/17 20:51:36 cegger Exp $");
__KERNEL_RCSID(0, "$NetBSD: procfs_vnops.c,v 1.174 2009/05/24 21:41:26 ad Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -1338,7 +1338,7 @@ procfs_readdir(void *v)
return ESRCH;
}
nfd = p->p_fd->fd_nfiles;
nfd = p->p_fd->fd_dt->dt_nfiles;
lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles);
if (i >= lim) {

View File

@ -1,4 +1,4 @@
/* $NetBSD: filedesc.h,v 1.54 2009/05/23 18:28:05 ad Exp $ */
/* $NetBSD: filedesc.h,v 1.55 2009/05/24 21:41:26 ad Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc.
@ -94,8 +94,8 @@
* in use. Locks:
*
* : unlocked
* a atomic operations + filedesc_t::fd_lock in some cases
* d filedesc_t::fd_lock
* f fdfile_t::ff_lock, may be stable if reference held
*
* Note that ff_exclose and ff_allocated are likely to be byte sized
* (bool). In general adjacent sub-word sized fields must be locked
@ -104,19 +104,29 @@
* it's invalid.
*/
typedef struct fdfile {
kmutex_t ff_lock; /* :: lock on structure */
bool ff_exclose; /* :: close on exec flag */
bool ff_allocated; /* d: descriptor slot is allocated */
u_int ff_refcnt; /* f: reference count on structure */
struct file *ff_file; /* f: pointer to file if open */
SLIST_HEAD(,knote) ff_knlist; /* f: knotes attached to this fd */
kcondvar_t ff_closing; /* f: notifier for close */
u_int ff_refcnt; /* a: reference count on structure */
struct file *ff_file; /* d: pointer to file if open */
SLIST_HEAD(,knote) ff_knlist; /* d: knotes attached to this fd */
kcondvar_t ff_closing; /* d: notifier for close */
} fdfile_t;
/* Reference count */
#define FR_CLOSING (0x80000000) /* closing: must interlock */
#define FR_MASK (~FR_CLOSING) /* reference count */
/*
* Open file table, potentially many 'active' tables per filedesc_t
* in a multi-threaded process, or with a shared filedesc_t (clone()).
* nfiles is first to avoid pointer arithmetic.
*/
typedef struct fdtab {
u_int dt_nfiles; /* number of open files allocated */
struct fdtab *dt_link; /* for lists of dtab */
fdfile_t *dt_ff[NDFILE]; /* file structures for open fds */
} fdtab_t;
typedef struct filedesc {
/*
* Built-in fdfile_t records first, since they have strict
@ -127,29 +137,27 @@ typedef struct filedesc {
* All of the remaining fields are locked by fd_lock.
*/
kmutex_t fd_lock; /* lock on structure */
fdfile_t **fd_ofiles; /* file structures for open files */
fdtab_t * volatile fd_dt; /* active descriptor table */
uint32_t *fd_himap; /* each bit points to 32 fds */
uint32_t *fd_lomap; /* bitmap of free fds */
void *fd_discard; /* old fd_ofiles tables to discard */
struct klist *fd_knhash; /* hash of attached non-fd knotes */
int fd_lastkqfile; /* max descriptor for kqueue */
int fd_lastfile; /* high-water mark of fd_ofiles */
int fd_refcnt; /* reference count */
int fd_nfiles; /* number of open files allocated */
u_long fd_knhashmask; /* size of fd_knhash */
#define fd_startzero fd_freefile /* area to zero on return to cache */
int fd_freefile; /* approx. next free file */
int fd_nused; /* number of slots in use */
int fd_unused; /* unused */
bool fd_exclose; /* non-zero if >0 fd with EXCLOSE */
/*
* These arrays are used when the number of open files is
* This structure is used when the number of open files is
* <= NDFILE, and are then pointed to by the pointers above.
*/
fdfile_t *fd_dfiles[NDFILE];
fdtab_t fd_dtbuiltin;
/*
* These arrays are used when the number of open files is
* <= 1024, and are then pointed to by the pointers above.
*/
#define fd_startzero fd_dhimap /* area to zero on return to cache */
uint32_t fd_dhimap[NDENTRIES >> NDENTRYSHIFT];
uint32_t fd_dlomap[NDENTRIES];
} filedesc_t;
@ -196,9 +204,6 @@ int fd_getsock(unsigned, struct socket **);
void fd_putvnode(unsigned);
void fd_putsock(unsigned);
int fd_close(unsigned);
void fd_used(filedesc_t *, unsigned);
void fd_unused(filedesc_t *, unsigned);
bool fd_isused(filedesc_t *, unsigned);
int fd_dup(file_t *, int, int *, bool);
int fd_dup2(file_t *, unsigned);
int fd_clone(file_t *, unsigned, int, const struct fileops *, void *);
@ -226,6 +231,7 @@ int do_fcntl_lock(int, int, struct flock *);
int do_posix_fadvise(int, off_t, off_t, int);
extern kmutex_t filelist_lock;
extern filedesc_t filedesc0;
#endif /* _KERNEL */

View File

@ -1,4 +1,4 @@
/* $NetBSD: fstat.c,v 1.88 2009/04/12 06:36:12 lukem Exp $ */
/* $NetBSD: fstat.c,v 1.89 2009/05/24 21:41:44 ad Exp $ */
/*-
* Copyright (c) 1988, 1993
@ -39,7 +39,7 @@ __COPYRIGHT("@(#) Copyright (c) 1988, 1993\
#if 0
static char sccsid[] = "@(#)fstat.c 8.3 (Berkeley) 5/2/95";
#else
__RCSID("$NetBSD: fstat.c,v 1.88 2009/04/12 06:36:12 lukem Exp $");
__RCSID("$NetBSD: fstat.c,v 1.89 2009/05/24 21:41:44 ad Exp $");
#endif
#endif /* not lint */
@ -313,6 +313,7 @@ dofiles(struct kinfo_proc2 *p)
int i;
struct filedesc filed;
struct cwdinfo cwdi;
struct fdtab dt;
Uname = user_from_uid(p->p_uid, 0);
Pid = p->p_pid;
@ -321,16 +322,20 @@ dofiles(struct kinfo_proc2 *p)
if (p->p_fd == 0 || p->p_cwdi == 0)
return;
if (!KVM_READ(p->p_fd, &filed, sizeof (filed))) {
warnx("can't read filedesc at %#llx for pid %d", (unsigned long long)p->p_fd, Pid);
warnx("can't read filedesc at %p for pid %d", (void *)(uintptr_t)p->p_fd, Pid);
return;
}
if (!KVM_READ(p->p_cwdi, &cwdi, sizeof(cwdi))) {
warnx("can't read cwdinfo at %#llx for pid %d", (unsigned long long)p->p_cwdi, Pid);
warnx("can't read cwdinfo at %p for pid %d", (void *)(uintptr_t)p->p_cwdi, Pid);
return;
}
if (filed.fd_nfiles < 0 || filed.fd_lastfile >= filed.fd_nfiles ||
if (!KVM_READ(filed.fd_dt, &dt, sizeof(dt))) {
warnx("can't read dtab at %p for pid %d", filed.fd_dt, Pid);
return;
}
if ((unsigned)filed.fd_lastfile >= dt.dt_nfiles ||
filed.fd_freefile > filed.fd_lastfile + 1) {
dprintf("filedesc corrupted at %#llx for pid %d", (unsigned long long)p->p_fd, Pid);
dprintf("filedesc corrupted at %p for pid %d", (void *)(uintptr_t)p->p_fd, Pid);
return;
}
/*
@ -355,10 +360,10 @@ dofiles(struct kinfo_proc2 *p)
*/
#define FPSIZE (sizeof (fdfile_t *))
ALLOC_OFILES(filed.fd_lastfile+1);
if (!KVM_READ(filed.fd_ofiles, ofiles,
if (!KVM_READ(&filed.fd_dt->dt_ff, ofiles,
(filed.fd_lastfile+1) * FPSIZE)) {
dprintf("can't read file structures at %p for pid %d",
filed.fd_ofiles, Pid);
&filed.fd_dt->dt_ff, Pid);
return;
}
for (i = 0; i <= filed.fd_lastfile; i++) {