summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormpi <mpi@openbsd.org>2017-03-17 17:19:16 +0000
committermpi <mpi@openbsd.org>2017-03-17 17:19:16 +0000
commitb554ebfc5ef68dbcbabda317521525d69f01b5e5 (patch)
treeac930470c4b490bea0d5231c4d25bfe4bb8b51a8
parentcarp(4) code is always executed in the 'softnet' thread, so remove (diff)
downloadwireguard-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.c6
-rw-r--r--sys/kern/uipc_socket2.c8
-rw-r--r--sys/net/if.c14
-rw-r--r--sys/net/if_pflow.c8
-rw-r--r--sys/net/pf.c52
-rw-r--r--sys/net/pf_ioctl.c16
-rw-r--r--sys/net/pf_norm.c4
-rw-r--r--sys/net/pfvar.h7
-rw-r--r--sys/sys/systm.h10
-rw-r--r--sys/uvm/uvm_vnode.c14
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);
}