Index: sys/net/if.c =================================================================== --- sys/net/if.c +++ sys/net/if.c @@ -1073,7 +1073,7 @@ * The vmove flag, if set, indicates that we are called from a callpath * that is moving an interface to a different vnet instance. * - * The shutdown flag, if set, indicates that we are called in the + * The has_moved_ifs flag, if set, indicates that we are called in the * process of shutting down a vnet instance. Currently only the * vnet_if_return SYSUNINIT function sets it. Note: we can be called * on a vnet instance shutdown without this flag being set, e.g., when @@ -1088,9 +1088,9 @@ struct ifnet *iter; int found = 0; #ifdef VIMAGE - bool shutdown; + bool has_moved_ifs; - shutdown = ifp->if_vnet->vnet_shutdown; + has_moved_ifs = vnet_has_moved_interfaces(ifp->if_vnet); #endif IFNET_WLOCK(); CK_STAILQ_FOREACH(iter, &V_ifnet, if_link) @@ -1160,7 +1160,7 @@ * On VNET shutdown abort here as the stack teardown will do all * the work top-down for us. */ - if (shutdown) { + if (has_moved_ifs) { /* Give interface users the chance to clean up. */ EVENTHANDLER_INVOKE(ifnet_departure_event, ifp); @@ -1171,7 +1171,7 @@ * if_detach() calls us in void context and does not care * about an early abort notification, so life is splendid :) */ - goto finish_vnet_shutdown; + goto finish_vnet_has_moved_ifs; } #endif @@ -1236,7 +1236,7 @@ rt_flushifroutes(ifp); #ifdef VIMAGE -finish_vnet_shutdown: +finish_vnet_has_moved_ifs: #endif /* * We cannot hold the lock over dom_ifdetach calls as they might Index: sys/net/vnet.h =================================================================== --- sys/net/vnet.h +++ sys/net/vnet.h @@ -72,9 +72,11 @@ u_int vnet_magic_n; u_int vnet_ifcnt; u_int vnet_sockcnt; - u_int vnet_shutdown; /* Shutdown in progress. */ + u_int vnet_state; /* SI_SUB_* */ void *vnet_data_mem; uintptr_t vnet_data_base; + u_int vnet_order; /* SI_ORDER_* */ + bool vnet_shutdown; /* Shutdown in progress. */ }; #define VNET_MAGIC_N 0x3e0d8f29 @@ -390,6 +392,24 @@ } \ } while(0) +static inline bool +vnet_has_moved_interfaces(struct vnet *vnet) +{ + return (vnet->vnet_shutdown && + ((vnet->vnet_state == SI_SUB_VNET_DONE && + vnet->vnet_order < SI_ORDER_ANY) || + (vnet->vnet_state < SI_SUB_VNET_DONE))); +} + +static inline bool +vnet_has_destroyed_hash_tables(struct vnet *vnet) +{ + return (vnet->vnet_shutdown && + ((vnet->vnet_state == SI_SUB_PROTO_DOMAIN && + vnet->vnet_order < SI_ORDER_THIRD) || + (vnet->vnet_state < SI_SUB_PROTO_DOMAIN))); +} + #else /* !VIMAGE */ /* Index: sys/net/vnet.c =================================================================== --- sys/net/vnet.c +++ sys/net/vnet.c @@ -279,6 +279,9 @@ LIST_REMOVE(vnet, vnet_le); VNET_LIST_WUNLOCK(); + /* Signal that VNET is being shutdown. */ + curvnet->vnet_shutdown = true; + CURVNET_SET_QUIET(vnet); vnet_sysuninit(); CURVNET_RESTORE(); @@ -350,16 +353,6 @@ } SYSINIT(vnet_data, SI_SUB_KLD, SI_ORDER_FIRST, vnet_data_startup, NULL); -static void -vnet_sysuninit_shutdown(void *unused __unused) -{ - - /* Signal that VNET is being shutdown. */ - curvnet->vnet_shutdown = 1; -} -VNET_SYSUNINIT(vnet_sysuninit_shutdown, SI_SUB_VNET_DONE, SI_ORDER_FIRST, - vnet_sysuninit_shutdown, NULL); - /* * When a module is loaded and requires storage for a virtualized global * variable, allocate space from the modspace free list. This interface @@ -572,9 +565,16 @@ struct vnet_sysinit *vs; VNET_SYSINIT_RLOCK(); - TAILQ_FOREACH(vs, &vnet_constructors, link) + TAILQ_FOREACH(vs, &vnet_constructors, link) { + curvnet->vnet_state = vs->subsystem; + curvnet->vnet_order = vs->order; vs->func(vs->arg); + } VNET_SYSINIT_RUNLOCK(); + + /* Make sure we always reach the final end state, also for vnet0. */ + curvnet->vnet_state = SI_SUB_VNET_DONE; + curvnet->vnet_order = SI_ORDER_ANY; } /* @@ -589,8 +589,11 @@ VNET_SYSINIT_RLOCK(); TAILQ_FOREACH_REVERSE(vs, &vnet_destructors, vnet_sysuninit_head, - link) + link) { + curvnet->vnet_state = vs->subsystem; + curvnet->vnet_order = vs->order; vs->func(vs->arg); + } VNET_SYSINIT_RUNLOCK(); } @@ -704,7 +707,9 @@ db_printf(" vnet_data_mem = %p\n", vnet->vnet_data_mem); db_printf(" vnet_data_base = %#jx\n", (uintmax_t)vnet->vnet_data_base); - db_printf(" vnet_shutdown = %#08x\n", vnet->vnet_shutdown); + db_printf(" vnet_state = %#08x\n", vnet->vnet_state); + db_printf(" vnet_order = %#08x\n", vnet->vnet_order); + db_printf(" vnet_shutdown = %u\n", vnet->vnet_shutdown); db_printf("\n"); }