summaryrefslogtreecommitdiffstats
path: root/sys/net/vnet.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/net/vnet.c')
-rw-r--r--sys/net/vnet.c142
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);
+ }
+}
OpenPOWER on IntegriCloud