diff options
author | 2017-03-17 17:19:16 +0000 | |
---|---|---|
committer | 2017-03-17 17:19:16 +0000 | |
commit | b554ebfc5ef68dbcbabda317521525d69f01b5e5 (patch) | |
tree | ac930470c4b490bea0d5231c4d25bfe4bb8b51a8 | |
parent | carp(4) code is always executed in the 'softnet' thread, so remove (diff) | |
download | wireguard-openbsd-b554ebfc5ef68dbcbabda317521525d69f01b5e5.tar.xz wireguard-openbsd-b554ebfc5ef68dbcbabda317521525d69f01b5e5.zip |
Revert the NET_LOCK() and bring back pf's contention lock for release.
For the moment the NET_LOCK() is always taken by threads running under
KERNEL_LOCK(). That means it doesn't buy us anything except a possible
deadlock that we did not spot. So make sure this doesn't happen, we'll
have plenty of time in the next release cycle to stress test it.
ok visa@
-rw-r--r-- | sys/kern/uipc_socket.c | 6 | ||||
-rw-r--r-- | sys/kern/uipc_socket2.c | 8 | ||||
-rw-r--r-- | sys/net/if.c | 14 | ||||
-rw-r--r-- | sys/net/if_pflow.c | 8 | ||||
-rw-r--r-- | sys/net/pf.c | 52 | ||||
-rw-r--r-- | sys/net/pf_ioctl.c | 16 | ||||
-rw-r--r-- | sys/net/pf_norm.c | 4 | ||||
-rw-r--r-- | sys/net/pfvar.h | 7 | ||||
-rw-r--r-- | sys/sys/systm.h | 10 | ||||
-rw-r--r-- | sys/uvm/uvm_vnode.c | 14 |
10 files changed, 62 insertions, 77 deletions
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index 1bb5874d1fa..0d427de67c9 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uipc_socket.c,v 1.180 2017/03/13 20:18:21 claudio Exp $ */ +/* $OpenBSD: uipc_socket.c,v 1.181 2017/03/17 17:19:16 mpi Exp $ */ /* $NetBSD: uipc_socket.c,v 1.21 1996/02/04 02:17:52 christos Exp $ */ /* @@ -1038,12 +1038,10 @@ sorflush(struct socket *so) { struct sockbuf *sb = &so->so_rcv; struct protosw *pr = so->so_proto; - sa_family_t af = pr->pr_domain->dom_family; struct sockbuf asb; sb->sb_flags |= SB_NOINTR; - sblock(sb, M_WAITOK, - (af != PF_LOCAL && af != PF_ROUTE) ? &netlock : NULL); + sblock(sb, M_WAITOK, NULL); socantrcvmore(so); sbunlock(sb); asb = *sb; diff --git a/sys/kern/uipc_socket2.c b/sys/kern/uipc_socket2.c index 2da9a6a61d6..ab72035f63c 100644 --- a/sys/kern/uipc_socket2.c +++ b/sys/kern/uipc_socket2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uipc_socket2.c,v 1.74 2017/03/13 20:18:21 claudio Exp $ */ +/* $OpenBSD: uipc_socket2.c,v 1.75 2017/03/17 17:19:16 mpi Exp $ */ /* $NetBSD: uipc_socket2.c,v 1.11 1996/02/04 02:17:55 christos Exp $ */ /* @@ -299,11 +299,7 @@ soassertlocked(struct socket *so) int sosleep(struct socket *so, void *ident, int prio, const char *wmesg, int timo) { - if ((so->so_proto->pr_domain->dom_family != PF_LOCAL) && - (so->so_proto->pr_domain->dom_family != PF_ROUTE)) { - return rwsleep(ident, &netlock, prio, wmesg, timo); - } else - return tsleep(ident, prio, wmesg, timo); + return tsleep(ident, prio, wmesg, timo); } /* diff --git a/sys/net/if.c b/sys/net/if.c index c690c9281a9..c34b5b067f8 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if.c,v 1.490 2017/03/08 09:19:45 mpi Exp $ */ +/* $OpenBSD: if.c,v 1.491 2017/03/17 17:19:16 mpi Exp $ */ /* $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $ */ /* @@ -230,12 +230,6 @@ struct taskq *softnettq; struct task if_input_task_locked = TASK_INITIALIZER(if_netisr, NULL); /* - * Serialize socket operations to ensure no new sleeping points - * are introduced in IP output paths. - */ -struct rwlock netlock = RWLOCK_INITIALIZER("netlock"); - -/* * Network interface utility routines. */ void @@ -1152,10 +1146,7 @@ if_clone_create(const char *name, int rdomain) if (ifunit(name) != NULL) return (EEXIST); - /* XXXSMP breaks atomicity */ - rw_exit_write(&netlock); ret = (*ifc->ifc_create)(ifc, unit); - rw_enter_write(&netlock); if (ret != 0 || (ifp = ifunit(name)) == NULL) return (ret); @@ -1197,10 +1188,7 @@ if_clone_destroy(const char *name) splx(s); } - /* XXXSMP breaks atomicity */ - rw_exit_write(&netlock); ret = (*ifc->ifc_destroy)(ifp); - rw_enter_write(&netlock); return (ret); } diff --git a/sys/net/if_pflow.c b/sys/net/if_pflow.c index 0ef0381c3d3..5dcdea31017 100644 --- a/sys/net/if_pflow.c +++ b/sys/net/if_pflow.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_pflow.c,v 1.74 2017/02/16 10:15:12 mpi Exp $ */ +/* $OpenBSD: if_pflow.c,v 1.75 2017/03/17 17:19:16 mpi Exp $ */ /* * Copyright (c) 2011 Florian Obser <florian@narrans.de> @@ -463,12 +463,9 @@ pflowioctl(struct ifnet *ifp, u_long cmd, caddr_t data) sc->sc_gcounter=pflowstats.pflow_flows; /* send templates on startup */ if (sc->sc_version == PFLOW_PROTO_10) { - /* XXXSMP breaks atomicity */ - rw_exit_write(&netlock); s = splnet(); pflow_sendout_ipfix_tmpl(sc); splx(s); - rw_enter_write(&netlock); } } else ifp->if_flags &= ~IFF_RUNNING; @@ -508,8 +505,6 @@ pflowioctl(struct ifnet *ifp, u_long cmd, caddr_t data) sizeof(pflowr)))) return (error); - /* XXXSMP breaks atomicity */ - rw_exit_write(&netlock); s = splnet(); error = pflow_set(sc, &pflowr); splx(s); @@ -527,7 +522,6 @@ pflowioctl(struct ifnet *ifp, u_long cmd, caddr_t data) } else ifp->if_flags &= ~IFF_RUNNING; - rw_enter_write(&netlock); break; default: diff --git a/sys/net/pf.c b/sys/net/pf.c index 3ddcd7726d2..39f005b066b 100644 --- a/sys/net/pf.c +++ b/sys/net/pf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf.c,v 1.1018 2017/03/09 05:47:28 claudio Exp $ */ +/* $OpenBSD: pf.c,v 1.1019 2017/03/17 17:19:16 mpi Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -1154,20 +1154,26 @@ pf_state_export(struct pfsync_state *sp, struct pf_state *st) /* END state table stuff */ void -pf_purge_expired_rules(void) +pf_purge_expired_rules(int locked) { struct pf_rule *r; - NET_ASSERT_LOCKED(); - if (SLIST_EMPTY(&pf_rule_gcl)) return; + if (!locked) + rw_enter_write(&pf_consistency_lock); + else + rw_assert_wrlock(&pf_consistency_lock); + while ((r = SLIST_FIRST(&pf_rule_gcl)) != NULL) { SLIST_REMOVE(&pf_rule_gcl, r, pf_rule, gcle); KASSERT(r->rule_flag & PFRULE_EXPIRED); pf_purge_rule(r); } + + if (!locked) + rw_exit_write(&pf_consistency_lock); } void @@ -1188,7 +1194,7 @@ pf_purge_thread(void *v) if (++nloops >= pf_default_rule.timeout[PFTM_INTERVAL]) { pf_purge_expired_fragments(); pf_purge_expired_src_nodes(0); - pf_purge_expired_rules(); + pf_purge_expired_rules(0); nloops = 0; } @@ -1235,20 +1241,26 @@ pf_state_expires(const struct pf_state *state) } void -pf_purge_expired_src_nodes(void) +pf_purge_expired_src_nodes(int waslocked) { struct pf_src_node *cur, *next; - - NET_ASSERT_LOCKED(); + int locked = waslocked; for (cur = RB_MIN(pf_src_tree, &tree_src_tracking); cur; cur = next) { next = RB_NEXT(pf_src_tree, &tree_src_tracking, cur); if (cur->states == 0 && cur->expire <= time_uptime) { - next = RB_NEXT(pf_src_tree, &tree_src_tracking, cur); - pf_remove_src_node(cur); + if (! locked) { + rw_enter_write(&pf_consistency_lock); + next = RB_NEXT(pf_src_tree, + &tree_src_tracking, cur); + locked = 1; + } } } + + if (locked && !waslocked) + rw_exit_write(&pf_consistency_lock); } void @@ -1293,10 +1305,7 @@ pf_remove_state(struct pf_state *cur) RB_REMOVE(pf_state_tree_id, &tree_id, cur); #if NPFLOW > 0 if (cur->state_flags & PFSTATE_PFLOW) { - /* XXXSMP breaks atomicity */ - rw_exit_write(&netlock); export_pflow(cur); - rw_enter_write(&netlock); } #endif /* NPFLOW > 0 */ #if NPFSYNC > 0 @@ -1321,12 +1330,13 @@ pf_remove_divert_state(struct pf_state_key *sk) } } +/* callers should hold the write_lock on pf_consistency_lock */ void pf_free_state(struct pf_state *cur) { struct pf_rule_item *ri; - NET_ASSERT_LOCKED(); + splsoftassert(IPL_SOFTNET); #if NPFSYNC > 0 if (pfsync_state_in_use(cur)) @@ -1361,8 +1371,7 @@ pf_purge_expired_states(u_int32_t maxcheck) { static struct pf_state *cur = NULL; struct pf_state *next; - - NET_ASSERT_LOCKED(); + int locked = 0; while (maxcheck--) { /* wrap to start of list when we hit the end */ @@ -1377,14 +1386,25 @@ pf_purge_expired_states(u_int32_t maxcheck) if (cur->timeout == PFTM_UNLINKED) { /* free removed state */ + if (! locked) { + rw_enter_write(&pf_consistency_lock); + locked = 1; + } pf_free_state(cur); } else if (pf_state_expires(cur) <= time_uptime) { /* remove and free expired state */ pf_remove_state(cur); + if (! locked) { + rw_enter_write(&pf_consistency_lock); + locked = 1; + } pf_free_state(cur); } cur = next; } + + if (locked) + rw_exit_write(&pf_consistency_lock); } int diff --git a/sys/net/pf_ioctl.c b/sys/net/pf_ioctl.c index 56a43a55ab8..887a36481d6 100644 --- a/sys/net/pf_ioctl.c +++ b/sys/net/pf_ioctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf_ioctl.c,v 1.307 2017/01/30 17:41:34 benno Exp $ */ +/* $OpenBSD: pf_ioctl.c,v 1.308 2017/03/17 17:19:16 mpi Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -111,6 +111,7 @@ void pf_qid2qname(u_int16_t, char *); void pf_qid_unref(u_int16_t); struct pf_rule pf_default_rule, pf_default_rule_new; +struct rwlock pf_consistency_lock = RWLOCK_INITIALIZER("pfcnslk"); struct { char statusif[IFNAMSIZ]; @@ -986,7 +987,12 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) return (EACCES); } - NET_LOCK(s); + if (flags & FWRITE) + rw_enter_write(&pf_consistency_lock); + else + rw_enter_read(&pf_consistency_lock); + + s = splsoftnet(); switch (cmd) { case DIOCSTART: @@ -2382,7 +2388,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) break; } fail: - NET_UNLOCK(s); + splx(s); + if (flags & FWRITE) + rw_exit_write(&pf_consistency_lock); + else + rw_exit_read(&pf_consistency_lock); return (error); } diff --git a/sys/net/pf_norm.c b/sys/net/pf_norm.c index ae60ffa2317..ce020ef96fd 100644 --- a/sys/net/pf_norm.c +++ b/sys/net/pf_norm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf_norm.c,v 1.201 2017/01/30 17:41:34 benno Exp $ */ +/* $OpenBSD: pf_norm.c,v 1.202 2017/03/17 17:19:16 mpi Exp $ */ /* * Copyright 2001 Niels Provos <provos@citi.umich.edu> @@ -176,8 +176,6 @@ pf_purge_expired_fragments(void) struct pf_fragment *frag; int32_t expire; - NET_ASSERT_LOCKED(); - expire = time_uptime - pf_default_rule.timeout[PFTM_FRAG]; while ((frag = TAILQ_LAST(&pf_fragqueue, pf_fragqueue)) != NULL) { if (frag->fr_timeout > expire) diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h index 00e9b790a91..7bf8375b450 100644 --- a/sys/net/pfvar.h +++ b/sys/net/pfvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pfvar.h,v 1.449 2017/02/22 16:12:12 mpi Exp $ */ +/* $OpenBSD: pfvar.h,v 1.450 2017/03/17 17:19:17 mpi Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -1614,9 +1614,9 @@ extern void pf_tbladdr_remove(struct pf_addr_wrap *); extern void pf_tbladdr_copyout(struct pf_addr_wrap *); extern void pf_calc_skip_steps(struct pf_rulequeue *); extern void pf_purge_thread(void *); -extern void pf_purge_expired_src_nodes(); +extern void pf_purge_expired_src_nodes(int); extern void pf_purge_expired_states(u_int32_t); -extern void pf_purge_expired_rules(); +extern void pf_purge_expired_rules(int); extern void pf_remove_state(struct pf_state *); extern void pf_remove_divert_state(struct pf_state_key *); extern void pf_free_state(struct pf_state *); @@ -1790,6 +1790,7 @@ int pf_addr_compare(struct pf_addr *, struct pf_addr *, extern struct pf_status pf_status; extern struct pool pf_frent_pl, pf_frag_pl; +extern struct rwlock pf_consistency_lock; struct pf_pool_limit { void *pp; diff --git a/sys/sys/systm.h b/sys/sys/systm.h index e93668641aa..f382c37d72e 100644 --- a/sys/sys/systm.h +++ b/sys/sys/systm.h @@ -1,4 +1,4 @@ -/* $OpenBSD: systm.h,v 1.124 2017/02/14 09:46:21 mpi Exp $ */ +/* $OpenBSD: systm.h,v 1.125 2017/03/17 17:19:16 mpi Exp $ */ /* $NetBSD: systm.h,v 1.50 1996/06/09 04:55:09 briggs Exp $ */ /*- @@ -293,31 +293,23 @@ int uiomove(void *, size_t, struct uio *); #include <sys/rwlock.h> -extern struct rwlock netlock; - #define NET_LOCK(s) \ do { \ - rw_enter_write(&netlock); \ s = splsoftnet(); \ } while (0) #define NET_UNLOCK(s) \ do { \ splx(s); \ - rw_exit_write(&netlock); \ } while (0) #define NET_ASSERT_LOCKED() \ do { \ - if (rw_status(&netlock) != RW_WRITE) \ - splassert_fail(RW_WRITE, rw_status(&netlock), __func__);\ splsoftassert(IPL_SOFTNET); \ } while (0) #define NET_ASSERT_UNLOCKED() \ do { \ - if (rw_status(&netlock) == RW_WRITE) \ - splassert_fail(0, rw_status(&netlock), __func__); \ } while (0) __returns_twice int setjmp(label_t *); diff --git a/sys/uvm/uvm_vnode.c b/sys/uvm/uvm_vnode.c index e6725d6fc32..bf5664815a5 100644 --- a/sys/uvm/uvm_vnode.c +++ b/sys/uvm/uvm_vnode.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uvm_vnode.c,v 1.94 2017/01/25 06:15:51 mpi Exp $ */ +/* $OpenBSD: uvm_vnode.c,v 1.95 2017/03/17 17:19:16 mpi Exp $ */ /* $NetBSD: uvm_vnode.c,v 1.36 2000/11/24 20:34:01 chs Exp $ */ /* @@ -1176,15 +1176,6 @@ uvn_io(struct uvm_vnode *uvn, vm_page_t *pps, int npages, int flags, int rw) result = vn_lock(vn, LK_EXCLUSIVE | LK_RECURSEFAIL, curproc); if (result == 0) { - int netlocked = (rw_status(&netlock) == RW_WRITE); - - /* - * This process may already have the NET_LOCK(), if we - * faulted in copyin() or copyout() in the network stack. - */ - if (netlocked) - rw_exit_write(&netlock); - /* NOTE: vnode now locked! */ if (rw == UIO_READ) result = VOP_READ(vn, &uio, 0, curproc->p_ucred); @@ -1193,9 +1184,6 @@ uvn_io(struct uvm_vnode *uvn, vm_page_t *pps, int npages, int flags, int rw) (flags & PGO_PDFREECLUST) ? IO_NOCACHE : 0, curproc->p_ucred); - if (netlocked) - rw_enter_write(&netlock); - if ((uvn->u_flags & UVM_VNODE_VNISLOCKED) == 0) VOP_UNLOCK(vn, curproc); } |