aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/kmod.c25
1 files changed, 23 insertions, 2 deletions
diff --git a/kernel/kmod.c b/kernel/kmod.c
index 6d016c5d97c8..2f37acde640b 100644
--- a/kernel/kmod.c
+++ b/kernel/kmod.c
@@ -71,6 +71,18 @@ static atomic_t kmod_concurrent_max = ATOMIC_INIT(MAX_KMOD_CONCURRENT);
71static DECLARE_WAIT_QUEUE_HEAD(kmod_wq); 71static DECLARE_WAIT_QUEUE_HEAD(kmod_wq);
72 72
73/* 73/*
74 * This is a restriction on having *all* MAX_KMOD_CONCURRENT threads
75 * running at the same time without returning. When this happens we
76 * believe you've somehow ended up with a recursive module dependency
77 * creating a loop.
78 *
79 * We have no option but to fail.
80 *
81 * Userspace should proactively try to detect and prevent these.
82 */
83#define MAX_KMOD_ALL_BUSY_TIMEOUT 5
84
85/*
74 modprobe_path is set via /proc/sys. 86 modprobe_path is set via /proc/sys.
75*/ 87*/
76char modprobe_path[KMOD_PATH_LEN] = "/sbin/modprobe"; 88char modprobe_path[KMOD_PATH_LEN] = "/sbin/modprobe";
@@ -167,8 +179,17 @@ int __request_module(bool wait, const char *fmt, ...)
167 pr_warn_ratelimited("request_module: kmod_concurrent_max (%u) close to 0 (max_modprobes: %u), for module %s, throttling...", 179 pr_warn_ratelimited("request_module: kmod_concurrent_max (%u) close to 0 (max_modprobes: %u), for module %s, throttling...",
168 atomic_read(&kmod_concurrent_max), 180 atomic_read(&kmod_concurrent_max),
169 MAX_KMOD_CONCURRENT, module_name); 181 MAX_KMOD_CONCURRENT, module_name);
170 wait_event_interruptible(kmod_wq, 182 ret = wait_event_killable_timeout(kmod_wq,
171 atomic_dec_if_positive(&kmod_concurrent_max) >= 0); 183 atomic_dec_if_positive(&kmod_concurrent_max) >= 0,
184 MAX_KMOD_ALL_BUSY_TIMEOUT * HZ);
185 if (!ret) {
186 pr_warn_ratelimited("request_module: modprobe %s cannot be processed, kmod busy with %d threads for more than %d seconds now",
187 module_name, MAX_KMOD_CONCURRENT, MAX_KMOD_ALL_BUSY_TIMEOUT);
188 return -ETIME;
189 } else if (ret == -ERESTARTSYS) {
190 pr_warn_ratelimited("request_module: sigkill sent for modprobe %s, giving up", module_name);
191 return ret;
192 }
172 } 193 }
173 194
174 trace_module_request(module_name, wait, _RET_IP_); 195 trace_module_request(module_name, wait, _RET_IP_);