|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v3 017/114] module: add before/after hooks and module_call_init_fn
module_call_init just walks the list. Add register_module_hooks
so one init type can wrap that walk with before and after
ModuleInitHook callbacks, and add module_call_init_fn so a single
function takes the same path.
module_call_init passes MODULE_INIT_PHASE_ON. A DSO or
module_call_init_fn passes DSO_BEFORE until module_call_init
finishes, then DSO_AFTER.
Signed-off-by: Yonggang Luo <luoyonggang@xxxxxxxxx>
---
include/qemu/module.h | 18 +++++++++++
util/module.c | 70 ++++++++++++++++++++++++++++++++++++++++---
2 files changed, 84 insertions(+), 4 deletions(-)
diff --git a/include/qemu/module.h b/include/qemu/module.h
index 34e05c75348..c10e32731fa 100644
--- a/include/qemu/module.h
+++ b/include/qemu/module.h
@@ -60,6 +60,20 @@ typedef enum {
typedef void (ModuleInitFn)(void);
+/*
+ * Where one module_init_run sits relative to module_call_init().
+ * DSO_BEFORE: a DSO or module_call_init_fn before module_call_init().
+ * ON: module_call_init() itself.
+ * DSO_AFTER: a DSO or module_call_init_fn after module_call_init().
+ */
+typedef enum ModuleInitPhase {
+ MODULE_INIT_PHASE_DSO_BEFORE,
+ MODULE_INIT_PHASE_ON,
+ MODULE_INIT_PHASE_DSO_AFTER,
+} ModuleInitPhase;
+
+typedef bool (ModuleInitHook)(ModuleInitPhase phase, Error **errp);
+
typedef struct ModuleEntry {
ModuleInitFn *init;
QTAILQ_ENTRY(ModuleEntry) node;
@@ -82,6 +96,10 @@ void register_module_init(ModuleEntry *e, module_init_type
type);
void register_dso_module_init(ModuleEntry *e, module_init_type type);
void module_call_init(module_init_type type);
+void module_call_init_fn(module_init_type type, ModuleInitFn *init, Error
**errp);
+
+void register_module_hooks(module_init_type type,
+ ModuleInitHook *before, ModuleInitHook *after);
/*
* module_load: attempt to load a module from a set of directories
diff --git a/util/module.c b/util/module.c
index 6c5980542f6..a007ecb53a6 100644
--- a/util/module.c
+++ b/util/module.c
@@ -32,6 +32,8 @@ typedef QTAILQ_HEAD(, ModuleEntry) ModuleEntryList;
typedef struct ModuleInit
{
module_init_type type;
+ ModuleInitHook *before;
+ ModuleInitHook *after;
ModuleEntryList list;
ModuleEntryList dso_list;
bool done;
@@ -88,14 +90,54 @@ void register_dso_module_init(ModuleEntry *e,
module_init_type type)
module_init_add(&find_type(type)->dso_list, e);
}
-static void module_init_run(ModuleInit *m, ModuleEntryList *list)
+/**
+ * register_module_hooks:
+ * @type: init list
+ * @before: runs before every registered init for @type
+ * @after: runs after every registered init for @type
+ *
+ * One ModuleInit holds both callbacks so before and after stay 1:1.
+ * module_call_init(@type) passes MODULE_INIT_PHASE_ON. A DSO or
+ * module_call_init_fn passes DSO_BEFORE if module_call_init() has not
+ * finished, otherwise DSO_AFTER.
+ */
+void register_module_hooks(module_init_type type,
+ ModuleInitHook *before, ModuleInitHook *after)
+{
+ ModuleInit *m = find_type(type);
+
+ g_assert(before);
+ g_assert(after);
+ g_assert(!m->before && !m->after);
+
+ m->before = before;
+ m->after = after;
+}
+
+static bool module_init_run(ModuleInit *m, ModuleEntryList *list, bool is_dso,
+ Error **errp)
{
ModuleEntry *e;
+ ModuleInitPhase phase;
+
+ if (!is_dso) {
+ phase = MODULE_INIT_PHASE_ON;
+ } else if (m->done) {
+ phase = MODULE_INIT_PHASE_DSO_AFTER;
+ } else {
+ phase = MODULE_INIT_PHASE_DSO_BEFORE;
+ }
- (void)m;
+ if (m->before && !m->before(phase, errp)) {
+ return false;
+ }
QTAILQ_FOREACH(e, list, node) {
e->init();
}
+ if (m->after && !m->after(phase, errp)) {
+ return false;
+ }
+ return true;
}
void module_call_init(module_init_type type)
@@ -106,10 +148,27 @@ void module_call_init(module_init_type type)
return;
}
- module_init_run(m, &m->list);
+ module_init_run(m, &m->list, false, &error_abort);
m->done = true;
}
+/*
+ * Run a single init through @type's before/after hooks with is_dso=true.
+ * May run before or after module_call_init.
+ */
+void module_call_init_fn(module_init_type type, ModuleInitFn *init, Error
**errp)
+{
+ ModuleInit *m = find_type(type);
+ ModuleEntry e = {
+ .init = init,
+ };
+ ModuleEntryList list;
+
+ QTAILQ_INIT(&list);
+ QTAILQ_INSERT_TAIL(&list, &e, node);
+ module_init_run(m, &list, true, errp);
+}
+
#ifdef CONFIG_MODULES
static const QemuModinfo module_info_stub[] = { {
@@ -201,7 +260,10 @@ static bool module_load_dso(const char *fname, bool
export_symbols,
continue;
}
- module_init_run(m, &m->dso_list);
+ if (!module_init_run(m, &m->dso_list, true, errp)) {
+ empty_dso_lists();
+ return false;
+ }
}
trace_module_load_module(fname);
empty_dso_lists();
--
2.52.0.windows.1
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |