svn commit: r191508 - in head/sys: kern sys
Marko Zec
zec at FreeBSD.org
Sun Apr 26 07:09:40 UTC 2009
Author: zec
Date: Sun Apr 26 07:09:39 2009
New Revision: 191508
URL: http://svn.freebsd.org/changeset/base/191508
Log:
Extend the vnet module registration / initialization framework
first introduced @ r190909 with a vnet module deregistration
service.
kldunloadable modules, which are currently using vnet_mod_register()
to attach their per-vnet initialization routines to the vnet
initialization framework, should call vnet_mod_deregister() before
acknowledging MOD_UNLOAD requests in their mod_event handlers. Such
changes to the existing code base will follow in subsequent commits.
vnet_mod_deregister() does not check whether departing vnet modules
are registered as prerequisites for another module(s), so it should
be used with care. Currently I'm only aware of vnet modules which
are leafs on module dependency graphs that are kldunloadable.
This change also introduces per-vnet module destructor handler, which
calls vnet's module cleanup function, which (if required) has to be
registered in vnet module's vnet_modinfo_t structure .vmi_idetach
field. Once options VIMAGE becomes operational, the framework will
take care that module's cleanup function become invoked for each
active vnet instance, and that the memory allocated for each instance
gets freed. Currently calls to destructor handlers must always
succeed.
Modified:
head/sys/kern/kern_vimage.c
head/sys/sys/vimage.h
Modified: head/sys/kern/kern_vimage.c
==============================================================================
--- head/sys/kern/kern_vimage.c Sun Apr 26 03:55:08 2009 (r191507)
+++ head/sys/kern/kern_vimage.c Sun Apr 26 07:09:39 2009 (r191508)
@@ -47,6 +47,7 @@ static TAILQ_HEAD(vnet_modlink_head, vne
static TAILQ_HEAD(vnet_modpending_head, vnet_modlink) vnet_modpending_head;
static void vnet_mod_complete_registration(struct vnet_modlink *);
static int vnet_mod_constructor(struct vnet_modlink *);
+static int vnet_mod_destructor(struct vnet_modlink *);
void
vnet_mod_register(const struct vnet_modinfo *vmi)
@@ -144,6 +145,37 @@ vnet_mod_complete_registration(struct vn
} while (vml_iter != NULL);
}
+void
+vnet_mod_deregister(const struct vnet_modinfo *vmi)
+{
+
+ vnet_mod_deregister_multi(vmi, NULL, NULL);
+}
+
+void
+vnet_mod_deregister_multi(const struct vnet_modinfo *vmi, void *iarg,
+ char *iname)
+{
+ VNET_ITERATOR_DECL(vnet_iter);
+ struct vnet_modlink *vml;
+
+ TAILQ_FOREACH(vml, &vnet_modlink_head, vml_mod_le)
+ if (vml->vml_modinfo == vmi && vml->vml_iarg == iarg)
+ break;
+ if (vml == NULL)
+ panic("cannot deregister unregistered vnet module %s",
+ vmi->vmi_name);
+
+ VNET_FOREACH(vnet_iter) {
+ CURVNET_SET_QUIET(vnet_iter);
+ vnet_mod_destructor(vml);
+ CURVNET_RESTORE();
+ }
+
+ TAILQ_REMOVE(&vnet_modlink_head, vml, vml_mod_le);
+ free(vml, M_VIMAGE);
+}
+
static int vnet_mod_constructor(struct vnet_modlink *vml)
{
const struct vnet_modinfo *vmi = vml->vml_modinfo;
@@ -153,16 +185,18 @@ static int vnet_mod_constructor(struct v
if (vml->vml_iarg)
printf("/%s", vml->vml_iname);
printf(": ");
- if (vmi->vmi_struct_size)
- printf("malloc(%zu); ", vmi->vmi_struct_size);
+#ifdef VIMAGE
+ if (vmi->vmi_size)
+ printf("malloc(%zu); ", vmi->vmi_size);
+#endif
if (vmi->vmi_iattach != NULL)
printf("iattach()");
printf("\n");
#endif
#ifdef VIMAGE
- if (vmi->vmi_struct_size) {
- void *mem = malloc(vmi->vmi_struct_size, M_VNET,
+ if (vmi->vmi_size) {
+ void *mem = malloc(vmi->vmi_size, M_VNET,
M_NOWAIT | M_ZERO);
if (mem == NULL) /* XXX should return error, not panic. */
panic("vi_alloc: malloc for %s\n", vmi->vmi_name);
@@ -176,6 +210,41 @@ static int vnet_mod_constructor(struct v
return (0);
}
+
+static int
+vnet_mod_destructor(struct vnet_modlink *vml)
+{
+ const struct vnet_modinfo *vmi = vml->vml_modinfo;
+
+#ifdef DEBUG_ORDERING
+ printf("destroying vnet_%s", vmi->vmi_name);
+ if (vml->vml_iarg)
+ printf("/%s", vml->vml_iname);
+ printf(": ");
+ if (vmi->vmi_idetach != NULL)
+ printf("idetach(); ");
+#ifdef VIMAGE
+ if (vmi->vmi_size)
+ printf("free()");
+#endif
+ printf("\n");
+#endif
+
+ if (vmi->vmi_idetach)
+ vmi->vmi_idetach(vml->vml_iarg);
+
+#ifdef VIMAGE
+ if (vmi->vmi_size) {
+ if (curvnet->mod_data[vmi->vmi_id] == NULL)
+ panic("vi_destroy: %s\n", vmi->vmi_name);
+ free(curvnet->mod_data[vmi->vmi_id], M_VNET);
+ curvnet->mod_data[vmi->vmi_id] = NULL;
+ }
+#endif
+
+ return (0);
+}
+
/*
* vi_symlookup() attempts to resolve name to address queries for
* variables which have been moved from global namespace to virtualization
Modified: head/sys/sys/vimage.h
==============================================================================
--- head/sys/sys/vimage.h Sun Apr 26 03:55:08 2009 (r191507)
+++ head/sys/sys/vimage.h Sun Apr 26 07:09:39 2009 (r191508)
@@ -121,6 +121,8 @@ struct vnet_modlink {
int vi_symlookup(struct kld_sym_lookup *, char *);
void vnet_mod_register(const struct vnet_modinfo *);
void vnet_mod_register_multi(const struct vnet_modinfo *, void *, char *);
+void vnet_mod_deregister(const struct vnet_modinfo *);
+void vnet_mod_deregister_multi(const struct vnet_modinfo *, void *, char *);
#endif /* !VIMAGE_GLOBALS */
More information about the svn-src-head
mailing list