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);

Reply via email to