soo_ioctl() will need to grab the socket lock since it modifies its states. Sadly this function is sometimes called from socket-only syscalls which already held the corresponding socket lock.
So the diff below simply set/remove SS_NBIO directly in places where we are dealing with sockets and already have the lock. ok? Index: kern/uipc_syscalls.c =================================================================== RCS file: /cvs/src/sys/kern/uipc_syscalls.c,v retrieving revision 1.151 diff -u -p -r1.151 uipc_syscalls.c --- kern/uipc_syscalls.c 27 Mar 2017 11:45:49 -0000 1.151 +++ kern/uipc_syscalls.c 3 Jul 2017 12:37:03 -0000 @@ -110,10 +110,10 @@ sys_socket(struct proc *p, void *v, regi closef(fp, p); fdpunlock(fdp); } else { - fp->f_data = so; if (type & SOCK_NONBLOCK) - (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&type, p); + so->so_state |= SS_NBIO; so->so_state |= ss; + fp->f_data = so; FILE_SET_MATURE(fp, p); *retval = fd; } @@ -332,12 +332,15 @@ doaccept(struct proc *p, int sock, struc fp->f_type = DTYPE_SOCKET; fp->f_flag = FREAD | FWRITE | nflag; fp->f_ops = &socketops; - fp->f_data = so; error = soaccept(so, nam); if (!error && name != NULL) error = copyaddrout(p, nam, name, namelen, anamelen); if (!error) { - (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&nflag, p); + if (nflag & FNONBLOCK) + so->so_state |= SS_NBIO; + else + so->so_state &= ~SS_NBIO; + fp->f_data = so; FILE_SET_MATURE(fp, p); *retval = tmpfd; }