libkmod: Ignore errors from softdeps

Before we had softdeps, the usual idiom was

install foo /sbin/modprobe bar; /sbin/modprobe --ignore-install foo

ignoring errors from the first modprobe invocation. This also matches
the behavior of module-init-tools' implementation of softdep.
diff --git a/libkmod/libkmod-module.c b/libkmod/libkmod-module.c
index a6c8a6e..1d90f34 100644
--- a/libkmod/libkmod-module.c
+++ b/libkmod/libkmod-module.c
@@ -87,6 +87,13 @@
 	bool ignorecmd : 1;
 
 	/*
+	 * set by kmod_module_get_probe_list: indicates whether this is the
+	 * module the user asked for or its dependency, or whether this
+	 * is a softdep only
+	 */
+	bool required : 1;
+
+	/*
 	 * if module was created by searching the modules.builtin file, this
 	 * is set. There's nothing much useful one can do with such a
 	 * "module", except knowing it's builtin.
@@ -208,6 +215,11 @@
 	mod->builtin = builtin;
 }
 
+void kmod_module_set_required(struct kmod_module *mod, bool required)
+{
+	mod->required = required;
+}
+
 /*
  * Memory layout with alias:
  *
@@ -1033,6 +1045,7 @@
 }
 
 static int __kmod_module_get_probe_list(struct kmod_module *mod,
+						bool required,
 						bool ignorecmd,
 						struct kmod_list **list);
 
@@ -1052,7 +1065,7 @@
 
 	kmod_list_foreach(l, pre) {
 		struct kmod_module *m = l->data;
-		err = __kmod_module_get_probe_list(m, false, list);
+		err = __kmod_module_get_probe_list(m, false, false, list);
 		if (err < 0)
 			goto fail;
 	}
@@ -1068,7 +1081,7 @@
 
 	kmod_list_foreach(l, post) {
 		struct kmod_module *m = l->data;
-		err = __kmod_module_get_probe_list(m, false, list);
+		err = __kmod_module_get_probe_list(m, false, false, list);
 		if (err < 0)
 			goto fail;
 	}
@@ -1082,6 +1095,7 @@
 
 /* re-entrant */
 static int __kmod_module_get_probe_list(struct kmod_module *mod,
+						bool required,
 						bool ignorecmd,
 						struct kmod_list **list)
 {
@@ -1096,6 +1110,19 @@
 	mod->visited = true;
 
 	dep = kmod_module_get_dependencies(mod);
+	if (required) {
+		/*
+		 * Called from kmod_module_probe_insert_module(); set the
+		 * ->required flag on mod and all its dependencies before
+		 * they are possibly visited through some softdeps.
+		 */
+		mod->required = true;
+		kmod_list_foreach(l, dep) {
+			struct kmod_module *m = l->data;
+			m->required = true;
+		}
+	}
+
 	kmod_list_foreach(l, dep) {
 		struct kmod_module *m = l->data;
 		err = __kmod_module_fill_softdep(m, list);
@@ -1133,8 +1160,9 @@
 	 * Make sure we don't get screwed by previous calls to this function
 	 */
 	kmod_set_modules_visited(mod->ctx, false);
+	kmod_set_modules_required(mod->ctx, false);
 
-	err = __kmod_module_get_probe_list(mod, ignorecmd, list);
+	err = __kmod_module_get_probe_list(mod, true, ignorecmd, list);
 	if (err < 0) {
 		kmod_module_unref_list(*list);
 		*list = NULL;
@@ -1295,8 +1323,12 @@
 				(flags & KMOD_PROBE_FAIL_ON_LOADED))
 			break;
 
-		if (err == -EEXIST)
+		/*
+		 * Ignore errors from softdeps
+		 */
+		if (err == -EEXIST || !m->required)
 			err = 0;
+
 		else if (err < 0)
 			break;
 	}