summaryrefslogtreecommitdiff
path: root/sys/net/if.c
diff options
context:
space:
mode:
authorBjoern A. Zeeb <bz@FreeBSD.org>2010-04-11 11:51:44 +0000
committerBjoern A. Zeeb <bz@FreeBSD.org>2010-04-11 11:51:44 +0000
commitd8c136591af009ff38f9a4620d0848b97cfa1e98 (patch)
tree733dc8c0a6a210cc18db521af3307fceaaca1da9 /sys/net/if.c
parent318c3213e58ab65f13fc32419cc2648316b100c9 (diff)
downloadsrc-test2-d8c136591af009ff38f9a4620d0848b97cfa1e98.tar.gz
src-test2-d8c136591af009ff38f9a4620d0848b97cfa1e98.zip
Notes
Diffstat (limited to 'sys/net/if.c')
-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 1cdc20bfa7b4..e4a200549636 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