Diff below introduces a new helper function to iterate on `filehead'. 

This global data structures contains a reference to living 'struct file *'
so its access must be serialized with fdrop().  This is what the comment
below explains.  Currently the serialization is done by the KERNEL_LOCK(),
but since I'd like to remove the KERNEL_LOCK() from syscalls that call
FRELE(9) we'll need to use another lock.  So having all the accesses to
`filehead' in the same place makes it easier.

Ok?


Index: kern/kern_descrip.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_descrip.c,v
retrieving revision 1.150
diff -u -p -r1.150 kern_descrip.c
--- kern/kern_descrip.c 12 Apr 2018 10:30:18 -0000      1.150
+++ kern/kern_descrip.c 17 Apr 2018 07:51:51 -0000
@@ -180,6 +180,28 @@ fd_unused(struct filedesc *fdp, int fd)
 }
 
 struct file *
+fd_iterfile(struct file *fp, struct proc *p)
+{
+       struct file *nfp;
+
+       if (fp == NULL)
+               nfp = LIST_FIRST(&filehead);
+       else
+               nfp = LIST_NEXT(fp, f_list);
+
+       /* don't FREF when f_count == 0 to avoid race in fdrop() */
+       while (nfp != NULL && nfp->f_count == 0)
+               nfp = LIST_NEXT(nfp, f_list);
+       if (nfp != NULL)
+               FREF(nfp);
+
+       if (fp != NULL)
+               FRELE(fp, p);
+
+       return nfp;
+}
+
+struct file *
 fd_getfile(struct filedesc *fdp, int fd)
 {
        struct file *fp;
Index: kern/kern_sysctl.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_sysctl.c,v
retrieving revision 1.332
diff -u -p -r1.332 kern_sysctl.c
--- kern/kern_sysctl.c  19 Feb 2018 08:59:52 -0000      1.332
+++ kern/kern_sysctl.c  16 Apr 2018 12:43:19 -0000
@@ -1250,7 +1250,7 @@ sysctl_file(int *name, u_int namelen, ch
 {
        struct kinfo_file *kf;
        struct filedesc *fdp;
-       struct file *fp, *nfp;
+       struct file *fp;
        struct process *pr;
        size_t buflen, elem_size, elem_count, outsize;
        char *dp = where;
@@ -1318,14 +1318,8 @@ sysctl_file(int *name, u_int namelen, ch
 #endif
                        NET_UNLOCK();
                }
-               fp = LIST_FIRST(&filehead);
-               /* don't FREF when f_count == 0 to avoid race in fdrop() */
-               while (fp != NULL && fp->f_count == 0)
-                       fp = LIST_NEXT(fp, f_list);
-               if (fp == NULL)
-                       break;
-               FREF(fp);
-               do {
+               fp = NULL; ;
+               while ((fp = fd_iterfile(fp, p)) != NULL) {
                        if (fp->f_count > 1 && /* 0, +1 for our FREF() */
                            FILE_IS_USABLE(fp) &&
                            (arg == 0 || fp->f_type == arg)) {
@@ -1339,14 +1333,7 @@ sysctl_file(int *name, u_int namelen, ch
                                if (!skip)
                                        FILLIT(fp, NULL, 0, NULL, NULL);
                        }
-                       nfp = LIST_NEXT(fp, f_list);
-                       while (nfp != NULL && nfp->f_count == 0)
-                               nfp = LIST_NEXT(nfp, f_list);
-                       if (nfp != NULL)
-                               FREF(nfp);
-                       FRELE(fp, p);
-                       fp = nfp;
-               } while (fp != NULL);
+               };
                break;
        case KERN_FILE_BYPID:
                /* A arg of -1 indicates all processes */
Index: sys/file.h
===================================================================
RCS file: /cvs/src/sys/sys/file.h,v
retrieving revision 1.40
diff -u -p -r1.40 file.h
--- sys/file.h  10 Feb 2018 05:24:23 -0000      1.40
+++ sys/file.h  16 Apr 2018 12:43:19 -0000
@@ -106,7 +106,6 @@ struct file {
 int    fdrop(struct file *, struct proc *);
 
 LIST_HEAD(filelist, file);
-extern struct filelist filehead;       /* head of list of open files */
 extern int maxfiles;                   /* kernel limit on number of open files 
*/
 extern int numfiles;                   /* actual number of open files */
 extern struct fileops vnops;           /* vnode operations for files */
Index: sys/filedesc.h
===================================================================
RCS file: /cvs/src/sys/sys/filedesc.h,v
retrieving revision 1.34
diff -u -p -r1.34 filedesc.h
--- sys/filedesc.h      11 Feb 2017 19:51:06 -0000      1.34
+++ sys/filedesc.h      16 Apr 2018 12:43:19 -0000
@@ -133,6 +133,7 @@ void        fdfree(struct proc *p);
 int    fdrelease(struct proc *p, int);
 void   fdremove(struct filedesc *, int);
 void   fdcloseexec(struct proc *);
+struct file *fd_iterfile(struct file *, struct proc *);
 struct file *fd_getfile(struct filedesc *, int);
 struct file *fd_getfile_mode(struct filedesc *, int, int);
 

Reply via email to