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.
Comments? Oks?
Index: kern/kern_descrip.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_descrip.c,v
retrieving revision 1.173
diff -u -p -r1.173 kern_descrip.c
--- kern/kern_descrip.c 1 Jul 2018 16:33:15 -0000 1.173
+++ kern/kern_descrip.c 2 Jul 2018 09:12:30 -0000
@@ -229,7 +229,7 @@ fd_getfile(struct filedesc *fdp, int fd)
return (NULL);
mtx_enter(&fhdlk);
- fp = fdp->fd_ofiles[fd];
+ fp = fdp->fd_files[fd].fn_fp;
if (fp != NULL)
fp->f_count++;
mtx_leave(&fhdlk);
@@ -282,7 +282,7 @@ restart:
if ((error = fdalloc(p, 0, &new)) != 0) {
FRELE(fp, p);
if (error == ENOSPC) {
- fdexpand(p);
+ fdexpand(fdp);
fdpunlock(fdp);
goto restart;
}
@@ -357,7 +357,7 @@ restart:
if ((error = fdalloc(p, new, &i)) != 0) {
FRELE(fp, p);
if (error == ENOSPC) {
- fdexpand(p);
+ fdexpand(fdp);
fdpunlock(fdp);
goto restart;
}
@@ -370,7 +370,7 @@ 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;
+ fdp->fd_files[new].fn_flags |= UF_EXCLOSE;
out:
fdpunlock(fdp);
@@ -417,7 +417,7 @@ restart:
if ((error = fdalloc(p, newmin, &i)) != 0) {
FRELE(fp, p);
if (error == ENOSPC) {
- fdexpand(p);
+ fdexpand(fdp);
fdpunlock(fdp);
goto restart;
}
@@ -426,7 +426,7 @@ restart:
error = finishdup(p, fp, fd, i, retval, 0);
if (!error && SCARG(uap, cmd) == F_DUPFD_CLOEXEC)
- fdp->fd_ofileflags[i] |= UF_EXCLOSE;
+ fdp->fd_files[i].fn_flags |= UF_EXCLOSE;
}
fdpunlock(fdp);
@@ -434,16 +434,16 @@ restart:
case F_GETFD:
fdplock(fdp);
- *retval = fdp->fd_ofileflags[fd] & UF_EXCLOSE ? 1 : 0;
+ *retval = fdp->fd_files[fd].fn_flags & UF_EXCLOSE ? 1 : 0;
fdpunlock(fdp);
break;
case F_SETFD:
fdplock(fdp);
if ((long)SCARG(uap, arg) & 1)
- fdp->fd_ofileflags[fd] |= UF_EXCLOSE;
+ fdp->fd_files[fd].fn_flags |= UF_EXCLOSE;
else
- fdp->fd_ofileflags[fd] &= ~UF_EXCLOSE;
+ fdp->fd_files[fd].fn_flags &= ~UF_EXCLOSE;
fdpunlock(fdp);
break;
@@ -668,8 +668,8 @@ finishdup(struct proc *p, struct file *f
fd_used(fdp, new);
}
- fdp->fd_ofiles[new] = fp;
- fdp->fd_ofileflags[new] = fdp->fd_ofileflags[old] & ~UF_EXCLOSE;
+ fdp->fd_files[new].fn_fp = fp;
+ fdp->fd_files[new].fn_flags = fdp->fd_files[old].fn_flags & ~UF_EXCLOSE;
*retval = new;
if (oldfp != NULL) {
@@ -690,15 +690,15 @@ 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_files[0].fn_fp) != NULL) {
LIST_INSERT_AFTER(fq, fp, f_list);
} else {
LIST_INSERT_HEAD(&filehead, fp, f_list);
}
}
- KASSERT(fdp->fd_ofiles[fd] == NULL);
- fdp->fd_ofiles[fd] = fp;
- fdp->fd_ofileflags[fd] |= (flags & UF_EXCLOSE);
+ KASSERT(fdp->fd_files[fd].fn_fp == NULL);
+ fdp->fd_files[fd].fn_fp = fp;
+ fdp->fd_files[fd].fn_flags |= (flags & UF_EXCLOSE);
mtx_leave(&fhdlk);
}
@@ -706,8 +706,8 @@ void
fdremove(struct filedesc *fdp, int fd)
{
fdpassertlocked(fdp);
- fdp->fd_ofiles[fd] = NULL;
- fdp->fd_ofileflags[fd] = 0;
+ fdp->fd_files[fd].fn_fp = NULL;
+ fdp->fd_files[fd].fn_flags = 0;
fd_unused(fdp, fd);
}
@@ -872,9 +872,9 @@ restart:
if (want <= fdp->fd_freefile)
fdp->fd_freefile = i;
*result = i;
- fdp->fd_ofileflags[i] = 0;
+ fdp->fd_files[i].fn_flags = 0;
if (ISSET(p->p_p->ps_flags, PS_PLEDGE))
- fdp->fd_ofileflags[i] |= UF_PLEDGED;
+ fdp->fd_files[i].fn_flags |= UF_PLEDGED;
return (0);
}
}
@@ -885,13 +885,11 @@ restart:
}
void
-fdexpand(struct proc *p)
+fdexpand(struct filedesc *fdp)
{
- struct filedesc *fdp = p->p_fd;
int nfiles;
size_t copylen;
- struct file **newofile;
- char *newofileflags;
+ struct fdnode *newfiles;
u_int *newhimap, *newlomap;
fdpassertlocked(fdp);
@@ -904,44 +902,37 @@ 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.
+ * sure that ``fd_files'' 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_files, copylen);
- if (fdp->fd_nfiles > NDFILE)
- free(fdp->fd_ofiles, M_FILEDESC, fdp->fd_nfiles * OFILESIZE);
+ if (fdp->fd_nfiles > NDFILE) {
+ free(fdp->fd_files, M_FILEDESC,
+ fdp->fd_nfiles * sizeof(struct fdnode));
+ }
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,
@@ -952,9 +943,8 @@ fdexpand(struct proc *p)
fdp->fd_himap = newhimap;
fdp->fd_lomap = newlomap;
}
- fdp->fd_ofiles = newofile;
- fdp->fd_ofileflags = newofileflags;
- fdp->fd_nfiles = nfiles;
+ fdp->fd_files = newfiles;
+ fdp->fd_nfiles = nfiles;
}
/*
@@ -974,7 +964,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);
@@ -1042,8 +1032,7 @@ fdinit(void)
/* Create the file descriptor table. */
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_files = newfdp->fd_dfiles;
newfdp->fd_fd.fd_nfiles = NDFILE;
newfdp->fd_fd.fd_himap = newfdp->fd_dhimap;
newfdp->fd_fd.fd_lomap = newfdp->fd_dlomap;
@@ -1100,9 +1089,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_files = mallocarray(i, sizeof(struct fdnode),
+ M_FILEDESC, M_WAITOK | M_ZERO);
newfdp->fd_nfiles = i;
}
if (NDHISLOTS(newfdp->fd_nfiles) > NDHISLOTS(NDFILE)) {
@@ -1117,7 +1105,7 @@ fdcopy(struct process *pr)
mtx_enter(&fhdlk);
for (i = 0; i <= fdp->fd_lastfile; i++) {
- struct file *fp = fdp->fd_ofiles[i];
+ struct file *fp = fdp->fd_files[i].fn_fp;
if (fp != NULL) {
/*
@@ -1133,8 +1121,8 @@ fdcopy(struct process *pr)
continue;
fp->f_count++;
- newfdp->fd_ofiles[i] = fp;
- newfdp->fd_ofileflags[i] = fdp->fd_ofileflags[i];
+ newfdp->fd_files[i].fn_fp = fp;
+ newfdp->fd_files[i].fn_flags =
fdp->fd_files[i].fn_flags;
fd_used(newfdp, i);
}
}
@@ -1151,24 +1139,26 @@ 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++) {
+ fp = fdp->fd_files[i].fn_fp;
+ fdp->fd_files[i].fn_fp = NULL;
+ fdp->fd_files[i].fn_flags = 0;
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_files, 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));
@@ -1380,9 +1370,10 @@ dupfdopen(struct proc *p, int indx, int
}
KASSERT(wfp->f_iflags & FIF_INSERTED);
- fdp->fd_ofiles[indx] = wfp;
- fdp->fd_ofileflags[indx] = (fdp->fd_ofileflags[indx] & UF_EXCLOSE) |
- (fdp->fd_ofileflags[dupfd] & ~UF_EXCLOSE);
+ fdp->fd_files[indx].fn_fp = wfp;
+ fdp->fd_files[indx].fn_flags =
+ (fdp->fd_files[indx].fn_flags & UF_EXCLOSE) |
+ (fdp->fd_files[dupfd].fn_flags & ~UF_EXCLOSE);
return (0);
}
@@ -1398,8 +1389,8 @@ fdcloseexec(struct proc *p)
fdplock(fdp);
for (fd = 0; fd <= fdp->fd_lastfile; fd++) {
- fdp->fd_ofileflags[fd] &= ~UF_PLEDGED;
- if (fdp->fd_ofileflags[fd] & UF_EXCLOSE)
+ fdp->fd_files[fd].fn_flags &= ~UF_PLEDGED;
+ if (fdp->fd_files[fd].fn_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.344
diff -u -p -r1.344 kern_sysctl.c
--- kern/kern_sysctl.c 1 Jul 2018 16:33:15 -0000 1.344
+++ kern/kern_sysctl.c 2 Jul 2018 08:24:57 -0000
@@ -1266,7 +1266,7 @@ fill_file(struct kinfo_file *kf, struct
}
if (fdp != NULL) {
fdplock(fdp);
- kf->fd_ofileflags = fdp->fd_ofileflags[fd];
+ kf->fd_ofileflags = fdp->fd_files[fd].fn_flags;
fdpunlock(fdp);
}
}
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 08:24:40 -0000
@@ -420,9 +420,9 @@ sys_ioctl(struct proc *p, void *v, regis
case FIOCLEX:
fdplock(fdp);
if (com == FIONCLEX)
- fdp->fd_ofileflags[SCARG(uap, fd)] &= ~UF_EXCLOSE;
+ fdp->fd_files[SCARG(uap, fd)].fn_flags &= ~UF_EXCLOSE;
else
- fdp->fd_ofileflags[SCARG(uap, fd)] |= UF_EXCLOSE;
+ fdp->fd_files[SCARG(uap, fd)].fn_flags |= UF_EXCLOSE;
fdpunlock(fdp);
goto out;
}
Index: kern/uipc_usrreq.c
===================================================================
RCS file: /cvs/src/sys/kern/uipc_usrreq.c,v
retrieving revision 1.132
diff -u -p -r1.132 uipc_usrreq.c
--- kern/uipc_usrreq.c 1 Jul 2018 16:33:15 -0000 1.132
+++ kern/uipc_usrreq.c 2 Jul 2018 09:12:44 -0000
@@ -725,7 +725,7 @@ restart:
fdremove(fdp, fds[i]);
if (error == ENOSPC) {
- fdexpand(p);
+ fdexpand(fdp);
error = 0;
} else {
/*
@@ -744,12 +744,12 @@ restart:
* fdalloc() works properly.. We finalize it all
* in the loop below.
*/
- fdp->fd_ofiles[fds[i]] = rp->fp;
- fdp->fd_ofileflags[fds[i]] = (rp->flags & UF_PLEDGED);
+ fdp->fd_files[fds[i]].fn_fp = rp->fp;
+ fdp->fd_files[fds[i]].fn_flags = (rp->flags & UF_PLEDGED);
rp++;
if (flags & MSG_CMSG_CLOEXEC)
- fdp->fd_ofileflags[fds[i]] |= UF_EXCLOSE;
+ fdp->fd_files[fds[i]].fn_flags |= UF_EXCLOSE;
}
/*
@@ -861,7 +861,7 @@ morespace:
goto fail;
}
rp->fp = fp;
- rp->flags = fdp->fd_ofileflags[fd] & UF_PLEDGED;
+ rp->flags = fdp->fd_files[fd].fn_flags & UF_PLEDGED;
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.40
diff -u -p -r1.40 filedesc.h
--- sys/filedesc.h 25 Jun 2018 09:36:28 -0000 1.40
+++ sys/filedesc.h 2 Jul 2018 09:13:01 -0000
@@ -43,12 +43,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 */
@@ -56,9 +54,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_files; /* 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 */
@@ -86,8 +89,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.
@@ -107,11 +110,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.
@@ -119,7 +117,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);