Author: rwatson
Date: Sun Aug 23 21:00:21 2009
New Revision: 196482
URL: http://svn.freebsd.org/changeset/base/196482

Log:
  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

Modified:
  head/sys/net/if_ef.c

Modified: head/sys/net/if_ef.c
==============================================================================
--- head/sys/net/if_ef.c        Sun Aug 23 20:40:19 2009        (r196481)
+++ head/sys/net/if_ef.c        Sun Aug 23 21:00:21 2009        (r196482)
@@ -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();
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to