diff options
author | rwatson <rwatson@FreeBSD.org> | 2009-08-23 21:00:21 +0000 |
---|---|---|
committer | rwatson <rwatson@FreeBSD.org> | 2009-08-23 21:00:21 +0000 |
commit | f0ee7a159b9f49405e827b40fed36a844334c3ac (patch) | |
tree | d0f37ae1e18cd43670edd205cd98238c11213fd2 /sys/net/if_ef.c | |
parent | ef8d755d4df716bf13f8a1833f7dd1db0b78c569 (diff) | |
download | FreeBSD-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.c | 17 |
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(); |