summaryrefslogtreecommitdiffstats
path: root/sys/net/if_ef.c
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2009-08-23 21:00:21 +0000
committerrwatson <rwatson@FreeBSD.org>2009-08-23 21:00:21 +0000
commitf0ee7a159b9f49405e827b40fed36a844334c3ac (patch)
treed0f37ae1e18cd43670edd205cd98238c11213fd2 /sys/net/if_ef.c
parentef8d755d4df716bf13f8a1833f7dd1db0b78c569 (diff)
downloadFreeBSD-src-f0ee7a159b9f49405e827b40fed36a844334c3ac.zip
FreeBSD-src-f0ee7a159b9f49405e827b40fed36a844334c3ac.tar.gz
Rather than using IFNET_RLOCK() when iterating over (and modifying) the
ifnet list during if_ef load, directly acquire the ifnet_sxlock exclusively. That way when if_alloc() recurses the lock, it's a write recursion rather than a read->write recursion. This code structure is arguably a bug, so add a comment indicating that this is the case. Post-8.0, we should fix this, but this commit resolves panic-on-load for if_ef. Discussed with: bz, julian Reported by: phk MFC after: 3 days
Diffstat (limited to 'sys/net/if_ef.c')
-rw-r--r--sys/net/if_ef.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/sys/net/if_ef.c b/sys/net/if_ef.c
index 7a5fca9..2af3a17 100644
--- a/sys/net/if_ef.c
+++ b/sys/net/if_ef.c
@@ -492,7 +492,20 @@ ef_load(void)
VNET_LIST_RLOCK();
VNET_FOREACH(vnet_iter) {
CURVNET_SET(vnet_iter);
- IFNET_RLOCK();
+
+ /*
+ * XXXRW: The following loop walks the ifnet list while
+ * modifying it, something not well-supported by ifnet
+ * locking. To avoid lock upgrade/recursion issues, manually
+ * acquire a write lock of ifnet_sxlock here, rather than a
+ * read lock, so that when if_alloc() recurses the lock, we
+ * don't panic. This structure, in which if_ef automatically
+ * attaches to all ethernet interfaces, should be replaced
+ * with a model like that found in if_vlan, in which
+ * interfaces are explicitly configured, which would avoid
+ * this (and other) problems.
+ */
+ sx_xlock(&ifnet_sxlock);
TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
if (ifp->if_type != IFT_ETHER) continue;
EFDEBUG("Found interface %s\n", ifp->if_xname);
@@ -523,7 +536,7 @@ ef_load(void)
efcount++;
SLIST_INSERT_HEAD(&efdev, efl, el_next);
}
- IFNET_RUNLOCK();
+ sx_xunlock(&ifnet_sxlock);
CURVNET_RESTORE();
}
VNET_LIST_RUNLOCK();
OpenPOWER on IntegriCloud