On 20/12/16(Tue) 16:33, Mike Belopuhov wrote:
> 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);

You'll need to release the lock before calling ifc->ifc_create in
if_clone_create() and do the same dance in if_clone_destroy().

But I think that's the way to go.  If you can create/destroy
pseudo-interface without panicing we're good.

>  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);
>  }

Please keep the NET_LOCK/UNLOCK() macro.  The places where we
grab/release the `netlock' directly are places that need attention.

Reply via email to