diff options
author | rwatson <rwatson@FreeBSD.org> | 2009-07-23 20:46:49 +0000 |
---|---|---|
committer | rwatson <rwatson@FreeBSD.org> | 2009-07-23 20:46:49 +0000 |
commit | b3be1c6e3bd7d3b5cf946ddb04c1c5811644229b (patch) | |
tree | 0191b21173debdadfbf9f7565dfc5a8b9eefe94a /sys/net/vnet.c | |
parent | fc8defe5dd957eaee1f1c841d45804df5bbf20f5 (diff) | |
download | FreeBSD-src-b3be1c6e3bd7d3b5cf946ddb04c1c5811644229b.zip FreeBSD-src-b3be1c6e3bd7d3b5cf946ddb04c1c5811644229b.tar.gz |
Introduce and use a sysinit-based initialization scheme for virtual
network stacks, VNET_SYSINIT:
- Add VNET_SYSINIT and VNET_SYSUNINIT macros to declare events that will
occur each time a network stack is instantiated and destroyed. In the
!VIMAGE case, these are simply mapped into regular SYSINIT/SYSUNINIT.
For the VIMAGE case, we instead use SYSINIT's to track their order and
properties on registration, using them for each vnet when created/
destroyed, or immediately on module load for already-started vnets.
- Remove vnet_modinfo mechanism that existed to serve this purpose
previously, as well as its dependency scheme: we now just use the
SYSINIT ordering scheme.
- Implement VNET_DOMAIN_SET() to allow protocol domains to declare that
they want init functions to be called for each virtual network stack
rather than just once at boot, compiling down to DOMAIN_SET() in the
non-VIMAGE case.
- Walk all virtualized kernel subsystems and make use of these instead
of modinfo or DOMAIN_SET() for init/uninit events. In some cases,
convert modular components from using modevent to using sysinit (where
appropriate). In some cases, do minor rejuggling of SYSINIT ordering
to make room for or better manage events.
Portions submitted by: jhb (VNET_SYSINIT), bz (cleanup)
Discussed with: jhb, bz, julian, zec
Reviewed by: bz
Approved by: re (VIMAGE blanket)
Diffstat (limited to 'sys/net/vnet.c')
-rw-r--r-- | sys/net/vnet.c | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/sys/net/vnet.c b/sys/net/vnet.c index a314886..cd5b2b3 100644 --- a/sys/net/vnet.c +++ b/sys/net/vnet.c @@ -126,6 +126,16 @@ MALLOC_DEFINE(M_VNET_DATA, "vnet_data", "VNET data"); */ static VNET_DEFINE(char, modspace[VNET_MODMIN]); +/* + * Global lists of subsystem constructor and destructors for vnets. + * They are registered via VNET_SYSINIT() and VNET_SYSUNINIT(). The + * lists are protected by the vnet_sxlock global lock. + */ +static TAILQ_HEAD(vnet_sysinit_head, vnet_sysinit) vnet_constructors = + TAILQ_HEAD_INITIALIZER(vnet_constructors); +static TAILQ_HEAD(vnet_sysuninit_head, vnet_sysinit) vnet_destructors = + TAILQ_HEAD_INITIALIZER(vnet_destructors); + struct vnet_data_free { uintptr_t vnd_start; int vnd_len; @@ -339,3 +349,135 @@ vnet_sysctl_handle_uint(SYSCTL_HANDLER_ARGS) arg1 = (void *)(curvnet->vnet_data_base + (uintptr_t)arg1); return (sysctl_handle_int(oidp, arg1, arg2, req)); } + +/* + * Support for special SYSINIT handlers registered via VNET_SYSINIT() + * and VNET_SYSUNINIT(). + */ +void +vnet_register_sysinit(void *arg) +{ + struct vnet_sysinit *vs, *vs2; + struct vnet *vnet; + + vs = arg; + KASSERT(vs->subsystem > SI_SUB_VNET, ("vnet sysinit too early")); + + /* Add the constructor to the global list of vnet constructors. */ + sx_xlock(&vnet_sxlock); + TAILQ_FOREACH(vs2, &vnet_constructors, 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_constructors, vs, link); + + /* + * Invoke the constructor on all the existing vnets when it is + * registered. + */ + VNET_FOREACH(vnet) { + CURVNET_SET_QUIET(vnet); + vs->func(vs->arg); + CURVNET_RESTORE(); + } + sx_xunlock(&vnet_sxlock); +} + +void +vnet_deregister_sysinit(void *arg) +{ + struct vnet_sysinit *vs; + + vs = arg; + + /* Remove the constructor from the global list of vnet constructors. */ + sx_xlock(&vnet_sxlock); + TAILQ_REMOVE(&vnet_constructors, vs, link); + sx_xunlock(&vnet_sxlock); +} + +void +vnet_register_sysuninit(void *arg) +{ + struct vnet_sysinit *vs, *vs2; + + vs = arg; + + /* Add the destructor to the global list of vnet destructors. */ + sx_xlock(&vnet_sxlock); + TAILQ_FOREACH(vs2, &vnet_destructors, 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_destructors, vs, link); + sx_xunlock(&vnet_sxlock); +} + +void +vnet_deregister_sysuninit(void *arg) +{ + struct vnet_sysinit *vs; + struct vnet *vnet; + + vs = arg; + + /* + * Invoke the destructor on all the existing vnets when it is + * deregistered. + */ + sx_xlock(&vnet_sxlock); + 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_destructors, vs, link); + sx_xunlock(&vnet_sxlock); +} + +/* + * Invoke all registered vnet constructors on the current vnet. Used + * during vnet construction. The caller is responsible for ensuring + * the new vnet is the current vnet and that the vnet_sxlock lock is + * locked. + */ +void +vnet_sysinit(void) +{ + struct vnet_sysinit *vs; + + sx_assert(&vnet_sxlock, SA_LOCKED); + TAILQ_FOREACH(vs, &vnet_constructors, link) { + vs->func(vs->arg); + } +} + +/* + * Invoke all registered vnet destructors on the current vnet. Used + * during vnet destruction. The caller is responsible for ensuring + * the dying vnet is the current vnet and that the vnet_sxlock lock is + * locked. + */ +void +vnet_sysuninit(void) +{ + struct vnet_sysinit *vs; + + sx_assert(&vnet_sxlock, SA_LOCKED); + TAILQ_FOREACH_REVERSE(vs, &vnet_destructors, vnet_sysuninit_head, + link) { + vs->func(vs->arg); + } +} |