From 8ee0399bd2620452620e993d7d77cd0df57d8ef4 Mon Sep 17 00:00:00 2001 From: mvs Date: Sat, 21 Dec 2024 00:10:04 +0000 Subject: [PATCH] Kill `inp_notify' list remains. This was the list where PCBs were temporary linked to avoid sleep with `inpt_mtx' mutex(9) held. in_pcbnotifyall() and in6_pcbnotify are the last list users, so switch them to in_pcb_iterator() too, moreover they already do in_pcb_is_iterator() check. Note, in_pcb_iterator() does necessary reference couter handling, unlocked `inp' dereference is safe. ok bluhm --- sys/netinet/in_pcb.c | 34 +++++++--------------------------- sys/netinet/in_pcb.h | 5 +---- sys/netinet6/in6_pcb.c | 24 +++++++----------------- 3 files changed, 15 insertions(+), 48 deletions(-) diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c index 5f30bdedef8..45019334d13 100644 --- a/sys/netinet/in_pcb.c +++ b/sys/netinet/in_pcb.c @@ -1,4 +1,4 @@ -/* $OpenBSD: in_pcb.c,v 1.305 2024/11/05 22:44:20 bluhm Exp $ */ +/* $OpenBSD: in_pcb.c,v 1.306 2024/12/21 00:10:04 mvs Exp $ */ /* $NetBSD: in_pcb.c,v 1.25 1996/02/13 23:41:53 christos Exp $ */ /* @@ -179,7 +179,6 @@ void in_pcbinit(struct inpcbtable *table, int hashsize) { mtx_init(&table->inpt_mtx, IPL_SOFTNET); - rw_init(&table->inpt_notify, "inpnotify"); TAILQ_INIT(&table->inpt_queue); table->inpt_hashtbl = hashinit(hashsize, M_PCB, M_WAITOK, &table->inpt_mask); @@ -763,8 +762,8 @@ void in_pcbnotifyall(struct inpcbtable *table, const struct sockaddr_in *dst, u_int rtable, int errno, void (*notify)(struct inpcb *, int)) { - SIMPLEQ_HEAD(, inpcb) inpcblist; - struct inpcb *inp; + struct inpcb_iterator iter = { .inp_table = NULL }; + struct inpcb *inp = NULL; u_int rdomain; if (dst->sin_addr.s_addr == INADDR_ANY) @@ -772,39 +771,20 @@ in_pcbnotifyall(struct inpcbtable *table, const struct sockaddr_in *dst, if (notify == NULL) return; - /* - * Use a temporary notify list protected by rwlock to run over - * selected PCB. This is necessary as the list of all PCB is - * protected by a mutex. Notify may call ip_output() eventually - * which may sleep as pf lock is a rwlock. Also the SRP - * implementation of the routing table might sleep. - * The same inp_notify list entry and inpt_notify rwlock are - * used for UDP multicast and raw IP delivery. - */ - SIMPLEQ_INIT(&inpcblist); rdomain = rtable_l2(rtable); - rw_enter_write(&table->inpt_notify); mtx_enter(&table->inpt_mtx); - TAILQ_FOREACH(inp, &table->inpt_queue, inp_queue) { - if (in_pcb_is_iterator(inp)) - continue; + while ((inp = in_pcb_iterator(table, inp, &iter)) != NULL) { KASSERT(!ISSET(inp->inp_flags, INP_IPV6)); if (inp->inp_faddr.s_addr != dst->sin_addr.s_addr || rtable_l2(inp->inp_rtableid) != rdomain) { continue; } - in_pcbref(inp); - SIMPLEQ_INSERT_TAIL(&inpcblist, inp, inp_notify); + mtx_leave(&table->inpt_mtx); + (*notify)(inp, errno); + mtx_enter(&table->inpt_mtx); } mtx_leave(&table->inpt_mtx); - - while ((inp = SIMPLEQ_FIRST(&inpcblist)) != NULL) { - SIMPLEQ_REMOVE_HEAD(&inpcblist, inp_notify); - (*notify)(inp, errno); - in_pcbunref(inp); - } - rw_exit_write(&table->inpt_notify); } /* diff --git a/sys/netinet/in_pcb.h b/sys/netinet/in_pcb.h index 0c7df7cbf78..4cffc7f5577 100644 --- a/sys/netinet/in_pcb.h +++ b/sys/netinet/in_pcb.h @@ -1,4 +1,4 @@ -/* $OpenBSD: in_pcb.h,v 1.159 2024/11/05 10:49:23 bluhm Exp $ */ +/* $OpenBSD: in_pcb.h,v 1.160 2024/12/21 00:10:04 mvs Exp $ */ /* $NetBSD: in_pcb.h,v 1.14 1996/02/13 23:42:00 christos Exp $ */ /* @@ -79,7 +79,6 @@ * I immutable after creation * N net lock * t inpt_mtx pcb table mutex - * y inpt_notify pcb table rwlock for notify * L pf_inp_mtx link pf to inp mutex * s so_lock socket rwlock */ @@ -128,7 +127,6 @@ struct inpcb { LIST_ENTRY(inpcb) inp_hash; /* [t] local and foreign hash */ LIST_ENTRY(inpcb) inp_lhash; /* [t] local port hash */ TAILQ_ENTRY(inpcb) inp_queue; /* [t] inet PCB queue */ - SIMPLEQ_ENTRY(inpcb) inp_notify; /* [y] notify or udp append */ struct inpcbtable *inp_table; /* [I] inet queue/hash table */ union inpaddru inp_faddru; /* [t] Foreign address. */ union inpaddru inp_laddru; /* [t] Local address. */ @@ -194,7 +192,6 @@ in_pcb_is_iterator(struct inpcb *inp) struct inpcbtable { struct mutex inpt_mtx; /* protect queue and hash */ - struct rwlock inpt_notify; /* protect inp_notify list */ TAILQ_HEAD(inpthead, inpcb) inpt_queue; /* [t] inet PCB queue */ struct inpcbhead *inpt_hashtbl; /* [t] local and foreign hash */ struct inpcbhead *inpt_lhashtbl; /* [t] local port hash */ diff --git a/sys/netinet6/in6_pcb.c b/sys/netinet6/in6_pcb.c index ace897cc4f1..1b4fc1786af 100644 --- a/sys/netinet6/in6_pcb.c +++ b/sys/netinet6/in6_pcb.c @@ -1,4 +1,4 @@ -/* $OpenBSD: in6_pcb.c,v 1.145 2024/11/05 10:49:23 bluhm Exp $ */ +/* $OpenBSD: in6_pcb.c,v 1.146 2024/12/21 00:10:04 mvs Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -427,8 +427,8 @@ in6_pcbnotify(struct inpcbtable *table, const struct sockaddr_in6 *dst, uint fport_arg, const struct sockaddr_in6 *src, uint lport_arg, u_int rtable, int cmd, void *cmdarg, void (*notify)(struct inpcb *, int)) { - SIMPLEQ_HEAD(, inpcb) inpcblist; - struct inpcb *inp; + struct inpcb_iterator iter = { .inp_table = NULL }; + struct inpcb *inp = NULL; u_short fport = fport_arg, lport = lport_arg; struct sockaddr_in6 sa6_src; int errno; @@ -474,13 +474,9 @@ in6_pcbnotify(struct inpcbtable *table, const struct sockaddr_in6 *dst, if (notify == NULL) return; - SIMPLEQ_INIT(&inpcblist); rdomain = rtable_l2(rtable); - rw_enter_write(&table->inpt_notify); mtx_enter(&table->inpt_mtx); - TAILQ_FOREACH(inp, &table->inpt_queue, inp_queue) { - if (in_pcb_is_iterator(inp)) - continue; + while ((inp = in_pcb_iterator(table, inp, &iter)) != NULL) { KASSERT(ISSET(inp->inp_flags, INP_IPV6)); /* @@ -546,17 +542,11 @@ in6_pcbnotify(struct inpcbtable *table, const struct sockaddr_in6 *dst, continue; } do_notify: - in_pcbref(inp); - SIMPLEQ_INSERT_TAIL(&inpcblist, inp, inp_notify); + mtx_leave(&table->inpt_mtx); + (*notify)(inp, errno); + mtx_enter(&table->inpt_mtx); } mtx_leave(&table->inpt_mtx); - - while ((inp = SIMPLEQ_FIRST(&inpcblist)) != NULL) { - SIMPLEQ_REMOVE_HEAD(&inpcblist, inp_notify); - (*notify)(inp, errno); - in_pcbunref(inp); - } - rw_exit_write(&table->inpt_notify); } struct rtentry *