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. > > 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. */