Index: sys/kern/uipc_socket.c =================================================================== RCS file: /mount/openbsd/cvs/src/sys/kern/uipc_socket.c,v diff -u -p -u -p -r1.347 uipc_socket.c --- sys/kern/uipc_socket.c 19 Dec 2024 22:11:35 -0000 1.347 +++ sys/kern/uipc_socket.c 24 Dec 2024 19:55:08 -0000 @@ -327,17 +327,14 @@ sofree(struct socket *so, int keep_lock) sounlock(head); } - switch (so->so_proto->pr_domain->dom_family) { - case AF_INET: - case AF_INET6: - if (so->so_proto->pr_type == SOCK_STREAM) - break; - /* FALLTHROUGH */ - default: + if (!keep_lock) { + /* + * sofree() was called from soclose(). Sleep is safe + * even for tcp(4) sockets. + */ sounlock(so); refcnt_finalize(&so->so_refcnt, "sofinal"); solock(so); - break; } sigio_free(&so->so_sigio); @@ -458,31 +455,6 @@ discard: if (so->so_sp) { struct socket *soback; - if (so->so_proto->pr_flags & PR_WANTRCVD) { - /* - * Copy - Paste, but can't relock and sleep in - * sofree() in tcp(4) case. That's why tcp(4) - * still rely on solock() for splicing and - * unsplicing. - */ - - if (issplicedback(so)) { - int freeing = SOSP_FREEING_WRITE; - - if (so->so_sp->ssp_soback == so) - freeing |= SOSP_FREEING_READ; - sounsplice(so->so_sp->ssp_soback, so, freeing); - } - if (isspliced(so)) { - int freeing = SOSP_FREEING_READ; - - if (so == so->so_sp->ssp_socket) - freeing |= SOSP_FREEING_WRITE; - sounsplice(so, so->so_sp->ssp_socket, freeing); - } - goto free; - } - sounlock(so); mtx_enter(&so->so_snd.sb_mtx); /* @@ -530,7 +502,6 @@ notsplicedback: solock(so); } -free: #endif /* SOCKET_SPLICE */ /* sofree() calls sounlock(). */ sofree(so, 0); @@ -1532,8 +1503,7 @@ sosplice(struct socket *so, int fd, off_ void sounsplice(struct socket *so, struct socket *sosp, int freeing) { - if ((so->so_proto->pr_flags & PR_WANTRCVD) == 0) - sbassertlocked(&so->so_rcv); + sbassertlocked(&so->so_rcv); soassertlocked(so); task_del(sosplice_taskq, &so->so_splicetask); @@ -1587,17 +1557,23 @@ sotask(void *arg) */ sblock(&so->so_rcv, SBL_WAIT | SBL_NOINTR); - if (sockstream) - solock(so); - if (so->so_rcv.sb_flags & SB_SPLICE) { - if (sockstream) + struct socket *sosp = so->so_sp->ssp_socket; + + if (sockstream) { + sblock(&sosp->so_snd, SBL_WAIT | SBL_NOINTR); + solock(so); doyield = 1; + } + somove(so, M_DONTWAIT); + + if (sockstream) { + sounlock(so); + sbunlock(&sosp->so_snd); + } } - if (sockstream) - sounlock(so); sbunlock(&so->so_rcv); if (doyield) { @@ -1652,8 +1628,10 @@ somove(struct socket *so, int wait) if (sockdgram) sbassertlocked(&so->so_rcv); - else + else { + sbassertlocked(&sosp->so_snd); soassertlocked(so); + } mtx_enter(&so->so_rcv.sb_mtx); mtx_enter(&sosp->so_snd.sb_mtx);