Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys Perform link state change processing on a work queue, ra...
details: https://anonhg.NetBSD.org/src/rev/c76698fb37c0
branches: trunk
changeset: 744578:c76698fb37c0
user: thorpej <thorpej%NetBSD.org@localhost>
date: Thu Feb 06 23:30:19 2020 +0000
description:
Perform link state change processing on a work queue, rather than in a
softint.
diffstat:
sys/net/if.c | 69 +++++++++++++++++++++++++++++---------------------
sys/net/if.h | 10 +++++--
sys/netinet/ip_carp.c | 12 ++------
3 files changed, 50 insertions(+), 41 deletions(-)
diffs (266 lines):
diff -r 45d2c8faa911 -r c76698fb37c0 sys/net/if.c
--- a/sys/net/if.c Thu Feb 06 22:52:25 2020 +0000
+++ b/sys/net/if.c Thu Feb 06 23:30:19 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if.c,v 1.470 2020/02/01 12:54:50 riastradh Exp $ */
+/* $NetBSD: if.c,v 1.471 2020/02/06 23:30:19 thorpej Exp $ */
/*-
* Copyright (c) 1999, 2000, 2001, 2008 The NetBSD Foundation, Inc.
@@ -90,7 +90,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.470 2020/02/01 12:54:50 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.471 2020/02/06 23:30:19 thorpej Exp $");
#if defined(_KERNEL_OPT)
#include "opt_inet.h"
@@ -180,6 +180,7 @@
kmutex_t ifnet_mtx __cacheline_aligned;
static struct psref_class *ifnet_psref_class __read_mostly;
static pserialize_t ifnet_psz;
+static struct workqueue *ifnet_link_state_wq __read_mostly;
static kmutex_t if_clone_mtx;
@@ -211,7 +212,7 @@
static int if_transmit(struct ifnet *, struct mbuf *);
static int if_clone_create(const char *);
static int if_clone_destroy(const char *);
-static void if_link_state_change_si(void *);
+static void if_link_state_change_work(struct work *, void *);
static void if_up_locked(struct ifnet *);
static void _if_down(struct ifnet *);
static void if_down_deactivated(struct ifnet *);
@@ -298,6 +299,7 @@
void
ifinit1(void)
{
+ int error __diagused;
#ifdef NET_MPSAFE
printf("NET_MPSAFE enabled\n");
@@ -310,6 +312,10 @@
ifnet_psz = pserialize_create();
ifnet_psref_class = psref_class_create("ifnet", IPL_SOFTNET);
ifa_psref_class = psref_class_create("ifa", IPL_SOFTNET);
+ error = workqueue_create(&ifnet_link_state_wq, "iflnkst",
+ if_link_state_change_work, NULL, PRI_SOFTNET, IPL_SOFTNET,
+ WQ_MPSAFE);
+ KASSERT(error == 0);
PSLIST_INIT(&ifnet_pslist);
if_indexlim = 8;
@@ -717,17 +723,6 @@
IF_AFDATA_LOCK_INIT(ifp);
- if (if_is_link_state_changeable(ifp)) {
- u_int flags = SOFTINT_NET;
- flags |= if_is_mpsafe(ifp) ? SOFTINT_MPSAFE : 0;
- ifp->if_link_si = softint_establish(flags,
- if_link_state_change_si, ifp);
- if (ifp->if_link_si == NULL) {
- rv = ENOMEM;
- goto fail;
- }
- }
-
PSLIST_ENTRY_INIT(ifp, if_pslist_entry);
PSLIST_INIT(&ifp->if_addr_pslist);
psref_target_init(&ifp->if_psref, ifnet_psref_class);
@@ -1484,11 +1479,6 @@
IF_AFDATA_LOCK_DESTROY(ifp);
- if (if_is_link_state_changeable(ifp)) {
- softint_disestablish(ifp->if_link_si);
- ifp->if_link_si = NULL;
- }
-
/*
* remove packets that came from ifp, from software interrupt queues.
*/
@@ -2252,7 +2242,7 @@
* - if IFEF_MPSAFE is enabled, if_snd isn't used and lock contentions on
* ifq_lock don't happen
* - if IFEF_MPSAFE is disabled, there is no lock contention on ifq_lock
- * because if_snd, if_link_state_change and if_link_state_change_softint
+ * because if_snd, if_link_state_change and if_link_state_change_process
* are all called with KERNEL_LOCK
*/
#define IF_LINK_STATE_CHANGE_LOCK(ifp) \
@@ -2260,6 +2250,16 @@
#define IF_LINK_STATE_CHANGE_UNLOCK(ifp) \
mutex_exit((ifp)->if_snd.ifq_lock)
+static void
+if_link_state_change_work_schedule(struct ifnet *ifp)
+{
+ if (ifp->if_link_cansched && !ifp->if_link_scheduled) {
+ ifp->if_link_scheduled = true;
+ workqueue_enqueue(ifnet_link_state_wq, &ifp->if_link_work,
+ NULL);
+ }
+}
+
/*
* Handle a change in the interface link state and
* queue notifications.
@@ -2328,7 +2328,7 @@
} else
LQ_STORE(ifp->if_link_queue, idx, (uint8_t)link_state);
- softint_schedule(ifp->if_link_si);
+ if_link_state_change_work_schedule(ifp);
out:
IF_LINK_STATE_CHANGE_UNLOCK(ifp);
@@ -2337,8 +2337,8 @@
/*
* Handle interface link state change notifications.
*/
-void
-if_link_state_change_softint(struct ifnet *ifp, int link_state)
+static void
+if_link_state_change_process(struct ifnet *ifp, int link_state)
{
struct domain *dp;
int s = splnet();
@@ -2409,32 +2409,34 @@
* Process the interface link state change queue.
*/
static void
-if_link_state_change_si(void *arg)
+if_link_state_change_work(struct work *work, void *arg)
{
- struct ifnet *ifp = arg;
+ struct ifnet *ifp = container_of(work, struct ifnet, if_link_work);
int s;
uint8_t state;
bool schedule;
- SOFTNET_KERNEL_LOCK_UNLESS_NET_MPSAFE();
+ KERNEL_LOCK_UNLESS_NET_MPSAFE();
s = splnet();
/* Pop a link state change from the queue and process it. */
IF_LINK_STATE_CHANGE_LOCK(ifp);
+ ifp->if_link_scheduled = false;
LQ_POP(ifp->if_link_queue, state);
IF_LINK_STATE_CHANGE_UNLOCK(ifp);
- if_link_state_change_softint(ifp, state);
+ if_link_state_change_process(ifp, state);
/* If there is a link state change to come, schedule it. */
IF_LINK_STATE_CHANGE_LOCK(ifp);
schedule = (LQ_ITEM(ifp->if_link_queue, 0) != LINK_STATE_UNSET);
IF_LINK_STATE_CHANGE_UNLOCK(ifp);
+
if (schedule)
- softint_schedule(ifp->if_link_si);
+ if_link_state_change_work_schedule(ifp);
splx(s);
- SOFTNET_KERNEL_UNLOCK_UNLESS_NET_MPSAFE();
+ KERNEL_UNLOCK_UNLESS_NET_MPSAFE();
}
/*
@@ -2517,6 +2519,11 @@
pserialize_read_exit(s);
curlwp_bindx(bound);
+ IF_LINK_STATE_CHANGE_LOCK(ifp);
+ ifp->if_link_cansched = false;
+ workqueue_wait(ifnet_link_state_wq, &ifp->if_link_work);
+ IF_LINK_STATE_CHANGE_UNLOCK(ifp);
+
IFQ_PURGE(&ifp->if_snd);
#if NCARP > 0
if (ifp->if_carp)
@@ -2589,6 +2596,10 @@
if (dp->dom_if_up)
dp->dom_if_up(ifp);
}
+
+ IF_LINK_STATE_CHANGE_LOCK(ifp);
+ ifp->if_link_cansched = true;
+ IF_LINK_STATE_CHANGE_UNLOCK(ifp);
}
/*
diff -r 45d2c8faa911 -r c76698fb37c0 sys/net/if.h
--- a/sys/net/if.h Thu Feb 06 22:52:25 2020 +0000
+++ b/sys/net/if.h Thu Feb 06 23:30:19 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if.h,v 1.280 2020/02/01 21:59:39 thorpej Exp $ */
+/* $NetBSD: if.h,v 1.281 2020/02/06 23:30:19 thorpej Exp $ */
/*-
* Copyright (c) 1999, 2000, 2001 The NetBSD Foundation, Inc.
@@ -229,6 +229,7 @@
#include <sys/percpu.h>
#include <sys/callout.h>
#include <sys/rwlock.h>
+#include <sys/workqueue.h>
#endif /* _KERNEL */
@@ -402,8 +403,12 @@
struct krwlock *if_afdata_lock;/* :: */
struct if_percpuq
*if_percpuq; /* :: we should remove it in the future */
- void *if_link_si; /* :: softint to handle link state changes */
+ struct work if_link_work; /* q: linkage on link state work queue */
uint16_t if_link_queue; /* q: masked link state change queue */
+ /* q: is link state work scheduled? */
+ bool if_link_scheduled;
+ /* q: can link state work be scheduled? */
+ bool if_link_cansched;
struct pslist_entry
if_pslist_entry;/* i: */
struct psref_target
@@ -1125,7 +1130,6 @@
void if_down(struct ifnet *);
void if_down_locked(struct ifnet *);
void if_link_state_change(struct ifnet *, int);
-void if_link_state_change_softint(struct ifnet *, int);
void if_up(struct ifnet *);
void ifinit(void);
void ifinit1(void);
diff -r 45d2c8faa911 -r c76698fb37c0 sys/netinet/ip_carp.c
--- a/sys/netinet/ip_carp.c Thu Feb 06 22:52:25 2020 +0000
+++ b/sys/netinet/ip_carp.c Thu Feb 06 23:30:19 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ip_carp.c,v 1.109 2020/02/04 05:46:32 thorpej Exp $ */
+/* $NetBSD: ip_carp.c,v 1.110 2020/02/06 23:30:20 thorpej Exp $ */
/* $OpenBSD: ip_carp.c,v 1.113 2005/11/04 08:11:54 mcbride Exp $ */
/*
@@ -33,7 +33,7 @@
#endif
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip_carp.c,v 1.109 2020/02/04 05:46:32 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip_carp.c,v 1.110 2020/02/06 23:30:20 thorpej Exp $");
/*
* TODO:
@@ -2265,13 +2265,7 @@
? LINK_STATE_DOWN : LINK_STATE_UNKNOWN;
break;
}
- /*
- * The lock is needed to serialize a call of
- * if_link_state_change_softint from here and a call from softint.
- */
- KERNEL_LOCK(1, NULL);
- if_link_state_change_softint(&sc->sc_if, link_state);
- KERNEL_UNLOCK_ONE(NULL);
+ if_link_state_change(&sc->sc_if, link_state);
}
void
Home |
Main Index |
Thread Index |
Old Index