Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 20 Jun 2014 17:25:51 +0200
From:      =?ISO-8859-1?Q?Roger_Pau_Monn=E9?= <roger.pau@citrix.com>
To:        <freebsd-net@freebsd.org>
Subject:   Ordering problem in if_detach_internal regarding if_bridge
Message-ID:  <53A4527F.90008@citrix.com>

next in thread | raw e-mail | index | archive | help
--------------030003030008040308010507
Content-Type: text/plain; charset="ISO-8859-1"
Content-Transfer-Encoding: 7bit

Hello,

I've stumbled across the following panic when testing Xen netback with 
if_bridge:

Kernel page fault with the following non-sleepable locks held:
exclusive sleep mutex if_bridge (if_bridge) r = 0 (0xfffff80006306c18) locked @ /usr/src/sys/m
KDB: stack backtrace:
X_db_symbol_values() at X_db_symbol_values+0x10b/frame 0xfffffe0000213490
kdb_backtrace() at kdb_backtrace+0x39/frame 0xfffffe0000213540
witness_warn() at witness_warn+0x4a8/frame 0xfffffe0000213600
trap() at trap+0xc9d/frame 0xfffffe00002136a0
trap() at trap+0x669/frame 0xfffffe00002138b0
calltrap() at calltrap+0x8/frame 0xfffffe00002138b0
--- trap 0xc, rip = 0xffffffff8221a0ef, rsp = 0xfffffe0000213970, rbp = 0xfffffe00002139e0 ---
bridge_input() at bridge_input+0x5ff/frame 0xfffffe00002139e0
ether_vlanencap() at ether_vlanencap+0x4a3/frame 0xfffffe0000213a10
netisr_dispatch_src() at netisr_dispatch_src+0x90/frame 0xfffffe0000213a80
ether_ifattach() at ether_ifattach+0x19f/frame 0xfffffe0000213ab0
ath_dfs_get_thresholds() at ath_dfs_get_thresholds+0x81ce/frame 0xfffffe0000213b30
intr_event_execute_handlers() at intr_event_execute_handlers+0x93/frame 0xfffffe0000213b70
db_dump_intr_event() at db_dump_intr_event+0x796/frame 0xfffffe0000213bb0
fork_exit() at fork_exit+0x84/frame 0xfffffe0000213bf0
fork_trampoline() at fork_trampoline+0xe/frame 0xfffffe0000213bf0
--- trap 0, rip = 0, rsp = 0xfffffe0000213cb0, rbp = 0 ---

I've tracked this down to if_detach_internal setting ifp->if_addr to 
NULL before calling EVENTHANDLER_INVOKE(ifnet_departure_event..., which 
causes a panic in GRAB_OUR_PACKETS in the if_bridge code when it tries 
to perform IF_LLADDR on an interface that's in the process of being 
destroyed (ifp->if_addr set to NULL, but the ifnet_departure_event event 
has not fired yet).

I have the following naive patch that moves the firing of the event 
before if_addr is set to NULL, but I'm not familiar with the ordering 
in if_detach_internal, so I'm not sure if this might cause problems in 
other parts of the code, could someone familiar with the net stuff 
comment on the best way to deal with it?

Thanks, Roger.

--------------030003030008040308010507
Content-Type: text/plain; charset="UTF-8"; x-mac-type=0; x-mac-creator=0;
	name="if_detach.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="if_detach.patch"

>From 35430bcf6458bb5218268fd28f59bd911ea1ce2b Mon Sep 17 00:00:00 2001
From: Roger Pau Monne <roger.pau@citrix.com>
Date: Fri, 20 Jun 2014 15:16:58 +0200
Subject: [PATCH]

---
 sys/net/if.c |    7 ++++---
 1 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/sys/net/if.c b/sys/net/if.c
index 47b5b9d..1b3227e 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -875,6 +875,10 @@ if_detach_internal(struct ifnet *ifp, int vmove)
 #endif
 	if_purgemaddrs(ifp);
 
+	/* Announce that the interface is gone. */
+	rt_ifannouncemsg(ifp, IFAN_DEPARTURE);
+	EVENTHANDLER_INVOKE(ifnet_departure_event, ifp);
+
 	if (!vmove) {
 		/*
 		 * Prevent further calls into the device driver via ifnet.
@@ -912,9 +916,6 @@ if_detach_internal(struct ifnet *ifp, int vmove)
 		}
 	}
 
-	/* Announce that the interface is gone. */
-	rt_ifannouncemsg(ifp, IFAN_DEPARTURE);
-	EVENTHANDLER_INVOKE(ifnet_departure_event, ifp);
 	if (IS_DEFAULT_VNET(curvnet))
 		devctl_notify("IFNET", ifp->if_xname, "DETACH", NULL);
 	if_delgroups(ifp);
-- 
1.7.7.5 (Apple Git-26)


--------------030003030008040308010507--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?53A4527F.90008>