On 20/12/16(Tue) 18:47, Mike Belopuhov wrote: > On Tue, Dec 20, 2016 at 17:06 +0100, Martin Pieuchot wrote: > > > > 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(). > > > > Indeed. > > > But I think that's the way to go. If you can create/destroy > > pseudo-interface without panicing we're good. > > > > Seems to work here, but it feels wrong.
I don't think we can do much better, let's go with that we'll refine later. ok mpi@ > > > > 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. > > Done. > > diff --git sys/net/if.c sys/net/if.c > index 1e103564710..bd8b9267d5f 100644 > --- sys/net/if.c > +++ sys/net/if.c > @@ -523,15 +523,15 @@ if_attachhead(struct ifnet *ifp) > void > 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 > if_attach_common(struct ifnet *ifp) > { > @@ -939,10 +939,11 @@ if_detach(struct ifnet *ifp) > /* Undo pseudo-driver changes. */ > if_deactivate(ifp); > > ifq_clr_oactive(&ifp->if_snd); > > + NET_LOCK(s); > s = splnet(); > /* Other CPUs must not have a reference before we start destroying. */ > if_idxmap_remove(ifp); > > ifp->if_start = if_detached_start; > @@ -1015,10 +1016,11 @@ if_detach(struct ifnet *ifp) > } > > /* Announce that the interface is gone. */ > rt_ifannouncemsg(ifp, IFAN_DEPARTURE); > splx(s); > + NET_UNLOCK(s); > > ifq_destroy(&ifp->if_snd); > } > > /* > @@ -1068,11 +1070,14 @@ if_clone_create(const char *name, int rdomain) > return (EINVAL); > > if (ifunit(name) != NULL) > return (EEXIST); > > + /* XXXSMP breaks atomicity */ > + rw_exit_write(&netlock); > ret = (*ifc->ifc_create)(ifc, unit); > + rw_enter_write(&netlock); > > if (ret != 0 || (ifp = ifunit(name)) == NULL) > return (ret); > > if_addgroup(ifp, ifc->ifc_name); > @@ -1088,10 +1093,11 @@ if_clone_create(const char *name, int rdomain) > int > if_clone_destroy(const char *name) > { > struct if_clone *ifc; > struct ifnet *ifp; > + int ret; > > splsoftassert(IPL_SOFTNET); > > ifc = if_clone_lookup(name, NULL); > if (ifc == NULL) > @@ -1109,11 +1115,16 @@ if_clone_destroy(const char *name) > s = splnet(); > if_down(ifp); > splx(s); > } > > - return ((*ifc->ifc_destroy)(ifp)); > + /* XXXSMP breaks atomicity */ > + rw_exit_write(&netlock); > + ret = (*ifc->ifc_destroy)(ifp); > + rw_enter_write(&netlock); > + > + return (ret); > } > > /* > * Look up a network interface cloner. > */