Attach:

  splassert: sowakeup: want 1 have 0
  Starting stack trace...
  sowakeup() at sowakeup+0x41
  sorwakeup() at sorwakeup+0xb4
  route_input() at route_input+0x2d7
  if_attach() at if_attach+0x58
  xnf_attach() at xnf_attach+0x45f
  config_attach() at config_attach+0x1bc
  xen_attach_device() at xen_attach_device+0x146
  xen_hotplug() at xen_hotplug+0x23f
  taskq_thread() at taskq_thread+0x6c
  end trace frame: 0x0, count: 248
  End of stack trace.

Detach:

  splassert: sowakeup: want 1 have 0
  Starting stack trace...
  sowakeup() at sowakeup+0x41
  sorwakeup() at sorwakeup+0xb4
  route_input() at route_input+0x2d7
  if_detach() at if_detach+0x27e
  xnf_detach() at xnf_detach+0x4d
  config_detach() at config_detach+0x13c
  xen_hotplug() at xen_hotplug+0x2e5
  taskq_thread() at taskq_thread+0x6c
  end trace frame: 0x0, count: 249
  End of stack trace.
  xnf2 detached

The taskq running xen_hotplug is KERNEL_LOCK'ed.  The diff below solves
the issue, but is it any good?

diff --git sys/net/if.c sys/net/if.c
index 1e103564710..a5c25b89560 100644
--- sys/net/if.c
+++ sys/net/if.c
@@ -525,11 +525,11 @@ if_attach(struct ifnet *ifp)
 {
        int s;
 
-       s = splsoftnet();
+       NET_LOCK(s);
        if_attach_common(ifp);
        TAILQ_INSERT_TAIL(&ifnet, ifp, if_list);
        if_attachsetup(ifp);
-       splx(s);
+       NET_UNLOCK(s);
 }
 
 void
@@ -941,6 +941,7 @@ if_detach(struct ifnet *ifp)
 
        ifq_clr_oactive(&ifp->if_snd);
 
+       rw_enter_write(&netlock);
        s = splnet();
        /* Other CPUs must not have a reference before we start destroying. */
        if_idxmap_remove(ifp);
@@ -1017,6 +1018,7 @@ if_detach(struct ifnet *ifp)
        /* Announce that the interface is gone. */
        rt_ifannouncemsg(ifp, IFAN_DEPARTURE);
        splx(s);
+       rw_exit_write(&netlock);
 
        ifq_destroy(&ifp->if_snd);
 }

Reply via email to