Skip site navigation (1)Skip section navigation (2)
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>