mirror of
https://github.com/openbsd/src.git
synced 2024-12-21 23:18:00 -08:00
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
This commit is contained in:
parent
77d0f8231d
commit
8ee0399bd2
@ -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 $ */
|
/* $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)
|
in_pcbinit(struct inpcbtable *table, int hashsize)
|
||||||
{
|
{
|
||||||
mtx_init(&table->inpt_mtx, IPL_SOFTNET);
|
mtx_init(&table->inpt_mtx, IPL_SOFTNET);
|
||||||
rw_init(&table->inpt_notify, "inpnotify");
|
|
||||||
TAILQ_INIT(&table->inpt_queue);
|
TAILQ_INIT(&table->inpt_queue);
|
||||||
table->inpt_hashtbl = hashinit(hashsize, M_PCB, M_WAITOK,
|
table->inpt_hashtbl = hashinit(hashsize, M_PCB, M_WAITOK,
|
||||||
&table->inpt_mask);
|
&table->inpt_mask);
|
||||||
@ -763,8 +762,8 @@ void
|
|||||||
in_pcbnotifyall(struct inpcbtable *table, const struct sockaddr_in *dst,
|
in_pcbnotifyall(struct inpcbtable *table, const struct sockaddr_in *dst,
|
||||||
u_int rtable, int errno, void (*notify)(struct inpcb *, int))
|
u_int rtable, int errno, void (*notify)(struct inpcb *, int))
|
||||||
{
|
{
|
||||||
SIMPLEQ_HEAD(, inpcb) inpcblist;
|
struct inpcb_iterator iter = { .inp_table = NULL };
|
||||||
struct inpcb *inp;
|
struct inpcb *inp = NULL;
|
||||||
u_int rdomain;
|
u_int rdomain;
|
||||||
|
|
||||||
if (dst->sin_addr.s_addr == INADDR_ANY)
|
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)
|
if (notify == NULL)
|
||||||
return;
|
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);
|
rdomain = rtable_l2(rtable);
|
||||||
rw_enter_write(&table->inpt_notify);
|
|
||||||
mtx_enter(&table->inpt_mtx);
|
mtx_enter(&table->inpt_mtx);
|
||||||
TAILQ_FOREACH(inp, &table->inpt_queue, inp_queue) {
|
while ((inp = in_pcb_iterator(table, inp, &iter)) != NULL) {
|
||||||
if (in_pcb_is_iterator(inp))
|
|
||||||
continue;
|
|
||||||
KASSERT(!ISSET(inp->inp_flags, INP_IPV6));
|
KASSERT(!ISSET(inp->inp_flags, INP_IPV6));
|
||||||
|
|
||||||
if (inp->inp_faddr.s_addr != dst->sin_addr.s_addr ||
|
if (inp->inp_faddr.s_addr != dst->sin_addr.s_addr ||
|
||||||
rtable_l2(inp->inp_rtableid) != rdomain) {
|
rtable_l2(inp->inp_rtableid) != rdomain) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
in_pcbref(inp);
|
mtx_leave(&table->inpt_mtx);
|
||||||
SIMPLEQ_INSERT_TAIL(&inpcblist, inp, inp_notify);
|
(*notify)(inp, errno);
|
||||||
|
mtx_enter(&table->inpt_mtx);
|
||||||
}
|
}
|
||||||
mtx_leave(&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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -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 $ */
|
/* $NetBSD: in_pcb.h,v 1.14 1996/02/13 23:42:00 christos Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -79,7 +79,6 @@
|
|||||||
* I immutable after creation
|
* I immutable after creation
|
||||||
* N net lock
|
* N net lock
|
||||||
* t inpt_mtx pcb table mutex
|
* t inpt_mtx pcb table mutex
|
||||||
* y inpt_notify pcb table rwlock for notify
|
|
||||||
* L pf_inp_mtx link pf to inp mutex
|
* L pf_inp_mtx link pf to inp mutex
|
||||||
* s so_lock socket rwlock
|
* 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_hash; /* [t] local and foreign hash */
|
||||||
LIST_ENTRY(inpcb) inp_lhash; /* [t] local port hash */
|
LIST_ENTRY(inpcb) inp_lhash; /* [t] local port hash */
|
||||||
TAILQ_ENTRY(inpcb) inp_queue; /* [t] inet PCB queue */
|
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 */
|
struct inpcbtable *inp_table; /* [I] inet queue/hash table */
|
||||||
union inpaddru inp_faddru; /* [t] Foreign address. */
|
union inpaddru inp_faddru; /* [t] Foreign address. */
|
||||||
union inpaddru inp_laddru; /* [t] Local address. */
|
union inpaddru inp_laddru; /* [t] Local address. */
|
||||||
@ -194,7 +192,6 @@ in_pcb_is_iterator(struct inpcb *inp)
|
|||||||
|
|
||||||
struct inpcbtable {
|
struct inpcbtable {
|
||||||
struct mutex inpt_mtx; /* protect queue and hash */
|
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 */
|
TAILQ_HEAD(inpthead, inpcb) inpt_queue; /* [t] inet PCB queue */
|
||||||
struct inpcbhead *inpt_hashtbl; /* [t] local and foreign hash */
|
struct inpcbhead *inpt_hashtbl; /* [t] local and foreign hash */
|
||||||
struct inpcbhead *inpt_lhashtbl; /* [t] local port hash */
|
struct inpcbhead *inpt_lhashtbl; /* [t] local port hash */
|
||||||
|
@ -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.
|
* 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,
|
uint fport_arg, const struct sockaddr_in6 *src, uint lport_arg,
|
||||||
u_int rtable, int cmd, void *cmdarg, void (*notify)(struct inpcb *, int))
|
u_int rtable, int cmd, void *cmdarg, void (*notify)(struct inpcb *, int))
|
||||||
{
|
{
|
||||||
SIMPLEQ_HEAD(, inpcb) inpcblist;
|
struct inpcb_iterator iter = { .inp_table = NULL };
|
||||||
struct inpcb *inp;
|
struct inpcb *inp = NULL;
|
||||||
u_short fport = fport_arg, lport = lport_arg;
|
u_short fport = fport_arg, lport = lport_arg;
|
||||||
struct sockaddr_in6 sa6_src;
|
struct sockaddr_in6 sa6_src;
|
||||||
int errno;
|
int errno;
|
||||||
@ -474,13 +474,9 @@ in6_pcbnotify(struct inpcbtable *table, const struct sockaddr_in6 *dst,
|
|||||||
if (notify == NULL)
|
if (notify == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
SIMPLEQ_INIT(&inpcblist);
|
|
||||||
rdomain = rtable_l2(rtable);
|
rdomain = rtable_l2(rtable);
|
||||||
rw_enter_write(&table->inpt_notify);
|
|
||||||
mtx_enter(&table->inpt_mtx);
|
mtx_enter(&table->inpt_mtx);
|
||||||
TAILQ_FOREACH(inp, &table->inpt_queue, inp_queue) {
|
while ((inp = in_pcb_iterator(table, inp, &iter)) != NULL) {
|
||||||
if (in_pcb_is_iterator(inp))
|
|
||||||
continue;
|
|
||||||
KASSERT(ISSET(inp->inp_flags, INP_IPV6));
|
KASSERT(ISSET(inp->inp_flags, INP_IPV6));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -546,17 +542,11 @@ in6_pcbnotify(struct inpcbtable *table, const struct sockaddr_in6 *dst,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
do_notify:
|
do_notify:
|
||||||
in_pcbref(inp);
|
mtx_leave(&table->inpt_mtx);
|
||||||
SIMPLEQ_INSERT_TAIL(&inpcblist, inp, inp_notify);
|
(*notify)(inp, errno);
|
||||||
|
mtx_enter(&table->inpt_mtx);
|
||||||
}
|
}
|
||||||
mtx_leave(&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 *
|
struct rtentry *
|
||||||
|
Loading…
Reference in New Issue
Block a user