diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c --- a/sys/kern/kern_jail.c +++ b/sys/kern/kern_jail.c @@ -3322,6 +3322,10 @@ mtx_assert(&pr->pr_mtx, MA_NOTOWNED); shm_remove_prison(pr); (void)osd_jail_call(pr, PR_METHOD_REMOVE, NULL); +#ifdef VIMAGE + if (pr->pr_vnet != pr->pr_parent->pr_vnet) + vnet_shutdown(pr->pr_vnet); +#endif } /* diff --git a/sys/net/vnet.h b/sys/net/vnet.h --- a/sys/net/vnet.h +++ b/sys/net/vnet.h @@ -166,9 +166,10 @@ #define VNET_STOP (uintptr_t)&__stop_set_vnet /* - * Functions to allocate and destroy virtual network stacks. + * Functions to allocate, shutdown and destroy virtual network stacks. */ struct vnet *vnet_alloc(void); +void vnet_shutdown(struct vnet *vnet); void vnet_destroy(struct vnet *vnet); /* @@ -360,6 +361,20 @@ SYSUNINIT(vnet_uninit_ ## ident, subsystem, order, \ vnet_deregister_sysuninit, &ident ## _vnet_uninit) +#define VNET_SHUTDOWN(ident, subsystem, order, func, arg) \ + CTASSERT((subsystem) > SI_SUB_VNET && \ + (subsystem) <= SI_SUB_VNET_DONE); \ + static struct vnet_sysinit ident ## _vnet_shutdown = { \ + subsystem, \ + order, \ + (sysinit_cfunc_t)(sysinit_nfunc_t)func, \ + (arg) \ + }; \ + SYSINIT(vnet_shutdown_ ## ident, subsystem, order, \ + vnet_register_shutdown, &ident ## _vnet_shutdown); \ + SYSUNINIT(vnet_shutdown_ ## ident, subsystem, order, \ + vnet_deregister_shutdown, &ident ## _vnet_shutdown) + /* * Run per-vnet sysinits or sysuninits during vnet creation/destruction. */ @@ -367,11 +382,13 @@ void vnet_sysuninit(void); /* - * Interfaces for managing per-vnet constructors and destructors. + * Interfaces for managing per-vnet constructors, shutdown handlers and destructors. */ void vnet_register_sysinit(void *arg); +void vnet_register_shutdown(void *arg); void vnet_register_sysuninit(void *arg); void vnet_deregister_sysinit(void *arg); +void vnet_deregister_shutdown(void *arg); void vnet_deregister_sysuninit(void *arg); /* @@ -449,7 +466,7 @@ SYSINIT(ident, subsystem, order, func, arg) #define VNET_SYSUNINIT(ident, subsystem, order, func, arg) \ SYSUNINIT(ident, subsystem, order, func, arg) - +#define VNET_SHUTDOWN(ident, subsystem, order, func, arg) /* * Without VIMAGE revert to the default implementation. */ diff --git a/sys/net/vnet.c b/sys/net/vnet.c --- a/sys/net/vnet.c +++ b/sys/net/vnet.c @@ -189,6 +189,8 @@ TAILQ_HEAD_INITIALIZER(vnet_constructors); static TAILQ_HEAD(vnet_sysuninit_head, vnet_sysinit) vnet_destructors = TAILQ_HEAD_INITIALIZER(vnet_destructors); +static TAILQ_HEAD(vnet_shutdown_head, vnet_sysinit) vnet_shutdown_handlers = + TAILQ_HEAD_INITIALIZER(vnet_shutdown_handlers); struct sx vnet_sysinit_sxlock; @@ -215,6 +217,7 @@ "struct vnet *"); SDT_PROBE_DEFINE2(vnet, functions, vnet_alloc, return, "int", "struct vnet *"); +// FIXME SDT_PROBE_DEFINE2 vnet_shutdown ? SDT_PROBE_DEFINE2(vnet, functions, vnet_destroy, entry, "int", "struct vnet *"); SDT_PROBE_DEFINE1(vnet, functions, vnet_destroy, return, @@ -264,6 +267,27 @@ return (vnet); } +/* + * Shutdown a virtual network stack, prior to destroy. + */ +void +vnet_shutdown(struct vnet *vnet) +{ + struct vnet_sysinit *vs; + + /* Signal that VNET is being shutdown. */ + vnet->vnet_shutdown = true; + + CURVNET_SET_QUIET(vnet); + VNET_SYSINIT_RLOCK(); + TAILQ_FOREACH_REVERSE(vs, &vnet_shutdown_handlers, vnet_shutdown_head, + link) { + vs->func(vs->arg); + } + VNET_SYSINIT_RUNLOCK(); + CURVNET_RESTORE(); +} + /* * Destroy a virtual network stack. */ @@ -279,9 +303,6 @@ LIST_REMOVE(vnet, vnet_le); VNET_LIST_WUNLOCK(); - /* Signal that VNET is being shutdown. */ - vnet->vnet_shutdown = true; - CURVNET_SET_QUIET(vnet); sx_xlock(&ifnet_detach_sxlock); vnet_sysuninit(); @@ -520,6 +541,52 @@ VNET_SYSINIT_WUNLOCK(); } +void +vnet_register_shutdown(void *arg) +{ + struct vnet_sysinit *vs, *vs2; + + vs = arg; + + /* Add the shutdown handler to the global list of vnet shutdown handlers. */ + VNET_SYSINIT_WLOCK(); + TAILQ_FOREACH(vs2, &vnet_shutdown_handlers, link) { + if (vs2->subsystem > vs->subsystem) + break; + if (vs2->subsystem == vs->subsystem && vs2->order > vs->order) + break; + } + if (vs2 != NULL) + TAILQ_INSERT_BEFORE(vs2, vs, link); + else + TAILQ_INSERT_TAIL(&vnet_shutdown_handlers, vs, link); + VNET_SYSINIT_WUNLOCK(); +} + +void +vnet_deregister_shutdown(void *arg) +{ + struct vnet_sysinit *vs; + struct vnet *vnet; + + vs = arg; + + /* + * Invoke the shutdown handler on all the existing vnets when it is + * deregistered. + */ + VNET_SYSINIT_WLOCK(); + VNET_FOREACH(vnet) { + CURVNET_SET_QUIET(vnet); + vs->func(vs->arg); + CURVNET_RESTORE(); + } + + /* Remove the destructor from the global list of vnet destructors. */ + TAILQ_REMOVE(&vnet_shutdown_handlers, vs, link); + VNET_SYSINIT_WUNLOCK(); +} + void vnet_register_sysuninit(void *arg) {