Merge r196482 from head to stable/8:

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

Approved by:	re (kib)
This commit is contained in:
rwatson 2009-08-28 20:07:38 +00:00
parent 464ba339f0
commit 43dd289fd1

View File

@ -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();