NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: kern/50602: removing ethernet cable panics the kernel
The following reply was made to PR kern/50602; it has been noted by GNATS.
From: Michael van Elst <mlelstv%serpens.de@localhost>
To: gnats-bugs%netbsd.org@localhost
Cc:
Subject: Re: kern/50602: removing ethernet cable panics the kernel
Date: Sun, 3 Jan 2016 15:01:54 +0100
Maybe this.
The patch
- defers link state handling to a softint
- fixes the destruction of the afdata lock
- makes the lock a _KERNEL only field to avoid
conflicts with kvm(3) users.
Index: sys/net/if.c
===================================================================
RCS file: /cvsroot/src/sys/net/if.c,v
retrieving revision 1.319
diff -p -u -r1.319 if.c
--- sys/net/if.c 20 Nov 2015 08:10:36 -0000 1.319
+++ sys/net/if.c 3 Jan 2016 13:55:38 -0000
@@ -198,6 +198,7 @@ static void if_attachdomain1(struct ifne
static int ifconf(u_long, void *);
static int if_clone_create(const char *);
static int if_clone_destroy(const char *);
+static void if_link_state_change_si(void *);
#if defined(INET) || defined(INET6)
static void sysctl_net_pktq_setup(struct sysctllog **, int);
@@ -592,6 +593,7 @@ if_initialize(ifnet_t *ifp)
ifp->if_broadcastaddr = 0; /* reliably crash if used uninitialized */
ifp->if_link_state = LINK_STATE_UNKNOWN;
+ ifp->if_old_link_state = LINK_STATE_UNKNOWN;
ifp->if_capenable = 0;
ifp->if_csum_flags_tx = 0;
@@ -617,6 +619,10 @@ if_initialize(ifnet_t *ifp)
IF_AFDATA_LOCK_INIT(ifp);
+ ifp->if_link_si = softint_establish(SOFTINT_NET, if_link_state_change_si, ifp);
+ if (ifp->if_link_si == NULL)
+ panic("%s: softint_establish() failed", __func__);
+
if_getindex(ifp);
}
@@ -895,6 +901,11 @@ again:
ifioctl_detach(ifp);
+ IF_AFDATA_LOCK_DESTROY(ifp);
+
+ softint_disestablish(ifp->if_link_si);
+ ifp->if_link_si = NULL;
+
/*
* remove packets that came from ifp, from software interrupt queues.
*/
@@ -1407,8 +1418,6 @@ void
if_link_state_change(struct ifnet *ifp, int link_state)
{
int s;
- int old_link_state;
- struct domain *dp;
s = splnet();
if (ifp->if_link_state == link_state) {
@@ -1416,8 +1425,26 @@ if_link_state_change(struct ifnet *ifp,
return;
}
- old_link_state = ifp->if_link_state;
ifp->if_link_state = link_state;
+ softint_schedule(ifp->if_link_si);
+
+ splx(s);
+}
+
+
+void
+if_link_state_change_si(void *arg)
+{
+ struct ifnet *ifp = arg;
+ int s;
+ int link_state, old_link_state;
+ struct domain *dp;
+
+ s = splnet();
+ link_state = ifp->if_link_state;
+ old_link_state = ifp->if_old_link_state;
+ ifp->if_old_link_state = ifp->if_link_state;
+
#ifdef DEBUG
log(LOG_DEBUG, "%s: link state %s (was %s)\n", ifp->if_xname,
link_state == LINK_STATE_UP ? "UP" :
Index: sys/net/if.h
===================================================================
RCS file: /cvsroot/src/sys/net/if.h,v
retrieving revision 1.193
diff -p -u -r1.193 if.h
--- sys/net/if.h 2 Oct 2015 03:08:26 -0000 1.193
+++ sys/net/if.h 3 Jan 2016 13:55:39 -0000
@@ -351,12 +351,14 @@ typedef struct ifnet {
struct ifnet_lock *if_ioctl_lock;
#ifdef _KERNEL /* XXX kvm(3) */
struct callout *if_slowtimo_ch;
-#endif
#ifdef GATEWAY
struct kmutex *if_afdata_lock;
#else
struct krwlock *if_afdata_lock;
#endif
+ void *if_link_si; /* softint to handle link state changes */
+ int if_old_link_state; /* previous link state */
+#endif
} ifnet_t;
#define if_mtu if_data.ifi_mtu
@@ -452,6 +454,8 @@ typedef struct ifnet {
(ifp)->if_afdata_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NET); \
} while (0)
+#define IF_AFDATA_LOCK_DESTROY(ifp) mutex_obj_free((ifp)->if_afdata_lock)
+
#define IF_AFDATA_WLOCK(ifp) mutex_enter((ifp)->if_afdata_lock)
#define IF_AFDATA_RLOCK(ifp) mutex_enter((ifp)->if_afdata_lock)
#define IF_AFDATA_WUNLOCK(ifp) mutex_exit((ifp)->if_afdata_lock)
@@ -459,7 +463,6 @@ typedef struct ifnet {
#define IF_AFDATA_LOCK(ifp) IF_AFDATA_WLOCK(ifp)
#define IF_AFDATA_UNLOCK(ifp) IF_AFDATA_WUNLOCK(ifp)
#define IF_AFDATA_TRYLOCK(ifp) mutex_tryenter((ifp)->if_afdata_lock)
-#define IF_AFDATA_DESTROY(ifp) mutex_destroy((ifp)->if_afdata_lock)
#define IF_AFDATA_LOCK_ASSERT(ifp) \
KASSERT(mutex_owned((ifp)->if_afdata_lock))
@@ -474,6 +477,8 @@ typedef struct ifnet {
#define IF_AFDATA_LOCK_INIT(ifp) \
do {(ifp)->if_afdata_lock = rw_obj_alloc();} while (0)
+#define IF_AFDATA_LOCK_DESTROY(ifp) rw_obj_free((ifp)->if_afdata_lock)
+
#define IF_AFDATA_WLOCK(ifp) rw_enter((ifp)->if_afdata_lock, RW_WRITER)
#define IF_AFDATA_RLOCK(ifp) rw_enter((ifp)->if_afdata_lock, RW_READER)
#define IF_AFDATA_WUNLOCK(ifp) rw_exit((ifp)->if_afdata_lock)
@@ -481,7 +486,6 @@ typedef struct ifnet {
#define IF_AFDATA_LOCK(ifp) IF_AFDATA_WLOCK(ifp)
#define IF_AFDATA_UNLOCK(ifp) IF_AFDATA_WUNLOCK(ifp)
#define IF_AFDATA_TRYLOCK(ifp) rw_tryenter((ifp)->if_afdata_lock, RW_WRITER)
-#define IF_AFDATA_DESTROY(ifp) rw_destroy((ifp)->if_afdata_lock)
#define IF_AFDATA_LOCK_ASSERT(ifp) \
KASSERT(rw_lock_held((ifp)->if_afdata_lock))
Home |
Main Index |
Thread Index |
Old Index