We're aiming to replace critical sections protected by splsoftnet() by
a non recursive rwlock.  So we'll have to care about recursivity.

Diff below prevents a recursion in the error path.  Currently closef()
will call soclose() which will take splsoftnet() again.  So let's
release the spl level before.

This is part of my bigger socket lock diff.

ok?

Index: kern/uipc_syscalls.c
===================================================================
RCS file: /cvs/src/sys/kern/uipc_syscalls.c,v
retrieving revision 1.138
diff -u -p -r1.138 uipc_syscalls.c
--- kern/uipc_syscalls.c        23 Oct 2016 17:06:40 -0000      1.138
+++ kern/uipc_syscalls.c        7 Nov 2016 09:10:32 -0000
@@ -276,16 +276,11 @@ doaccept(struct proc *p, int sock, struc
        if ((error = getsock(p, sock, &fp)) != 0)
                return (error);
 
-       s = splsoftnet();
        headfp = fp;
-       head = fp->f_data;
-
-       if (isdnssocket((struct socket *)fp->f_data)) {
-               error = EINVAL;
-               goto bad;
-       }
 redo:
-       if ((head->so_options & SO_ACCEPTCONN) == 0) {
+       s = splsoftnet();
+       head = headfp->f_data;
+       if (isdnssocket(head) || (head->so_options & SO_ACCEPTCONN) == 0) {
                error = EINVAL;
                goto bad;
        }
@@ -311,7 +306,7 @@ redo:
                head->so_error = 0;
                goto bad;
        }
-       
+
        /* Figure out whether the new socket should be non-blocking. */
        nflag = flags & SOCK_NONBLOCK_INHERIT ? (headfp->f_flag & FNONBLOCK)
            : (flags & SOCK_NONBLOCK ? FNONBLOCK : 0);
@@ -338,6 +333,7 @@ redo:
         * or another thread or process to accept it.  If so, start over.
         */
        if (head->so_qlen == 0) {
+               splx(s);
                m_freem(nam);
                fdplock(fdp);
                fdremove(fdp, tmpfd);
@@ -366,18 +362,23 @@ redo:
 
        if (error) {
                /* if an error occurred, free the file descriptor */
+               splx(s);
+               m_freem(nam);
                fdplock(fdp);
                fdremove(fdp, tmpfd);
                closef(fp, p);
                fdpunlock(fdp);
+               goto out;
        } else {
                (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&nflag, p);
                FILE_SET_MATURE(fp, p);
                *retval = tmpfd;
+               m_freem(nam);
        }
-       m_freem(nam);
+
 bad:
        splx(s);
+out:
        FRELE(headfp, p);
        return (error);
 }

Reply via email to