Do not cache softdeps list
This might include a circular dependency which would screw up the
refcounting because there's an internal reference.
diff --git a/libkmod/libkmod-module.c b/libkmod/libkmod-module.c
index 4e19af9..9ad3f82 100644
--- a/libkmod/libkmod-module.c
+++ b/libkmod/libkmod-module.c
@@ -53,10 +53,6 @@
char *options;
const char *install_commands; /* owned by kmod_config */
const char *remove_commands; /* owned by kmod_config */
- struct {
- struct kmod_list *pre;
- struct kmod_list *post;
- } softdeps;
char *alias; /* only set if this module was created from an alias */
int n_dep;
int refcount;
@@ -65,7 +61,6 @@
bool options : 1;
bool install_commands : 1;
bool remove_commands : 1;
- bool softdeps : 1;
} init;
};
@@ -407,8 +402,6 @@
DBG(mod->ctx, "kmod_module %p released\n", mod);
kmod_pool_del_module(mod->ctx, mod, mod->hashkey);
- kmod_module_unref_list(mod->softdeps.pre);
- kmod_module_unref_list(mod->softdeps.post);
kmod_module_unref_list(mod->dep);
kmod_unref(mod->ctx);
free(mod->options);
@@ -935,19 +928,21 @@
* @post: where to save the list of post soft dependencies.
*
* Get soft dependencies for this kmod module. Soft dependencies come
- * from configuration file and are cached in @mod. The first call
- * to this function will search for this module in configuration and
- * subsequent calls return the known results.
+ * from configuration file and are not cached in @mod because it may include
+ * dependency cycles that would make we leak kmod_module. Any call
+ * to this function will search for this module in configuration, allocate a
+ * list and return the result.
*
* Both @pre and @post are newly created list of kmod_module and
* should be unreferenced with kmod_module_unref_list().
*
* Returns: 0 on success or < 0 otherwise.
*/
-KMOD_EXPORT int kmod_module_get_softdeps(const struct kmod_module *mod, struct kmod_list **pre, struct kmod_list **post)
+KMOD_EXPORT int kmod_module_get_softdeps(const struct kmod_module *mod,
+ struct kmod_list **pre,
+ struct kmod_list **post)
{
- const struct kmod_list *l;
- struct kmod_list *l_new;
+ const struct kmod_list *l, *ctx_softdeps;
if (mod == NULL || pre == NULL || post == NULL)
return -ENOENT;
@@ -955,64 +950,31 @@
assert(*pre == NULL);
assert(*post == NULL);
- if (!mod->init.softdeps) {
- /* lazy init */
- struct kmod_module *m = (struct kmod_module *)mod;
- const struct kmod_list *ctx_softdeps;
+ ctx_softdeps = kmod_get_softdeps(mod->ctx);
- ctx_softdeps = kmod_get_softdeps(mod->ctx);
+ kmod_list_foreach(l, ctx_softdeps) {
+ const char *modname = kmod_softdep_get_name(l);
+ const char * const *array;
+ unsigned count;
- kmod_list_foreach(l, ctx_softdeps) {
- const char *modname = kmod_softdep_get_name(l);
- const char * const *array;
- unsigned count;
+ if (fnmatch(modname, mod->name, 0) != 0)
+ continue;
- if (fnmatch(modname, mod->name, 0) != 0)
- continue;
+ array = kmod_softdep_get_pre(l, &count);
+ *pre = lookup_softdep(mod->ctx, array, count);
+ array = kmod_softdep_get_post(l, &count);
+ *post = lookup_softdep(mod->ctx, array, count);
- array = kmod_softdep_get_pre(l, &count);
- m->softdeps.pre = lookup_softdep(mod->ctx, array, count);
- array = kmod_softdep_get_post(l, &count);
- m->softdeps.post = lookup_softdep(mod->ctx, array, count);
- /*
- * find only the first command, as modprobe from
- * module-init-tools does
- */
- break;
- }
-
- m->init.softdeps = true;
- }
-
- kmod_list_foreach(l, mod->softdeps.pre) {
- l_new = kmod_list_append(*pre, kmod_module_ref(l->data));
- if (l_new == NULL) {
- kmod_module_unref(l->data);
- goto fail;
- }
- *pre = l_new;
- }
-
- kmod_list_foreach(l, mod->softdeps.post) {
- l_new = kmod_list_append(*post, kmod_module_ref(l->data));
- if (l_new == NULL) {
- kmod_module_unref(l->data);
- goto fail;
- }
- *post = l_new;
+ /*
+ * find only the first command, as modprobe from
+ * module-init-tools does
+ */
+ break;
}
return 0;
-
-fail:
- kmod_module_unref_list(*pre);
- *pre = NULL;
- kmod_module_unref_list(*post);
- *post = NULL;
- return -ENOMEM;
}
-
/**
* kmod_module_get_remove_commands:
* @mod: kmod module