Struct file has reference count "f_count" field. When f_count > 0 file instance
exists, when f_count becomes 0 file instance should be removed. It's simple
but some strange magic exists. When file was created by falloc() it has
f_count == 2. One additional FREF() call was done inside falloc(). After
file was setupped, FILE_SET_MATURE() call do FRELE() and f_count becomes == 1.
Also closef() function exists. It wants f_count be >= 2 otherwise it panics.
closef() caller bumps f_count before closef() call just for prevents this
panic. I found this behaviour strange, and I described this before as "Strange
magic with f_count...". Ok, this explanation sucks :) so I dug into cvs
history.

Before sys/sys/file.h rev 1.15 struct file has only one reference counter
f_count. It was used sometimes by direct "fp->f_count++" or "--fp->f_count"
operations. In sys/sys/file.h rev 1.15 another reference counter "f_usecount"
wa added to struct file. Also new macro "FILE_USE()" and "FILE_UNUSE()" were
added for increase and decrease file reference count and they used
"f_usecount". Now, those macroses known as "FREF()" and "FRELE()". So, after
sys/sys/file.h rev 1.15 struct file has two reference counters and they are
both used up to sys/sys/file.h rev 1.30 where "f_usecount" was removed, but
not completely. Within FREF() and FRELE() "f_usecount" was just replaced by
"f_count" and existed old fp->f_count increments and decrements haven't be
removed. So after sys/sys/file.h rev 1.30 there are some places where f_count
is bumped twice and decremented twice and other related code has hacks for this
condition.

Now, the legacy of "f_usecount" coexists with "f_count" and I think it
should be fixed. I did the diff for this. I did system rebuild on diskless
NFS machine without panics, and kern.nfiles before rebuild is equal to
kern.nfiles after rebuild. So looks like there is no f_count corruption
and file instance leaks. In this diff falloc() returns file instance with
f_count == 1 so FRELE() call removed from FILE_SET_MATURE(). "struct proc *"
arg removed from FILE_SET_MATURE() because it is unnecessary. closef() wants
f_count >= 1 and closef() callers don't do additional bump on f_count.

Really, I think this diff doesn't fix anything :) The code has some places
with direct "fp->f_count++" and "--fp->f_count" operations, the code has some
places with unreferenced fp instances and the code has some places where
FREF() calls on fp instance were made wrong. I think the whole "f_count"
related stuff should be refactored but even the solution described above
should not be the first step. I think, the right file instance acquisition
(f_count increment) and direct "f_count" modification cleanups should be done
before.

Index: sys/dev/systrace.c
===================================================================
RCS file: /home/cvsync/openbsd-cvs/src/sys/dev/systrace.c,v
retrieving revision 1.75
diff -u -p -r1.75 systrace.c
--- sys/dev/systrace.c  14 Mar 2015 03:38:46 -0000      1.75
+++ sys/dev/systrace.c  5 May 2015 22:37:31 -0000
@@ -518,7 +518,7 @@ systraceioctl(dev_t dev, u_long cmd, cad
                f->f_ops = &systracefops;
                f->f_data = (caddr_t) fst;
                *(int *)data = fd;
-               FILE_SET_MATURE(f, p);
+               FILE_SET_MATURE(f);
                break;
        default:
                error = EINVAL;
Index: sys/kern/exec_script.c
===================================================================
RCS file: /home/cvsync/openbsd-cvs/src/sys/kern/exec_script.c,v
retrieving revision 1.35
diff -u -p -r1.35 exec_script.c
--- sys/kern/exec_script.c      14 Mar 2015 03:38:50 -0000      1.35
+++ sys/kern/exec_script.c      5 May 2015 22:37:31 -0000
@@ -185,7 +185,7 @@ check_shell:
                fp->f_ops = &vnops;
                fp->f_data = (caddr_t) scriptvp;
                fp->f_flag = FREAD;
-               FILE_SET_MATURE(fp, p);
+               FILE_SET_MATURE(fp);
        }
 
        /* set up the parameters for the recursive check_exec() call */
Index: sys/kern/kern_descrip.c
===================================================================
RCS file: /home/cvsync/openbsd-cvs/src/sys/kern/kern_descrip.c,v
retrieving revision 1.119
diff -u -p -r1.119 kern_descrip.c
--- sys/kern/kern_descrip.c     30 Apr 2015 21:18:45 -0000      1.119
+++ sys/kern/kern_descrip.c     5 May 2015 22:37:31 -0000
@@ -576,8 +576,6 @@ finishdup(struct proc *p, struct file *f
         * closef can deal with that.
         */
        oldfp = fdp->fd_ofiles[new];
-       if (oldfp != NULL)
-               FREF(oldfp);
 
        fdp->fd_ofiles[new] = fp;
        fdp->fd_ofileflags[new] = fdp->fd_ofileflags[old] & ~UF_EXCLOSE;
@@ -620,7 +618,6 @@ fdrelease(struct proc *p, int fd)
        fp = *fpp;
        if (fp == NULL)
                return (EBADF);
-       FREF(fp);
        *fpp = NULL;
        fd_unused(fdp, fd);
        if (fd < fdp->fd_knlistsize)
@@ -897,7 +894,6 @@ restart:
                *resultfp = fp;
        if (resultfd)
                *resultfd = i;
-       FREF(fp);
        return (0);
 }
 
@@ -1047,7 +1043,6 @@ fdfree(struct proc *p)
        for (i = fdp->fd_lastfile; i >= 0; i--, fpp++) {
                fp = *fpp;
                if (fp != NULL) {
-                       FREF(fp);
                        *fpp = NULL;
                        (void) closef(fp, p);
                }
@@ -1087,10 +1082,9 @@ closef(struct file *fp, struct proc *p)
                return (0);
 
 #ifdef DIAGNOSTIC
-       if (fp->f_count < 2)
-               panic("closef: count (%ld) < 2", fp->f_count);
+       if (fp->f_count < 1)
+               panic("closef: count (%ld) < 1", fp->f_count);
 #endif
-       fp->f_count--;
 
        /*
         * POSIX record locking dictates that any close releases ALL
Index: sys/kern/kern_event.c
===================================================================
RCS file: /home/cvsync/openbsd-cvs/src/sys/kern/kern_event.c,v
retrieving revision 1.61
diff -u -p -r1.61 kern_event.c
--- sys/kern/kern_event.c       19 Dec 2014 05:59:21 -0000      1.61
+++ sys/kern/kern_event.c       5 May 2015 22:37:31 -0000
@@ -458,7 +458,7 @@ sys_kqueue(struct proc *p, void *v, regi
        if (fdp->fd_knlistsize < 0)
                fdp->fd_knlistsize = 0;         /* this process has a kq */
        kq->kq_fdp = fdp;
-       FILE_SET_MATURE(fp, p);
+       FILE_SET_MATURE(fp);
        return (0);
 }
 
Index: sys/kern/kern_exec.c
===================================================================
RCS file: /home/cvsync/openbsd-cvs/src/sys/kern/kern_exec.c,v
retrieving revision 1.161
diff -u -p -r1.161 kern_exec.c
--- sys/kern/kern_exec.c        14 Mar 2015 03:38:50 -0000      1.161
+++ sys/kern/kern_exec.c        5 May 2015 22:37:31 -0000
@@ -605,7 +605,7 @@ sys_execve(struct proc *p, void *v, regi
                                fp->f_type = DTYPE_VNODE;
                                fp->f_ops = &vnops;
                                fp->f_data = (caddr_t)vp;
-                               FILE_SET_MATURE(fp, p);
+                               FILE_SET_MATURE(fp);
                        }
                }
                fdpunlock(p->p_fd);
Index: sys/kern/sys_pipe.c
===================================================================
RCS file: /home/cvsync/openbsd-cvs/src/sys/kern/sys_pipe.c,v
retrieving revision 1.69
diff -u -p -r1.69 sys_pipe.c
--- sys/kern/sys_pipe.c 10 Feb 2015 21:56:10 -0000      1.69
+++ sys/kern/sys_pipe.c 5 May 2015 22:37:31 -0000
@@ -167,8 +167,8 @@ dopipe(struct proc *p, int *ufds, int fl
        rpipe->pipe_peer = wpipe;
        wpipe->pipe_peer = rpipe;
 
-       FILE_SET_MATURE(rf, p);
-       FILE_SET_MATURE(wf, p);
+       FILE_SET_MATURE(rf);
+       FILE_SET_MATURE(wf);
 
        error = copyout(fds, ufds, sizeof(fds));
        if (error != 0) {
Index: sys/kern/tty_pty.c
===================================================================
RCS file: /home/cvsync/openbsd-cvs/src/sys/kern/tty_pty.c,v
retrieving revision 1.70
diff -u -p -r1.70 tty_pty.c
--- sys/kern/tty_pty.c  10 Feb 2015 21:56:10 -0000      1.70
+++ sys/kern/tty_pty.c  5 May 2015 22:37:31 -0000
@@ -1176,8 +1176,8 @@ retry:
                memcpy(ptm->sn, pti->pty_sn, sizeof(pti->pty_sn));
 
                /* mark the files mature now that we've passed all errors */
-               FILE_SET_MATURE(cfp, p);
-               FILE_SET_MATURE(sfp, p);
+               FILE_SET_MATURE(cfp);
+               FILE_SET_MATURE(sfp);
 
                fdpunlock(fdp);
                break;
Index: sys/kern/uipc_syscalls.c
===================================================================
RCS file: /home/cvsync/openbsd-cvs/src/sys/kern/uipc_syscalls.c,v
retrieving revision 1.100
diff -u -p -r1.100 uipc_syscalls.c
--- sys/kern/uipc_syscalls.c    14 Mar 2015 03:38:51 -0000      1.100
+++ sys/kern/uipc_syscalls.c    5 May 2015 22:37:31 -0000
@@ -100,7 +100,7 @@ sys_socket(struct proc *p, void *v, regi
                fp->f_data = so;
                if (type & SOCK_NONBLOCK)
                        (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&type, p);
-               FILE_SET_MATURE(fp, p);
+               FILE_SET_MATURE(fp);
                *retval = fd;
        }
 out:
@@ -291,7 +291,7 @@ redo:
                fdpunlock(fdp);
        } else {
                (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&nflag, p);
-               FILE_SET_MATURE(fp, p);
+               FILE_SET_MATURE(fp);
                *retval = tmpfd;
        }
        m_freem(nam);
@@ -418,8 +418,8 @@ sys_socketpair(struct proc *p, void *v, 
                        (*fp2->f_ops->fo_ioctl)(fp2, FIONBIO, (caddr_t)&flags,
                            p);
                }
-               FILE_SET_MATURE(fp1, p);
-               FILE_SET_MATURE(fp2, p);
+               FILE_SET_MATURE(fp1);
+               FILE_SET_MATURE(fp2);
                fdpunlock(fdp);
                return (0);
        }
Index: sys/kern/uipc_usrreq.c
===================================================================
RCS file: /home/cvsync/openbsd-cvs/src/sys/kern/uipc_usrreq.c,v
retrieving revision 1.80
diff -u -p -r1.80 uipc_usrreq.c
--- sys/kern/uipc_usrreq.c      28 Mar 2015 23:50:55 -0000      1.80
+++ sys/kern/uipc_usrreq.c      5 May 2015 22:37:31 -0000
@@ -962,7 +962,6 @@ unp_gc(void)
                        *fpp++ = fp;
                        nunref++;
                        FREF(fp);
-                       fp->f_count++;
                }
        }
        for (i = nunref, fpp = extra_ref; --i >= 0; ++fpp)
@@ -1039,7 +1038,6 @@ unp_discard(struct file *fp)
 
        if (fp == NULL)
                return;
-       FREF(fp);
        fp->f_msgcount--;
        unp_rights--;
        (void) closef(fp, NULL);
Index: sys/kern/vfs_syscalls.c
===================================================================
RCS file: /home/cvsync/openbsd-cvs/src/sys/kern/vfs_syscalls.c,v
retrieving revision 1.219
diff -u -p -r1.219 vfs_syscalls.c
--- sys/kern/vfs_syscalls.c     30 Apr 2015 09:20:51 -0000      1.219
+++ sys/kern/vfs_syscalls.c     5 May 2015 22:37:31 -0000
@@ -924,7 +924,7 @@ doopenat(struct proc *p, int fd, const c
        }
        VOP_UNLOCK(vp, 0, p);
        *retval = indx;
-       FILE_SET_MATURE(fp, p);
+       FILE_SET_MATURE(fp);
 out:
        fdpunlock(fdp);
        return (error);
@@ -1086,7 +1086,7 @@ sys_fhopen(struct proc *p, void *v, regi
        }
        VOP_UNLOCK(vp, 0, p);
        *retval = indx;
-       FILE_SET_MATURE(fp, p);
+       FILE_SET_MATURE(fp);
 
        fdpunlock(fdp);
        return (0);
Index: sys/nfs/nfs_syscalls.c
===================================================================
RCS file: /home/cvsync/openbsd-cvs/src/sys/nfs/nfs_syscalls.c,v
retrieving revision 1.99
diff -u -p -r1.99 nfs_syscalls.c
--- sys/nfs/nfs_syscalls.c      14 Mar 2015 03:38:52 -0000      1.99
+++ sys/nfs/nfs_syscalls.c      5 May 2015 22:37:31 -0000
@@ -478,7 +478,6 @@ nfsrv_zapsock(struct nfssvc_sock *slp)
        slp->ns_flag &= ~SLP_ALLFLAGS;
        fp = slp->ns_fp;
        if (fp) {
-               FREF(fp);
                slp->ns_fp = NULL;
                so = slp->ns_so;
                so->so_upcall = NULL;
Index: sys/sys/file.h
===================================================================
RCS file: /home/cvsync/openbsd-cvs/src/sys/sys/file.h,v
retrieving revision 1.34
diff -u -p -r1.34 file.h
--- sys/sys/file.h      18 Nov 2014 15:16:35 -0000      1.34
+++ sys/sys/file.h      5 May 2015 22:37:31 -0000
@@ -96,9 +96,8 @@ struct file {
 #define FREF(fp)       do { (fp)->f_count++; } while (0)
 #define FRELE(fp,p)    (--(fp)->f_count == 0 ? fdrop(fp, p) : 0)
 
-#define FILE_SET_MATURE(fp,p) do {                             \
+#define FILE_SET_MATURE(fp) do {                               \
        (fp)->f_iflags &= ~FIF_LARVAL;                          \
-       FRELE(fp, p);                                           \
 } while (0)
 
 int    fdrop(struct file *, struct proc *);



Reply via email to