From: Alexander Bluhm Subject: Re: Please test: shared solock for all intet sockets within knote(9) routines To: Vitaliy Makkoveev Cc: tech@openbsd.org Date: Thu, 1 Feb 2024 19:35:04 +0100 On Thu, Feb 01, 2024 at 01:07:14AM +0300, Vitaliy Makkoveev wrote: > Sorry, I forgot to change knote_locked() to knote() within > sohasoutofband(). This diff fixes it. Also sblock() fix included. > > Since the `sb_klist' uses `sb_mtx' mutex(9) for protection, special > `socket_klistops' is not required anymore and was removed. This line is missing. const struct pr_usrreqs divert6_usrreqs = { .pru_locked = divert_locked, [-- MARK -- Thu Feb 1 15:35:00 2024] splassert: soassertlocked: want 0 have 1 Starting stack trace... soassertlocked(0) at soassertlocked+0xc7 soassertlocked(d7e2543c) at soassertlocked+0xc7 sbappendaddr(d7e2543c,d7e254b0,f580280c,d914fa00,0) at sbappendaddr+0x18 divert6_packet(d914fa00,1,9a02) at divert6_packet+0x24e pf_test(18,1,d836e830,f5802a50) at pf_test+0x929 ip6_input_if(f5802a50,f5802a3c,29,0,d836e830) at ip6_input_if+0x1bd ipv6_input(d836e830,d914fa00) at ipv6_input+0x2b ether_input(d836e830,d914fa00) at ether_input+0x2c4 if_input_process(d836e830,f5802aa4) at if_input_process+0x4d ifiq_process(d836eb00) at ifiq_process+0x66 taskq_thread(d82f9000) at taskq_thread+0x84 End of stack trace. splassert: soassertlocked: want 0 have 1 Starting stack trace... soassertlocked(0) at soassertlocked+0xc7 soassertlocked(d7e2595c) at soassertlocked+0xc7 sbappendaddr(d7e2595c,d7e259d0,f5a1005c,d8865600,0) at sbappendaddr+0x18 divert6_packet(d8865600,2,9a02) at divert6_packet+0x24e pf_test(18,2,d836e830,f5a1027c) at pf_test+0x929 ip6_output(d8865600,0,d7e40634,0,0,d7e406bc) at ip6_output+0xc27 udp6_output(d7e405e8,d8865600,0,0) at udp6_output+0x3fd udp_send(d7e2543c,d8865600,0,0) at udp_send+0xbe sosend(d7e2543c,0,f5a103ec,d8865600,0,0) at sosend+0x2d8 sendit(d7e54360,1,f5a10440,0,f5a104b8) at sendit+0x2cc sys_sendto(d7e54360,f5a104c0,f5a104b8) at sys_sendto+0x5c syscall(f5a10500) at syscall+0x55e Xsyscall_untramp() at Xsyscall_untramp+0xa9 end of kernel End of stack trace. [-- MARK -- Thu Feb 1 15:40:00 2024] With that fixed, OK bluhm@ All regress pass, I think it should be commited. bluhm > Index: sys/kern/uipc_socket.c > =================================================================== > RCS file: /cvs/src/sys/kern/uipc_socket.c,v > retrieving revision 1.315 > diff -u -p -r1.315 uipc_socket.c > --- sys/kern/uipc_socket.c 26 Jan 2024 18:24:23 -0000 1.315 > +++ sys/kern/uipc_socket.c 31 Jan 2024 22:06:44 -0000 > @@ -72,26 +72,20 @@ int filt_soread(struct knote *kn, long h > void filt_sowdetach(struct knote *kn); > int filt_sowrite(struct knote *kn, long hint); > int filt_soexcept(struct knote *kn, long hint); > -int filt_solisten(struct knote *kn, long hint); > -int filt_somodify(struct kevent *kev, struct knote *kn); > -int filt_soprocess(struct knote *kn, struct kevent *kev); > > -const struct filterops solisten_filtops = { > - .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, > - .f_attach = NULL, > - .f_detach = filt_sordetach, > - .f_event = filt_solisten, > - .f_modify = filt_somodify, > - .f_process = filt_soprocess, > -}; > +int filt_snd_somodify(struct kevent *kev, struct knote *kn); > +int filt_snd_soprocess(struct knote *kn, struct kevent *kev); > + > +int filt_rcv_somodify(struct kevent *kev, struct knote *kn); > +int filt_rcv_soprocess(struct knote *kn, struct kevent *kev); > > const struct filterops soread_filtops = { > .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, > .f_attach = NULL, > .f_detach = filt_sordetach, > .f_event = filt_soread, > - .f_modify = filt_somodify, > - .f_process = filt_soprocess, > + .f_modify = filt_rcv_somodify, > + .f_process = filt_rcv_soprocess, > }; > > const struct filterops sowrite_filtops = { > @@ -99,8 +93,8 @@ const struct filterops sowrite_filtops = > .f_attach = NULL, > .f_detach = filt_sowdetach, > .f_event = filt_sowrite, > - .f_modify = filt_somodify, > - .f_process = filt_soprocess, > + .f_modify = filt_snd_somodify, > + .f_process = filt_snd_soprocess, > }; > > const struct filterops soexcept_filtops = { > @@ -108,18 +102,8 @@ const struct filterops soexcept_filtops > .f_attach = NULL, > .f_detach = filt_sordetach, > .f_event = filt_soexcept, > - .f_modify = filt_somodify, > - .f_process = filt_soprocess, > -}; > - > -void klist_soassertlk(void *); > -int klist_solock(void *); > -void klist_sounlock(void *, int); > - > -const struct klistops socket_klistops = { > - .klo_assertlk = klist_soassertlk, > - .klo_lock = klist_solock, > - .klo_unlock = klist_sounlock, > + .f_modify = filt_rcv_somodify, > + .f_process = filt_rcv_soprocess, > }; > > #ifndef SOMINCONN > @@ -158,8 +142,10 @@ soalloc(const struct domain *dp, int wai > return (NULL); > rw_init_flags(&so->so_lock, dp->dom_name, RWL_DUPOK); > refcnt_init(&so->so_refcnt); > - klist_init(&so->so_rcv.sb_klist, &socket_klistops, so); > - klist_init(&so->so_snd.sb_klist, &socket_klistops, so); > + mtx_init(&so->so_rcv.sb_mtx, IPL_MPFLOOR); > + mtx_init(&so->so_snd.sb_mtx, IPL_MPFLOOR); > + klist_init_mutex(&so->so_rcv.sb_klist, &so->so_rcv.sb_mtx); > + klist_init_mutex(&so->so_snd.sb_klist, &so->so_snd.sb_mtx); > sigio_init(&so->so_sigio); > TAILQ_INIT(&so->so_q0); > TAILQ_INIT(&so->so_q); > @@ -1757,7 +1743,7 @@ somove(struct socket *so, int wait) > void > sorwakeup(struct socket *so) > { > - soassertlocked(so); > + soassertlocked_readonly(so); > > #ifdef SOCKET_SPLICE > if (so->so_rcv.sb_flags & SB_SPLICE) { > @@ -1785,7 +1771,7 @@ sorwakeup(struct socket *so) > void > sowwakeup(struct socket *so) > { > - soassertlocked(so); > + soassertlocked_readonly(so); > > #ifdef SOCKET_SPLICE > if (so->so_snd.sb_flags & SB_SPLICE) > @@ -2134,7 +2120,46 @@ void > sohasoutofband(struct socket *so) > { > pgsigio(&so->so_sigio, SIGURG, 0); > - knote_locked(&so->so_rcv.sb_klist, 0); > + knote(&so->so_rcv.sb_klist, 0); > +} > + > +void > +sofilt_lock(struct socket *so, struct sockbuf *sb) > +{ > + switch (so->so_proto->pr_domain->dom_family) { > + case PF_INET: > + case PF_INET6: > + NET_LOCK_SHARED(); > + break; > + default: > + rw_enter_write(&so->so_lock); > + break; > + } > + > + mtx_enter(&sb->sb_mtx); > +} > + > +void > +sofilt_unlock(struct socket *so, struct sockbuf *sb) > +{ > + mtx_leave(&sb->sb_mtx); > + > + switch (so->so_proto->pr_domain->dom_family) { > + case PF_INET: > + case PF_INET6: > + NET_UNLOCK_SHARED(); > + break; > + default: > + rw_exit_write(&so->so_lock); > + break; > + } > +} > + > +static inline void > +sofilt_assert_locked(struct socket *so, struct sockbuf *sb) > +{ > + MUTEX_ASSERT_LOCKED(&sb->sb_mtx); > + soassertlocked_readonly(so); > } > > int > @@ -2143,13 +2168,9 @@ soo_kqfilter(struct file *fp, struct kno > struct socket *so = kn->kn_fp->f_data; > struct sockbuf *sb; > > - solock(so); > switch (kn->kn_filter) { > case EVFILT_READ: > - if (so->so_options & SO_ACCEPTCONN) > - kn->kn_fop = &solisten_filtops; > - else > - kn->kn_fop = &soread_filtops; > + kn->kn_fop = &soread_filtops; > sb = &so->so_rcv; > break; > case EVFILT_WRITE: > @@ -2161,12 +2182,12 @@ soo_kqfilter(struct file *fp, struct kno > sb = &so->so_rcv; > break; > default: > - sounlock(so); > return (EINVAL); > } > > + mtx_enter(&sb->sb_mtx); > klist_insert_locked(&sb->sb_klist, kn); > - sounlock(so); > + mtx_leave(&sb->sb_mtx); > > return (0); > } > @@ -2185,7 +2206,23 @@ filt_soread(struct knote *kn, long hint) > struct socket *so = kn->kn_fp->f_data; > int rv = 0; > > - soassertlocked(so); > + sofilt_assert_locked(so, &so->so_rcv); > + > + if (so->so_options & SO_ACCEPTCONN) { > + kn->kn_data = so->so_qlen; > + rv = (kn->kn_data != 0); > + > + if (kn->kn_flags & (__EV_POLL | __EV_SELECT)) { > + if (so->so_state & SS_ISDISCONNECTED) { > + kn->kn_flags |= __EV_HUP; > + rv = 1; > + } else { > + rv = soreadable(so); > + } > + } > + > + return rv; > + } > > kn->kn_data = so->so_rcv.sb_cc; > #ifdef SOCKET_SPLICE > @@ -2226,7 +2263,7 @@ filt_sowrite(struct knote *kn, long hint > struct socket *so = kn->kn_fp->f_data; > int rv; > > - soassertlocked(so); > + sofilt_assert_locked(so, &so->so_snd); > > kn->kn_data = sbspace(so, &so->so_snd); > if (so->so_snd.sb_state & SS_CANTSENDMORE) { > @@ -2257,7 +2294,7 @@ filt_soexcept(struct knote *kn, long hin > struct socket *so = kn->kn_fp->f_data; > int rv = 0; > > - soassertlocked(so); > + sofilt_assert_locked(so, &so->so_rcv); > > #ifdef SOCKET_SPLICE > if (isspliced(so)) { > @@ -2283,77 +2320,55 @@ filt_soexcept(struct knote *kn, long hin > } > > int > -filt_solisten(struct knote *kn, long hint) > +filt_snd_somodify(struct kevent *kev, struct knote *kn) > { > struct socket *so = kn->kn_fp->f_data; > - int active; > - > - soassertlocked(so); > - > - kn->kn_data = so->so_qlen; > - active = (kn->kn_data != 0); > + int rv; > > - if (kn->kn_flags & (__EV_POLL | __EV_SELECT)) { > - if (so->so_state & SS_ISDISCONNECTED) { > - kn->kn_flags |= __EV_HUP; > - active = 1; > - } else { > - active = soreadable(so); > - } > - } > + sofilt_lock(so, &so->so_snd); > + rv = knote_modify(kev, kn); > + sofilt_unlock(so, &so->so_snd); > > - return (active); > + return (rv); > } > > int > -filt_somodify(struct kevent *kev, struct knote *kn) > +filt_snd_soprocess(struct knote *kn, struct kevent *kev) > { > struct socket *so = kn->kn_fp->f_data; > int rv; > > - solock(so); > - rv = knote_modify(kev, kn); > - sounlock(so); > + sofilt_lock(so, &so->so_snd); > + rv = knote_process(kn, kev); > + sofilt_unlock(so, &so->so_snd); > > return (rv); > } > > int > -filt_soprocess(struct knote *kn, struct kevent *kev) > +filt_rcv_somodify(struct kevent *kev, struct knote *kn) > { > struct socket *so = kn->kn_fp->f_data; > int rv; > > - solock(so); > - rv = knote_process(kn, kev); > - sounlock(so); > + sofilt_lock(so, &so->so_rcv); > + rv = knote_modify(kev, kn); > + sofilt_unlock(so, &so->so_rcv); > > return (rv); > } > > -void > -klist_soassertlk(void *arg) > -{ > - struct socket *so = arg; > - > - soassertlocked(so); > -} > - > int > -klist_solock(void *arg) > +filt_rcv_soprocess(struct knote *kn, struct kevent *kev) > { > - struct socket *so = arg; > - > - solock(so); > - return (1); > -} > + struct socket *so = kn->kn_fp->f_data; > + int rv; > > -void > -klist_sounlock(void *arg, int ls) > -{ > - struct socket *so = arg; > + sofilt_lock(so, &so->so_rcv); > + rv = knote_process(kn, kev); > + sofilt_unlock(so, &so->so_rcv); > > - sounlock(so); > + return (rv); > } > > #ifdef DDB > Index: sys/kern/uipc_socket2.c > =================================================================== > RCS file: /cvs/src/sys/kern/uipc_socket2.c,v > retrieving revision 1.140 > diff -u -p -r1.140 uipc_socket2.c > --- sys/kern/uipc_socket2.c 11 Jan 2024 14:15:11 -0000 1.140 > +++ sys/kern/uipc_socket2.c 31 Jan 2024 22:06:44 -0000 > @@ -439,7 +439,7 @@ sounlock_shared(struct socket *so) > } > > void > -soassertlocked(struct socket *so) > +soassertlocked_readonly(struct socket *so) > { > switch (so->so_proto->pr_domain->dom_family) { > case PF_INET: > @@ -452,6 +452,27 @@ soassertlocked(struct socket *so) > } > } > > +void > +soassertlocked(struct socket *so) > +{ > + switch (so->so_proto->pr_domain->dom_family) { > + case PF_INET: > + case PF_INET6: > + if (rw_status(&netlock) == RW_READ) { > + NET_ASSERT_LOCKED(); > + > + if (splassert_ctl > 0 && pru_locked(so) == 0 && > + rw_status(&so->so_lock) != RW_WRITE) > + splassert_fail(0, RW_WRITE, __func__); > + } else > + NET_ASSERT_LOCKED_EXCLUSIVE(); > + break; > + default: > + rw_assert_wrlock(&so->so_lock); > + break; > + } > +} > + > int > sosleep_nsec(struct socket *so, void *ident, int prio, const char *wmesg, > uint64_t nsecs) > @@ -489,46 +510,62 @@ sbwait(struct socket *so, struct sockbuf > > soassertlocked(so); > > + mtx_enter(&sb->sb_mtx); > sb->sb_flags |= SB_WAIT; > + mtx_leave(&sb->sb_mtx); > + > return sosleep_nsec(so, &sb->sb_cc, prio, "netio", sb->sb_timeo_nsecs); > } > > int > sblock(struct socket *so, struct sockbuf *sb, int flags) > { > - int error, prio = PSOCK; > + int error = 0, prio = PSOCK; > > soassertlocked(so); > > + mtx_enter(&sb->sb_mtx); > if ((sb->sb_flags & SB_LOCK) == 0) { > sb->sb_flags |= SB_LOCK; > - return (0); > + goto out; > + } > + if ((flags & SBL_WAIT) == 0) { > + error = EWOULDBLOCK; > + goto out; > } > - if ((flags & SBL_WAIT) == 0) > - return (EWOULDBLOCK); > if (!(flags & SBL_NOINTR || sb->sb_flags & SB_NOINTR)) > prio |= PCATCH; > > while (sb->sb_flags & SB_LOCK) { > sb->sb_flags |= SB_WANT; > + mtx_leave(&sb->sb_mtx); > error = sosleep_nsec(so, &sb->sb_flags, prio, "netlck", INFSLP); > if (error) > return (error); > + mtx_enter(&sb->sb_mtx); > } > sb->sb_flags |= SB_LOCK; > - return (0); > +out: > + mtx_leave(&sb->sb_mtx); > + > + return (error); > } > > void > sbunlock(struct socket *so, struct sockbuf *sb) > { > - soassertlocked(so); > + int dowakeup = 0; > > + mtx_enter(&sb->sb_mtx); > sb->sb_flags &= ~SB_LOCK; > if (sb->sb_flags & SB_WANT) { > sb->sb_flags &= ~SB_WANT; > - wakeup(&sb->sb_flags); > + dowakeup = 1; > } > + mtx_leave(&sb->sb_mtx); > + > + if (dowakeup) > + wakeup(&sb->sb_flags); > } > > /* > @@ -539,15 +576,24 @@ sbunlock(struct socket *so, struct sockb > void > sowakeup(struct socket *so, struct sockbuf *sb) > { > - soassertlocked(so); > + int dowakeup = 0, dopgsigio = 0; > > + mtx_enter(&sb->sb_mtx); > if (sb->sb_flags & SB_WAIT) { > sb->sb_flags &= ~SB_WAIT; > - wakeup(&sb->sb_cc); > + dowakeup = 1; > } > if (sb->sb_flags & SB_ASYNC) > - pgsigio(&so->so_sigio, SIGIO, 0); > + dopgsigio = 1; > + > knote_locked(&sb->sb_klist, 0); > + mtx_leave(&sb->sb_mtx); > + > + if (dowakeup) > + wakeup(&sb->sb_cc); > + > + if (dopgsigio) > + pgsigio(&so->so_sigio, SIGIO, 0); > } > > /* > Index: sys/kern/uipc_syscalls.c > =================================================================== > RCS file: /cvs/src/sys/kern/uipc_syscalls.c,v > retrieving revision 1.216 > diff -u -p -r1.216 uipc_syscalls.c > --- sys/kern/uipc_syscalls.c 3 Jan 2024 11:07:04 -0000 1.216 > +++ sys/kern/uipc_syscalls.c 31 Jan 2024 22:06:44 -0000 > @@ -326,7 +326,7 @@ doaccept(struct proc *p, int sock, struc > : (flags & SOCK_NONBLOCK ? FNONBLOCK : 0); > > /* connection has been removed from the listen queue */ > - knote_locked(&head->so_rcv.sb_klist, 0); > + knote(&head->so_rcv.sb_klist, 0); > > if (persocket) > sounlock(head); > Index: sys/netinet/ip_divert.c > =================================================================== > RCS file: /cvs/src/sys/netinet/ip_divert.c,v > retrieving revision 1.92 > diff -u -p -r1.92 ip_divert.c > --- sys/netinet/ip_divert.c 16 Sep 2023 09:33:27 -0000 1.92 > +++ sys/netinet/ip_divert.c 31 Jan 2024 22:06:44 -0000 > @@ -67,6 +67,7 @@ const struct pr_usrreqs divert_usrreqs = > .pru_detach = divert_detach, > .pru_lock = divert_lock, > .pru_unlock = divert_unlock, > + .pru_locked = divert_locked, > .pru_bind = divert_bind, > .pru_shutdown = divert_shutdown, > .pru_send = divert_send, > @@ -311,6 +312,14 @@ divert_unlock(struct socket *so) > > NET_ASSERT_LOCKED(); > mtx_leave(&inp->inp_mtx); > +} > + > +int > +divert_locked(struct socket *so) > +{ > + struct inpcb *inp = sotoinpcb(so); > + > + return mtx_owned(&inp->inp_mtx); > } > > int > Index: sys/netinet/ip_divert.h > =================================================================== > RCS file: /cvs/src/sys/netinet/ip_divert.h,v > retrieving revision 1.24 > diff -u -p -r1.24 ip_divert.h > --- sys/netinet/ip_divert.h 17 Oct 2022 14:49:02 -0000 1.24 > +++ sys/netinet/ip_divert.h 31 Jan 2024 22:06:44 -0000 > @@ -74,6 +74,7 @@ int divert_attach(struct socket *, int, > int divert_detach(struct socket *); > void divert_lock(struct socket *); > void divert_unlock(struct socket *); > +int divert_locked(struct socket *); > int divert_bind(struct socket *, struct mbuf *, struct proc *); > int divert_shutdown(struct socket *); > int divert_send(struct socket *, struct mbuf *, struct mbuf *, > Index: sys/netinet/ip_var.h > =================================================================== > RCS file: /cvs/src/sys/netinet/ip_var.h,v > retrieving revision 1.110 > diff -u -p -r1.110 ip_var.h > --- sys/netinet/ip_var.h 26 Nov 2023 22:08:10 -0000 1.110 > +++ sys/netinet/ip_var.h 31 Jan 2024 22:06:44 -0000 > @@ -260,6 +260,7 @@ int rip_attach(struct socket *, int, in > int rip_detach(struct socket *); > void rip_lock(struct socket *); > void rip_unlock(struct socket *); > +int rip_locked(struct socket *); > int rip_bind(struct socket *, struct mbuf *, struct proc *); > int rip_connect(struct socket *, struct mbuf *); > int rip_disconnect(struct socket *); > Index: sys/netinet/raw_ip.c > =================================================================== > RCS file: /cvs/src/sys/netinet/raw_ip.c,v > retrieving revision 1.154 > diff -u -p -r1.154 raw_ip.c > --- sys/netinet/raw_ip.c 21 Jan 2024 01:17:20 -0000 1.154 > +++ sys/netinet/raw_ip.c 31 Jan 2024 22:06:44 -0000 > @@ -108,6 +108,7 @@ const struct pr_usrreqs rip_usrreqs = { > .pru_detach = rip_detach, > .pru_lock = rip_lock, > .pru_unlock = rip_unlock, > + .pru_locked = rip_locked, > .pru_bind = rip_bind, > .pru_connect = rip_connect, > .pru_disconnect = rip_disconnect, > @@ -522,6 +523,14 @@ rip_unlock(struct socket *so) > > NET_ASSERT_LOCKED(); > mtx_leave(&inp->inp_mtx); > +} > + > +int > +rip_locked(struct socket *so) > +{ > + struct inpcb *inp = sotoinpcb(so); > + > + return mtx_owned(&inp->inp_mtx); > } > > int > Index: sys/netinet/udp_usrreq.c > =================================================================== > RCS file: /cvs/src/sys/netinet/udp_usrreq.c,v > retrieving revision 1.316 > diff -u -p -r1.316 udp_usrreq.c > --- sys/netinet/udp_usrreq.c 28 Jan 2024 20:34:25 -0000 1.316 > +++ sys/netinet/udp_usrreq.c 31 Jan 2024 22:06:44 -0000 > @@ -127,6 +127,7 @@ const struct pr_usrreqs udp_usrreqs = { > .pru_detach = udp_detach, > .pru_lock = udp_lock, > .pru_unlock = udp_unlock, > + .pru_locked = udp_locked, > .pru_bind = udp_bind, > .pru_connect = udp_connect, > .pru_disconnect = udp_disconnect, > @@ -143,6 +144,7 @@ const struct pr_usrreqs udp6_usrreqs = { > .pru_detach = udp_detach, > .pru_lock = udp_lock, > .pru_unlock = udp_unlock, > + .pru_locked = udp_locked, > .pru_bind = udp_bind, > .pru_connect = udp_connect, > .pru_disconnect = udp_disconnect, > @@ -1154,6 +1156,14 @@ udp_unlock(struct socket *so) > > NET_ASSERT_LOCKED(); > mtx_leave(&inp->inp_mtx); > +} > + > +int > +udp_locked(struct socket *so) > +{ > + struct inpcb *inp = sotoinpcb(so); > + > + return mtx_owned(&inp->inp_mtx); > } > > int > Index: sys/netinet/udp_var.h > =================================================================== > RCS file: /cvs/src/sys/netinet/udp_var.h,v > retrieving revision 1.50 > diff -u -p -r1.50 udp_var.h > --- sys/netinet/udp_var.h 10 Jan 2024 16:44:30 -0000 1.50 > +++ sys/netinet/udp_var.h 31 Jan 2024 22:06:44 -0000 > @@ -147,6 +147,7 @@ int udp_attach(struct socket *, int, in > int udp_detach(struct socket *); > void udp_lock(struct socket *); > void udp_unlock(struct socket *); > +int udp_locked(struct socket *); > int udp_bind(struct socket *, struct mbuf *, struct proc *); > int udp_connect(struct socket *, struct mbuf *); > int udp_disconnect(struct socket *); > Index: sys/netinet6/ip6_mroute.c > =================================================================== > RCS file: /cvs/src/sys/netinet6/ip6_mroute.c,v > retrieving revision 1.138 > diff -u -p -r1.138 ip6_mroute.c > --- sys/netinet6/ip6_mroute.c 6 Dec 2023 09:27:17 -0000 1.138 > +++ sys/netinet6/ip6_mroute.c 31 Jan 2024 22:06:44 -0000 > @@ -861,12 +861,12 @@ socket6_send(struct socket *so, struct m > > mtx_enter(&inp->inp_mtx); > ret = sbappendaddr(so, &so->so_rcv, sin6tosa(src), mm, NULL); > + if (ret != 0) > + sorwakeup(so); > mtx_leave(&inp->inp_mtx); > > - if (ret != 0) { > - sorwakeup(so); > + if (ret != 0) > return 0; > - } > } > m_freem(mm); > return -1; > Index: sys/netinet6/ip6_var.h > =================================================================== > RCS file: /cvs/src/sys/netinet6/ip6_var.h,v > retrieving revision 1.109 > diff -u -p -r1.109 ip6_var.h > --- sys/netinet6/ip6_var.h 3 Dec 2023 20:36:24 -0000 1.109 > +++ sys/netinet6/ip6_var.h 31 Jan 2024 22:06:44 -0000 > @@ -353,6 +353,7 @@ int rip6_attach(struct socket *, int, in > int rip6_detach(struct socket *); > void rip6_lock(struct socket *); > void rip6_unlock(struct socket *); > +int rip6_locked(struct socket *); > int rip6_bind(struct socket *, struct mbuf *, struct proc *); > int rip6_connect(struct socket *, struct mbuf *); > int rip6_disconnect(struct socket *); > Index: sys/netinet6/raw_ip6.c > =================================================================== > RCS file: /cvs/src/sys/netinet6/raw_ip6.c,v > retrieving revision 1.179 > diff -u -p -r1.179 raw_ip6.c > --- sys/netinet6/raw_ip6.c 21 Jan 2024 01:17:20 -0000 1.179 > +++ sys/netinet6/raw_ip6.c 31 Jan 2024 22:06:44 -0000 > @@ -110,6 +110,7 @@ const struct pr_usrreqs rip6_usrreqs = { > .pru_detach = rip6_detach, > .pru_lock = rip6_lock, > .pru_unlock = rip6_unlock, > + .pru_locked = rip6_locked, > .pru_bind = rip6_bind, > .pru_connect = rip6_connect, > .pru_disconnect = rip6_disconnect, > @@ -651,6 +652,14 @@ rip6_unlock(struct socket *so) > > NET_ASSERT_LOCKED(); > mtx_leave(&inp->inp_mtx); > +} > + > +int > +rip6_locked(struct socket *so) > +{ > + struct inpcb *inp = sotoinpcb(so); > + > + return mtx_owned(&inp->inp_mtx); > } > > int > Index: sys/sys/mutex.h > =================================================================== > RCS file: /cvs/src/sys/sys/mutex.h,v > retrieving revision 1.19 > diff -u -p -r1.19 mutex.h > --- sys/sys/mutex.h 1 Dec 2023 14:37:22 -0000 1.19 > +++ sys/sys/mutex.h 31 Jan 2024 22:06:44 -0000 > @@ -127,6 +127,9 @@ void mtx_leave(struct mutex *); > > #define mtx_init(m, ipl) mtx_init_flags(m, ipl, NULL, 0) > > +#define mtx_owned(mtx) \ > + (((mtx)->mtx_owner == curcpu()) || panicstr || db_active) > + > #ifdef WITNESS > > void _mtx_init_flags(struct mutex *, int, const char *, int, > Index: sys/sys/protosw.h > =================================================================== > RCS file: /cvs/src/sys/sys/protosw.h,v > retrieving revision 1.64 > diff -u -p -r1.64 protosw.h > --- sys/sys/protosw.h 11 Jan 2024 14:15:12 -0000 1.64 > +++ sys/sys/protosw.h 31 Jan 2024 22:06:44 -0000 > @@ -69,6 +69,7 @@ struct pr_usrreqs { > int (*pru_detach)(struct socket *); > void (*pru_lock)(struct socket *); > void (*pru_unlock)(struct socket *); > + int (*pru_locked)(struct socket *so); > int (*pru_bind)(struct socket *, struct mbuf *, struct proc *); > int (*pru_listen)(struct socket *); > int (*pru_connect)(struct socket *, struct mbuf *); > @@ -294,6 +295,14 @@ pru_unlock(struct socket *so) > { > if (so->so_proto->pr_usrreqs->pru_unlock) > (*so->so_proto->pr_usrreqs->pru_unlock)(so); > +} > + > +static inline int > +pru_locked(struct socket *so) > +{ > + if (so->so_proto->pr_usrreqs->pru_locked) > + return (*so->so_proto->pr_usrreqs->pru_locked)(so); > + return (0); > } > > static inline int > Index: sys/sys/socketvar.h > =================================================================== > RCS file: /cvs/src/sys/sys/socketvar.h,v > retrieving revision 1.121 > diff -u -p -r1.121 socketvar.h > --- sys/sys/socketvar.h 11 Jan 2024 14:15:12 -0000 1.121 > +++ sys/sys/socketvar.h 31 Jan 2024 22:06:44 -0000 > @@ -40,6 +40,7 @@ > #include /* for struct sigio_ref */ > #include > #include > +#include > #include > #include > > @@ -105,6 +106,7 @@ struct socket { > * Variables for socket buffering. > */ > struct sockbuf { > + struct mutex sb_mtx; > /* The following fields are all zeroed on flush. */ > #define sb_startzero sb_cc > u_long sb_cc; /* actual chars in buffer */ > @@ -174,6 +176,7 @@ struct socket { > #include > > void soassertlocked(struct socket *); > +void soassertlocked_readonly(struct socket *); > > static inline void > soref(struct socket *so) > @@ -200,9 +203,16 @@ sorele(struct socket *so) > static inline int > sb_notify(struct socket *so, struct sockbuf *sb) > { > + int rv; > + > soassertlocked(so); > - return ((sb->sb_flags & (SB_WAIT|SB_ASYNC|SB_SPLICE)) != 0 || > + > + mtx_enter(&sb->sb_mtx); > + rv = ((sb->sb_flags & (SB_WAIT|SB_ASYNC|SB_SPLICE)) != 0 || > !klist_empty(&sb->sb_klist)); > + mtx_leave(&sb->sb_mtx); > + > + return rv; > } > > /* > @@ -211,10 +221,12 @@ sb_notify(struct socket *so, struct sock > * still be negative (cc > hiwat or mbcnt > mbmax). Should detect > * overflow and return 0. > */ > + > static inline long > sbspace(struct socket *so, struct sockbuf *sb) > { > - soassertlocked(so); > + soassertlocked_readonly(so); > + > return lmin(sb->sb_hiwat - sb->sb_cc, sb->sb_mbmax - sb->sb_mbcnt); > } > > @@ -230,7 +242,7 @@ sbspace(struct socket *so, struct sockbu > static inline int > soreadable(struct socket *so) > { > - soassertlocked(so); > + soassertlocked_readonly(so); > if (isspliced(so)) > return 0; > return (so->so_rcv.sb_state & SS_CANTRCVMORE) || so->so_qlen || > @@ -241,7 +253,7 @@ soreadable(struct socket *so) > static inline int > sowriteable(struct socket *so) > { > - soassertlocked(so); > + soassertlocked_readonly(so); > return ((sbspace(so, &so->so_snd) >= so->so_snd.sb_lowat && > ((so->so_state & SS_ISCONNECTED) || > (so->so_proto->pr_flags & PR_CONNREQUIRED)==0)) ||