Date: Sun, 24 Apr 2016 16:36:33 +0000 (UTC) From: "Bjoern A. Zeeb" <bz@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r298547 - projects/vnet/sys/net Message-ID: <201604241636.u3OGaX8w077511@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: bz Date: Sun Apr 24 16:36:33 2016 New Revision: 298547 URL: https://svnweb.freebsd.org/changeset/base/298547 Log: Remove the "shutdown" argument again to if_detach_internal(). Using the sysuninit state we do not need this anymore and this simplifies the logic. Make sure we always call the dom_ifdetach handler, aas this is the only place this can happen. Sponsored by: The FreeBSD Foundation Modified: projects/vnet/sys/net/if.c Modified: projects/vnet/sys/net/if.c ============================================================================== --- projects/vnet/sys/net/if.c Sun Apr 24 16:33:25 2016 (r298546) +++ projects/vnet/sys/net/if.c Sun Apr 24 16:36:33 2016 (r298547) @@ -174,9 +174,9 @@ static int if_getgroup(struct ifgroupreq static int if_getgroupmembers(struct ifgroupreq *); static void if_delgroups(struct ifnet *); static void if_attach_internal(struct ifnet *, int, struct if_clone *); -static int if_detach_internal(struct ifnet *, int, int, struct if_clone **); +static int if_detach_internal(struct ifnet *, int, struct if_clone **); #ifdef VIMAGE -static void if_vmove(struct ifnet *, struct vnet *, int); +static void if_vmove(struct ifnet *, struct vnet *); #endif #ifdef INET6 @@ -397,7 +397,7 @@ vnet_if_return(const void *unused __unus /* Return all inherited interfaces to their parent vnets. */ TAILQ_FOREACH_SAFE(ifp, &V_ifnet, if_link, nifp) { if (ifp->if_home_vnet != ifp->if_vnet) - if_vmove(ifp, ifp->if_home_vnet, 1); + if_vmove(ifp, ifp->if_home_vnet); } } VNET_SYSUNINIT(vnet_if_return, SI_SUB_INIT_IF, SI_ORDER_ANY, @@ -904,7 +904,7 @@ if_detach(struct ifnet *ifp) { CURVNET_SET_QUIET(ifp->if_vnet); - if_detach_internal(ifp, 0, 0, NULL); + if_detach_internal(ifp, 0, NULL); CURVNET_RESTORE(); } @@ -919,15 +919,16 @@ if_detach(struct ifnet *ifp) * the cloned interfaces are destoyed as first thing of teardown. */ static int -if_detach_internal(struct ifnet *ifp, int vmove, int shutdown, - struct if_clone **ifcp) +if_detach_internal(struct ifnet *ifp, int vmove, struct if_clone **ifcp) { struct ifaddr *ifa; int i; struct domain *dp; struct ifnet *iter; - int found = 0; + int found = 0, shutdown; + shutdown = (ifp->if_vnet->vnet_state > SI_SUB_VNET && + ifp->if_vnet->vnet_state < SI_SUB_VNET_DONE) ? 1 : 0; IFNET_WLOCK(); TAILQ_FOREACH(iter, &V_ifnet, if_link) if (iter == ifp) { @@ -956,23 +957,51 @@ if_detach_internal(struct ifnet *ifp, in #endif } - /* The one thing we have to do. */ - if_delgroups(ifp); + /* + * At this point we know the interface still was on the ifnet list + * and we removed it so we are in a stable state. + */ /* - * Remove/wait for pending events. + * In any case (destroy or vmove) detach us from the groups + * and remove/wait for pending events on the taskq. + * XXX-BZ in theory an interface could still enqueue a taskq change? */ - taskqueue_drain(taskqueue_swi, &ifp->if_linktask); + if_delgroups(ifp); - if (!vmove && !shutdown && - ifp->if_vnet->vnet_state <= SI_SUB_PSEUDO_DONE) - return (ENOENT); + taskqueue_drain(taskqueue_swi, &ifp->if_linktask); - /* Check if this is a cloned interface or not. */ + /* + * Check if this is a cloned interface or not. Must do even if + * shutting down as a if_vmove_reclaim() would move the ifp and + * the if_clone_addgroup() will have a corrupted string overwise + * from a gibberish pointer. + */ if (vmove && ifcp != NULL) *ifcp = if_clone_findifc(ifp); /* + * On VNET shutdown abort here as the stack teardown will do all + * the work top-down for us. + */ + if (shutdown) { + /* + * In case of a vmove we are done here without error. + * If we would signal an error it would lead to the same + * abort as if we did not find the ifnet anymore. + * if_detach() calls us in void context and does not care + * about an early abort notification, so life is splendid :) + */ + goto finish_vnet_shutdown; + } + + /* + * At this point we are not tearing down a VNET and are either + * going to destroy or vmove the interface and have to cleanup + * accordingly. + */ + + /* * Remove routes and flush queues. */ if_down(ifp); @@ -986,7 +1015,7 @@ if_detach_internal(struct ifnet *ifp, in if_purgeaddrs(ifp); #ifdef INET - in_ifdetach(ifp, !shutdown); + in_ifdetach(ifp, 1); #endif #ifdef INET6 @@ -996,10 +1025,9 @@ if_detach_internal(struct ifnet *ifp, in * routes are expected to be removed by the IPv6-specific kernel API. * Otherwise, the kernel will detect some inconsistency and bark it. */ - in6_ifdetach(ifp, !shutdown); + in6_ifdetach(ifp, 1); #endif - if (!shutdown) - if_purgemaddrs(ifp); + if_purgemaddrs(ifp); /* Announce that the interface is gone. */ rt_ifannouncemsg(ifp, IFAN_DEPARTURE); @@ -1029,9 +1057,9 @@ if_detach_internal(struct ifnet *ifp, in } } - if (!shutdown) - rt_flushifroutes(ifp); + rt_flushifroutes(ifp); +finish_vnet_shutdown: /* * We cannot hold the lock over dom_ifdetach calls as they might * sleep, for example trying to drain a callout, thus open up the @@ -1059,7 +1087,7 @@ if_detach_internal(struct ifnet *ifp, in * and finally find an unused if_xname for the target vnet. */ static void -if_vmove(struct ifnet *ifp, struct vnet *new_vnet, int shutdown) +if_vmove(struct ifnet *ifp, struct vnet *new_vnet) { struct if_clone *ifc; int rc; @@ -1077,7 +1105,7 @@ if_vmove(struct ifnet *ifp, struct vnet * mark as dead etc. so that the ifnet can be reattached later. * If we cannot find it, we lost the race to someone else. */ - rc = if_detach_internal(ifp, 1, shutdown, &ifc); + rc = if_detach_internal(ifp, 1, &ifc); if (rc != 0) return; @@ -1152,7 +1180,7 @@ if_vmove_loan(struct thread *td, struct } /* Move the interface into the child jail/vnet. */ - if_vmove(ifp, pr->pr_vnet, 0); + if_vmove(ifp, pr->pr_vnet); /* Report the new if_xname back to the userland. */ sprintf(ifname, "%s", ifp->if_xname); @@ -1195,7 +1223,7 @@ if_vmove_reclaim(struct thread *td, char } /* Get interface back from child jail/vnet. */ - if_vmove(ifp, vnet_dst, 0); + if_vmove(ifp, vnet_dst); CURVNET_RESTORE(); /* Report the new if_xname back to the userland. */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201604241636.u3OGaX8w077511>