summaryrefslogtreecommitdiffstats
path: root/sys/net
diff options
context:
space:
mode:
authorbz <bz@FreeBSD.org>2010-04-11 11:51:44 +0000
committerbz <bz@FreeBSD.org>2010-04-11 11:51:44 +0000
commitd5b3b3f9d9f415d433fc76253779bd585b99c59f (patch)
tree733dc8c0a6a210cc18db521af3307fceaaca1da9 /sys/net
parent674a87c918aac879260de667e43372e3fe9b355b (diff)
downloadFreeBSD-src-d5b3b3f9d9f415d433fc76253779bd585b99c59f.zip
FreeBSD-src-d5b3b3f9d9f415d433fc76253779bd585b99c59f.tar.gz
In if_detach_internal() we cannot hold the af_data lock over the
dom_ifdetach() calls as they might sleep for callout_drain(). Do as we do in if_attachdomain1() [r121470] and handle if_afdata_initialized earlier and call dom_ifdetach() unlocked. Discussed with: rwatson MFC after: 10 days
Diffstat (limited to 'sys/net')
-rw-r--r--sys/net/if.c12
1 files changed, 9 insertions, 3 deletions
diff --git a/sys/net/if.c b/sys/net/if.c
index 1cdc20b..e4a2005 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -897,14 +897,20 @@ if_detach_internal(struct ifnet *ifp, int vmove)
devctl_notify("IFNET", ifp->if_xname, "DETACH", NULL);
if_delgroups(ifp);
+ /*
+ * We cannot hold the lock over dom_ifdetach calls as they might
+ * sleep, for example trying to drain a callout, thus open up the
+ * theoretical race with re-attaching.
+ */
IF_AFDATA_LOCK(ifp);
- for (dp = domains; ifp->if_afdata_initialized > 0 && dp; dp = dp->dom_next) {
+ i = ifp->if_afdata_initialized;
+ ifp->if_afdata_initialized = 0;
+ IF_AFDATA_UNLOCK(ifp);
+ for (dp = domains; i > 0 && dp; dp = dp->dom_next) {
if (dp->dom_ifdetach && ifp->if_afdata[dp->dom_family])
(*dp->dom_ifdetach)(ifp,
ifp->if_afdata[dp->dom_family]);
}
- ifp->if_afdata_initialized = 0;
- IF_AFDATA_UNLOCK(ifp);
}
#ifdef VIMAGE
OpenPOWER on IntegriCloud