On 02/07/18(Mon) 11:22, Martin Pieuchot wrote:
> Let's use a array of structures to keep track of open files. This will
> allow us to simplify locking when expending it.
>
> While here consistently use M_ZERO when (re)allocating M_FILEDESC
> structures. I doubt the memset() solution makes any difference these
> days and the resulting code is simpler to understand.
>
> Finally passes a 'struct filedesc' to fdexpand() to be coherent with
> the other functions.
Updated diff now that Visa committed his nice refcounting code using
atomics.
Since flags are now part of the `fd_ofiles' array we can use the new
spinning `fd_fplock' to serialize access to them instead of fdplock().
Comments, oks?
Index: kern/kern_descrip.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_descrip.c,v
retrieving revision 1.175
diff -u -p -r1.175 kern_descrip.c
--- kern/kern_descrip.c 2 Jul 2018 14:36:33 -0000 1.175
+++ kern/kern_descrip.c 2 Jul 2018 15:36:46 -0000
@@ -235,7 +235,7 @@ fd_getfile(struct filedesc *fdp, int fd)
return (NULL);
mtx_enter(&fdp->fd_fplock);
- fp = fdp->fd_ofiles[fd];
+ fp = fdp->fd_ofiles[fd].fn_fp;
if (fp != NULL)
atomic_inc_int(&fp->f_count);
mtx_leave(&fdp->fd_fplock);
@@ -288,7 +288,7 @@ restart:
if ((error = fdalloc(p, 0, &new)) != 0) {
FRELE(fp, p);
if (error == ENOSPC) {
- fdexpand(p);
+ fdexpand(fdp);
fdpunlock(fdp);
goto restart;
}
@@ -363,7 +363,7 @@ restart:
if ((error = fdalloc(p, new, &i)) != 0) {
FRELE(fp, p);
if (error == ENOSPC) {
- fdexpand(p);
+ fdexpand(fdp);
fdpunlock(fdp);
goto restart;
}
@@ -375,8 +375,11 @@ restart:
}
/* No need for FRELE(), finishdup() uses current ref. */
error = finishdup(p, fp, old, new, retval, 1);
- if (!error && flags & O_CLOEXEC)
- fdp->fd_ofileflags[new] |= UF_EXCLOSE;
+ if (!error && flags & O_CLOEXEC) {
+ mtx_enter(&fdp->fd_fplock);
+ fdp->fd_ofiles[new].fn_flags |= UF_EXCLOSE;
+ mtx_leave(&fdp->fd_fplock);
+ }
out:
fdpunlock(fdp);
@@ -423,7 +426,7 @@ restart:
if ((error = fdalloc(p, newmin, &i)) != 0) {
FRELE(fp, p);
if (error == ENOSPC) {
- fdexpand(p);
+ fdexpand(fdp);
fdpunlock(fdp);
goto restart;
}
@@ -431,26 +434,29 @@ restart:
/* No need for FRELE(), finishdup() uses current ref. */
error = finishdup(p, fp, fd, i, retval, 0);
- if (!error && SCARG(uap, cmd) == F_DUPFD_CLOEXEC)
- fdp->fd_ofileflags[i] |= UF_EXCLOSE;
+ if (!error && SCARG(uap, cmd) == F_DUPFD_CLOEXEC) {
+ mtx_enter(&fdp->fd_fplock);
+ fdp->fd_ofiles[i].fn_flags |= UF_EXCLOSE;
+ mtx_leave(&fdp->fd_fplock);
+ }
}
fdpunlock(fdp);
return (error);
case F_GETFD:
- fdplock(fdp);
- *retval = fdp->fd_ofileflags[fd] & UF_EXCLOSE ? 1 : 0;
- fdpunlock(fdp);
+ mtx_enter(&fdp->fd_fplock);
+ *retval = fdp->fd_ofiles[fd].fn_flags & UF_EXCLOSE ? 1 : 0;
+ mtx_leave(&fdp->fd_fplock);
break;
case F_SETFD:
- fdplock(fdp);
+ mtx_enter(&fdp->fd_fplock);
if ((long)SCARG(uap, arg) & 1)
- fdp->fd_ofileflags[fd] |= UF_EXCLOSE;
+ fdp->fd_ofiles[fd].fn_flags |= UF_EXCLOSE;
else
- fdp->fd_ofileflags[fd] &= ~UF_EXCLOSE;
- fdpunlock(fdp);
+ fdp->fd_ofiles[fd].fn_flags &= ~UF_EXCLOSE;
+ mtx_leave(&fdp->fd_fplock);
break;
case F_GETFL:
@@ -679,10 +685,10 @@ finishdup(struct proc *p, struct file *f
* the function no longer creates a new reference to the old file.
*/
mtx_enter(&fdp->fd_fplock);
- fdp->fd_ofiles[new] = fp;
+ fdp->fd_ofiles[new].fn_fp = fp;
+ fdp->fd_ofiles[new].fn_flags =
+ fdp->fd_ofiles[old].fn_flags & ~UF_EXCLOSE;
mtx_leave(&fdp->fd_fplock);
-
- fdp->fd_ofileflags[new] = fdp->fd_ofileflags[old] & ~UF_EXCLOSE;
*retval = new;
if (oldfp != NULL) {
@@ -703,7 +709,8 @@ fdinsert(struct filedesc *fdp, int fd, i
mtx_enter(&fhdlk);
if ((fp->f_iflags & FIF_INSERTED) == 0) {
fp->f_iflags |= FIF_INSERTED;
- if ((fq = fdp->fd_ofiles[0]) != NULL) {
+ if ((fq = fdp->fd_ofiles[0].fn_fp) != NULL) {
+ KASSERT(fq->f_iflags & FIF_INSERTED);
LIST_INSERT_AFTER(fq, fp, f_list);
} else {
LIST_INSERT_HEAD(&filehead, fp, f_list);
@@ -712,11 +719,10 @@ fdinsert(struct filedesc *fdp, int fd, i
mtx_leave(&fhdlk);
mtx_enter(&fdp->fd_fplock);
- KASSERT(fdp->fd_ofiles[fd] == NULL);
- fdp->fd_ofiles[fd] = fp;
+ KASSERT(fdp->fd_ofiles[fd].fn_fp == NULL);
+ fdp->fd_ofiles[fd].fn_fp = fp;
+ fdp->fd_ofiles[fd].fn_flags |= (flags & UF_EXCLOSE);
mtx_leave(&fdp->fd_fplock);
-
- fdp->fd_ofileflags[fd] |= (flags & UF_EXCLOSE);
}
void
@@ -729,11 +735,10 @@ fdremove(struct filedesc *fdp, int fd)
* the function no longer creates a new reference to the file.
*/
mtx_enter(&fdp->fd_fplock);
- fdp->fd_ofiles[fd] = NULL;
+ fdp->fd_ofiles[fd].fn_fp = NULL;
+ fdp->fd_ofiles[fd].fn_flags = 0;
mtx_leave(&fdp->fd_fplock);
- fdp->fd_ofileflags[fd] = 0;
-
fd_unused(fdp, fd);
}
@@ -900,9 +905,12 @@ restart:
if (want <= fdp->fd_freefile)
fdp->fd_freefile = i;
*result = i;
- fdp->fd_ofileflags[i] = 0;
+
+ mtx_enter(&fdp->fd_fplock);
+ fdp->fd_ofiles[i].fn_flags = 0;
if (ISSET(p->p_p->ps_flags, PS_PLEDGE))
- fdp->fd_ofileflags[i] |= UF_PLEDGED;
+ fdp->fd_ofiles[i].fn_flags |= UF_PLEDGED;
+ mtx_leave(&fdp->fd_fplock);
return (0);
}
}
@@ -913,19 +921,17 @@ restart:
}
void
-fdexpand(struct proc *p)
+fdexpand(struct filedesc *fdp)
{
- struct filedesc *fdp = p->p_fd;
int nfiles, oldnfiles;
size_t copylen;
- struct file **newofile, **oldofile;
- char *newofileflags;
+ struct fdnode *newfiles, *oldfiles;
u_int *newhimap, *newlomap;
fdpassertlocked(fdp);
oldnfiles = fdp->fd_nfiles;
- oldofile = fdp->fd_ofiles;
+ oldfiles = fdp->fd_ofiles;
/*
* No space in current array.
@@ -935,41 +941,32 @@ fdexpand(struct proc *p)
else
nfiles = 2 * fdp->fd_nfiles;
- newofile = mallocarray(nfiles, OFILESIZE, M_FILEDESC, M_WAITOK);
+ newfiles = mallocarray(nfiles, sizeof(struct fdnode), M_FILEDESC,
+ M_WAITOK | M_ZERO);
+
/*
* Allocate all required chunks before calling free(9) to make
* sure that ``fd_ofiles'' stays valid if we go to sleep.
*/
if (NDHISLOTS(nfiles) > NDHISLOTS(fdp->fd_nfiles)) {
newhimap = mallocarray(NDHISLOTS(nfiles), sizeof(u_int),
- M_FILEDESC, M_WAITOK);
+ M_FILEDESC, M_WAITOK | M_ZERO);
newlomap = mallocarray(NDLOSLOTS(nfiles), sizeof(u_int),
- M_FILEDESC, M_WAITOK);
+ M_FILEDESC, M_WAITOK | M_ZERO);
}
- newofileflags = (char *) &newofile[nfiles];
/*
- * Copy the existing ofile and ofileflags arrays
- * and zero the new portion of each array.
+ * Copy the existing files array.
*/
- copylen = sizeof(struct file *) * fdp->fd_nfiles;
- memcpy(newofile, fdp->fd_ofiles, copylen);
- memset((char *)newofile + copylen, 0,
- nfiles * sizeof(struct file *) - copylen);
- copylen = sizeof(char) * fdp->fd_nfiles;
- memcpy(newofileflags, fdp->fd_ofileflags, copylen);
- memset(newofileflags + copylen, 0, nfiles * sizeof(char) - copylen);
+ copylen = sizeof(struct fdnode) * fdp->fd_nfiles;
+ memcpy(newfiles, fdp->fd_ofiles, copylen);
if (NDHISLOTS(nfiles) > NDHISLOTS(fdp->fd_nfiles)) {
copylen = NDHISLOTS(fdp->fd_nfiles) * sizeof(u_int);
memcpy(newhimap, fdp->fd_himap, copylen);
- memset((char *)newhimap + copylen, 0,
- NDHISLOTS(nfiles) * sizeof(u_int) - copylen);
copylen = NDLOSLOTS(fdp->fd_nfiles) * sizeof(u_int);
memcpy(newlomap, fdp->fd_lomap, copylen);
- memset((char *)newlomap + copylen, 0,
- NDLOSLOTS(nfiles) * sizeof(u_int) - copylen);
if (NDHISLOTS(fdp->fd_nfiles) > NDHISLOTS(NDFILE)) {
free(fdp->fd_himap, M_FILEDESC,
@@ -980,16 +977,15 @@ fdexpand(struct proc *p)
fdp->fd_himap = newhimap;
fdp->fd_lomap = newlomap;
}
-
mtx_enter(&fdp->fd_fplock);
- fdp->fd_ofiles = newofile;
+ fdp->fd_ofiles = newfiles;
mtx_leave(&fdp->fd_fplock);
- fdp->fd_ofileflags = newofileflags;
fdp->fd_nfiles = nfiles;
if (oldnfiles > NDFILE)
- free(oldofile, M_FILEDESC, oldnfiles * OFILESIZE);
+ free(oldfiles, M_FILEDESC, oldnfiles * sizeof(struct fdnode));
+
}
/*
@@ -1009,7 +1005,7 @@ falloc(struct proc *p, struct file **res
restart:
if ((error = fdalloc(p, 0, &i)) != 0) {
if (error == ENOSPC) {
- fdexpand(p);
+ fdexpand(p->p_fd);
goto restart;
}
return (error);
@@ -1077,7 +1073,6 @@ fdinit(void)
newfdp->fd_fd.fd_refcnt = 1;
newfdp->fd_fd.fd_cmask = S_IWGRP|S_IWOTH;
newfdp->fd_fd.fd_ofiles = newfdp->fd_dfiles;
- newfdp->fd_fd.fd_ofileflags = newfdp->fd_dfileflags;
newfdp->fd_fd.fd_nfiles = NDFILE;
newfdp->fd_fd.fd_himap = newfdp->fd_dhimap;
newfdp->fd_fd.fd_lomap = newfdp->fd_dlomap;
@@ -1134,9 +1129,8 @@ fdcopy(struct process *pr)
i = fdp->fd_nfiles;
while (i >= 2 * NDEXTENT && i > fdp->fd_lastfile * 2)
i /= 2;
- newfdp->fd_ofiles = mallocarray(i, OFILESIZE, M_FILEDESC,
- M_WAITOK | M_ZERO);
- newfdp->fd_ofileflags = (char *) &newfdp->fd_ofiles[i];
+ newfdp->fd_ofiles = mallocarray(i, sizeof(struct fdnode),
+ M_FILEDESC, M_WAITOK | M_ZERO);
newfdp->fd_nfiles = i;
}
if (NDHISLOTS(newfdp->fd_nfiles) > NDHISLOTS(NDFILE)) {
@@ -1150,7 +1144,7 @@ fdcopy(struct process *pr)
newfdp->fd_cmask = fdp->fd_cmask;
for (i = 0; i <= fdp->fd_lastfile; i++) {
- struct file *fp = fdp->fd_ofiles[i];
+ struct file *fp = fdp->fd_ofiles[i].fn_fp;
if (fp != NULL) {
/*
@@ -1166,8 +1160,9 @@ fdcopy(struct process *pr)
continue;
FREF(fp);
- newfdp->fd_ofiles[i] = fp;
- newfdp->fd_ofileflags[i] = fdp->fd_ofileflags[i];
+ newfdp->fd_ofiles[i].fn_fp = fp;
+ newfdp->fd_ofiles[i].fn_flags =
+ fdp->fd_ofiles[i].fn_flags;
fd_used(newfdp, i);
}
}
@@ -1183,24 +1178,28 @@ void
fdfree(struct proc *p)
{
struct filedesc *fdp = p->p_fd;
- struct file **fpp, *fp;
+ struct file *fp;
int i;
if (--fdp->fd_refcnt > 0)
return;
- fpp = fdp->fd_ofiles;
- for (i = fdp->fd_lastfile; i >= 0; i--, fpp++) {
- fp = *fpp;
+ for (i = 0; i <= fdp->fd_lastfile; i++) {
+ mtx_enter(&fdp->fd_fplock);
+ fp = fdp->fd_ofiles[i].fn_fp;
+ fdp->fd_ofiles[i].fn_fp = NULL;
+ fdp->fd_ofiles[i].fn_flags = 0;
+ mtx_leave(&fdp->fd_fplock);
if (fp != NULL) {
- *fpp = NULL;
/* closef() expects a refcount of 2 */
FREF(fp);
(void) closef(fp, p);
}
}
p->p_fd = NULL;
- if (fdp->fd_nfiles > NDFILE)
- free(fdp->fd_ofiles, M_FILEDESC, fdp->fd_nfiles * OFILESIZE);
+ if (fdp->fd_nfiles > NDFILE) {
+ free(fdp->fd_ofiles, M_FILEDESC,
+ fdp->fd_nfiles * sizeof(struct fdnode));
+ }
if (NDHISLOTS(fdp->fd_nfiles) > NDHISLOTS(NDFILE)) {
free(fdp->fd_himap, M_FILEDESC,
NDHISLOTS(fdp->fd_nfiles) * sizeof(u_int));
@@ -1411,13 +1410,13 @@ dupfdopen(struct proc *p, int indx, int
KASSERT(wfp->f_iflags & FIF_INSERTED);
mtx_enter(&fdp->fd_fplock);
- KASSERT(fdp->fd_ofiles[indx] == NULL);
- fdp->fd_ofiles[indx] = wfp;
+ KASSERT(fdp->fd_ofiles[indx].fn_fp == NULL);
+ fdp->fd_ofiles[indx].fn_fp = wfp;
+ fdp->fd_ofiles[indx].fn_flags =
+ (fdp->fd_ofiles[indx].fn_flags & UF_EXCLOSE) |
+ (fdp->fd_ofiles[dupfd].fn_flags & ~UF_EXCLOSE);
mtx_leave(&fdp->fd_fplock);
- fdp->fd_ofileflags[indx] = (fdp->fd_ofileflags[indx] & UF_EXCLOSE) |
- (fdp->fd_ofileflags[dupfd] & ~UF_EXCLOSE);
-
return (0);
}
@@ -1428,12 +1427,16 @@ void
fdcloseexec(struct proc *p)
{
struct filedesc *fdp = p->p_fd;
+ char flags;
int fd;
fdplock(fdp);
for (fd = 0; fd <= fdp->fd_lastfile; fd++) {
- fdp->fd_ofileflags[fd] &= ~UF_PLEDGED;
- if (fdp->fd_ofileflags[fd] & UF_EXCLOSE)
+ mtx_enter(&fdp->fd_fplock);
+ fdp->fd_ofiles[fd].fn_flags &= ~UF_PLEDGED;
+ flags = fdp->fd_ofiles[fd].fn_flags;
+ mtx_leave(&fdp->fd_fplock);
+ if (flags & UF_EXCLOSE)
(void) fdrelease(p, fd);
}
fdpunlock(fdp);
Index: kern/kern_sysctl.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_sysctl.c,v
retrieving revision 1.345
diff -u -p -r1.345 kern_sysctl.c
--- kern/kern_sysctl.c 2 Jul 2018 14:36:33 -0000 1.345
+++ kern/kern_sysctl.c 2 Jul 2018 15:33:05 -0000
@@ -1263,9 +1263,9 @@ fill_file(struct kinfo_file *kf, struct
strlcpy(kf->p_comm, pr->ps_comm, sizeof(kf->p_comm));
}
if (fdp != NULL) {
- fdplock(fdp);
- kf->fd_ofileflags = fdp->fd_ofileflags[fd];
- fdpunlock(fdp);
+ mtx_enter(&fdp->fd_fplock);
+ kf->fd_ofileflags = fdp->fd_ofiles[fd].fn_flags;
+ mtx_leave(&fdp->fd_fplock);
}
}
Index: kern/sys_generic.c
===================================================================
RCS file: /cvs/src/sys/kern/sys_generic.c,v
retrieving revision 1.119
diff -u -p -r1.119 sys_generic.c
--- kern/sys_generic.c 8 May 2018 08:53:41 -0000 1.119
+++ kern/sys_generic.c 2 Jul 2018 15:33:41 -0000
@@ -418,12 +418,12 @@ sys_ioctl(struct proc *p, void *v, regis
switch (com) {
case FIONCLEX:
case FIOCLEX:
- fdplock(fdp);
+ mtx_enter(&fdp->fd_fplock);
if (com == FIONCLEX)
- fdp->fd_ofileflags[SCARG(uap, fd)] &= ~UF_EXCLOSE;
+ fdp->fd_ofiles[SCARG(uap, fd)].fn_flags &= ~UF_EXCLOSE;
else
- fdp->fd_ofileflags[SCARG(uap, fd)] |= UF_EXCLOSE;
- fdpunlock(fdp);
+ fdp->fd_ofiles[SCARG(uap, fd)].fn_flags |= UF_EXCLOSE;
+ mtx_leave(&fdp->fd_fplock);
goto out;
}
Index: kern/uipc_usrreq.c
===================================================================
RCS file: /cvs/src/sys/kern/uipc_usrreq.c,v
retrieving revision 1.133
diff -u -p -r1.133 uipc_usrreq.c
--- kern/uipc_usrreq.c 2 Jul 2018 14:36:33 -0000 1.133
+++ kern/uipc_usrreq.c 2 Jul 2018 15:33:10 -0000
@@ -725,7 +725,7 @@ restart:
fdremove(fdp, fds[i]);
if (error == ENOSPC) {
- fdexpand(p);
+ fdexpand(fdp);
error = 0;
} else {
/*
@@ -745,13 +745,12 @@ restart:
* in the loop below.
*/
mtx_enter(&fdp->fd_fplock);
- KASSERT(fdp->fd_ofiles[fds[i]] == NULL);
- fdp->fd_ofiles[fds[i]] = rp->fp;
- mtx_leave(&fdp->fd_fplock);
-
- fdp->fd_ofileflags[fds[i]] = (rp->flags & UF_PLEDGED);
+ KASSERT(fdp->fd_ofiles[fds[i]].fn_fp == NULL);
+ fdp->fd_ofiles[fds[i]].fn_fp = rp->fp;
+ fdp->fd_ofiles[fds[i]].fn_flags = (rp->flags & UF_PLEDGED);
if (flags & MSG_CMSG_CLOEXEC)
- fdp->fd_ofileflags[fds[i]] |= UF_EXCLOSE;
+ fdp->fd_ofiles[fds[i]].fn_flags |= UF_EXCLOSE;
+ mtx_leave(&fdp->fd_fplock);
rp++;
}
@@ -865,7 +864,9 @@ morespace:
goto fail;
}
rp->fp = fp;
- rp->flags = fdp->fd_ofileflags[fd] & UF_PLEDGED;
+ mtx_enter(&fdp->fd_fplock);
+ rp->flags = fdp->fd_ofiles[fd].fn_flags & UF_PLEDGED;
+ mtx_leave(&fdp->fd_fplock);
rp--;
if ((unp = fptounp(fp)) != NULL) {
unp->unp_file = fp;
Index: dev/pci/drm/drm_linux.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/drm/drm_linux.c,v
retrieving revision 1.25
diff -u -p -r1.25 drm_linux.c
--- dev/pci/drm/drm_linux.c 1 Jul 2018 12:12:14 -0000 1.25
+++ dev/pci/drm/drm_linux.c 2 Jul 2018 09:13:22 -0000
@@ -931,7 +931,7 @@ dma_buf_fd(struct dma_buf *dmabuf, int f
restart:
if ((error = fdalloc(p, 0, &fd)) != 0) {
if (error == ENOSPC) {
- fdexpand(p);
+ fdexpand(fdp);
goto restart;
}
fdpunlock(fdp);
Index: sys/filedesc.h
===================================================================
RCS file: /cvs/src/sys/sys/filedesc.h,v
retrieving revision 1.41
diff -u -p -r1.41 filedesc.h
--- sys/filedesc.h 2 Jul 2018 14:36:33 -0000 1.41
+++ sys/filedesc.h 2 Jul 2018 15:38:34 -0000
@@ -44,12 +44,10 @@
* shells). If these descriptors are exhausted, a larger descriptor table
* may be allocated, up to a process' resource limit; the internal arrays
* are then unused. The initial expansion is set to NDEXTENT; each time
- * it runs out, it is doubled until the resource limit is reached. NDEXTENT
- * should be selected to be the biggest multiple of OFILESIZE (see below)
- * that will fit in a power-of-two sized piece of memory.
+ * it runs out, it is doubled until the resource limit is reached.
*/
#define NDFILE 20
-#define NDEXTENT 50 /* 250 bytes in 256-byte alloc. */
+#define NDEXTENT 50
#define NDENTRIES 32 /* 32 fds per entry */
#define NDENTRYMASK (NDENTRIES - 1)
#define NDENTRYSHIFT 5 /* bits per entry */
@@ -57,9 +55,14 @@
#define NDHISLOTS(x) (NDREDUCE(NDREDUCE(x)))
#define NDLOSLOTS(x) (NDHISLOTS(x) << NDENTRYSHIFT)
+struct fdnode {
+ struct file *fn_fp; /* per-process open file structure */
+ char fn_flags; /* per-process open file flag */
+ char _pad[3];
+};
+
struct filedesc {
- struct file **fd_ofiles; /* file structures for open files */
- char *fd_ofileflags; /* per-process open file flags */
+ struct fdnode *fd_ofiles; /* file struct. & flag for open files */
struct vnode *fd_cdir; /* current directory */
struct vnode *fd_rdir; /* root directory */
int fd_nfiles; /* number of open files allocated */
@@ -89,8 +92,8 @@ struct filedesc0 {
* These arrays are used when the number of open files is
* <= NDFILE, and are then pointed to by the pointers above.
*/
- struct file *fd_dfiles[NDFILE];
- char fd_dfileflags[NDFILE];
+ struct fdnode fd_dfiles[NDFILE];
+
/*
* There arrays are used when the number of open files is
* <= 1024, and are then pointed to by the pointers above.
@@ -110,11 +113,6 @@ struct filedesc0 {
*/
#define FD_ADVLOCK 0x01 /* May hold a POSIX adv. lock. */
-/*
- * Storage required per open file descriptor.
- */
-#define OFILESIZE (sizeof(struct file *) + sizeof(char))
-
#ifdef _KERNEL
/*
* Kernel global variables and routines.
@@ -122,7 +120,7 @@ struct filedesc0 {
void filedesc_init(void);
int dupfdopen(struct proc *, int, int);
int fdalloc(struct proc *p, int want, int *result);
-void fdexpand(struct proc *);
+void fdexpand(struct filedesc *);
struct file *fnew(struct proc *_p);
int falloc(struct proc *_p, struct file **_rfp, int *_rfd);
struct filedesc *fdinit(void);