summaryrefslogtreecommitdiffstats
path: root/kernel/kmod.c
diff options
context:
space:
mode:
authorOleg Nesterov <oleg@redhat.com>2014-12-10 18:54:42 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-12-10 20:41:17 -0500
commit7f6def9f9b6ebba42fcdc12cfb3092f2cf44b3fe (patch)
tree031f84245bea9a5b64bcbdf0eb1f61e4949c6c34 /kernel/kmod.c
parent7117bc8888aff73fb081956afa501edcc85a1552 (diff)
usermodehelper: kill the kmod_thread_locker logic
Now that we do not call kernel_thread(CLONE_VFORK) from the worker thread we can not deadlock if do_execve() in turn triggers another call_usermodehelper(), we can remove the kmod_thread_locker code. Note: we should probably kill khelper_wq and simply use one of the global workqueues, say, system_unbound_wq, this special wq for umh buys nothing nowadays. Signed-off-by: Oleg Nesterov <oleg@redhat.com> Cc: Martin Schwidefsky <schwidefsky@de.ibm.com> Cc: Oleg Nesterov <oleg@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/kmod.c')
-rw-r--r--kernel/kmod.c33
1 files changed, 3 insertions, 30 deletions
diff --git a/kernel/kmod.c b/kernel/kmod.c
index 4621771b43b9..2777f40a9c7b 100644
--- a/kernel/kmod.c
+++ b/kernel/kmod.c
@@ -47,13 +47,6 @@ extern int max_threads;
47 47
48static struct workqueue_struct *khelper_wq; 48static struct workqueue_struct *khelper_wq;
49 49
50/*
51 * kmod_thread_locker is used for deadlock avoidance. There is no explicit
52 * locking to protect this global - it is private to the singleton khelper
53 * thread and should only ever be modified by that thread.
54 */
55static const struct task_struct *kmod_thread_locker;
56
57#define CAP_BSET (void *)1 50#define CAP_BSET (void *)1
58#define CAP_PI (void *)2 51#define CAP_PI (void *)2
59 52
@@ -273,13 +266,6 @@ out:
273 do_exit(0); 266 do_exit(0);
274} 267}
275 268
276static int call_helper(void *data)
277{
278 /* Worker thread started blocking khelper thread. */
279 kmod_thread_locker = current;
280 return ____call_usermodehelper(data);
281}
282
283/* Keventd can't block, but this (a child) can. */ 269/* Keventd can't block, but this (a child) can. */
284static int wait_for_helper(void *data) 270static int wait_for_helper(void *data)
285{ 271{
@@ -327,11 +313,9 @@ static void __call_usermodehelper(struct work_struct *work)
327 if (sub_info->wait & UMH_WAIT_PROC) 313 if (sub_info->wait & UMH_WAIT_PROC)
328 pid = kernel_thread(wait_for_helper, sub_info, 314 pid = kernel_thread(wait_for_helper, sub_info,
329 CLONE_FS | CLONE_FILES | SIGCHLD); 315 CLONE_FS | CLONE_FILES | SIGCHLD);
330 else { 316 else
331 pid = kernel_thread(call_helper, sub_info, SIGCHLD); 317 pid = kernel_thread(____call_usermodehelper, sub_info,
332 /* Worker thread stopped blocking khelper thread. */ 318 SIGCHLD);
333 kmod_thread_locker = NULL;
334 }
335 319
336 if (pid < 0) { 320 if (pid < 0) {
337 sub_info->retval = pid; 321 sub_info->retval = pid;
@@ -565,17 +549,6 @@ int call_usermodehelper_exec(struct subprocess_info *sub_info, int wait)
565 goto out; 549 goto out;
566 } 550 }
567 /* 551 /*
568 * Worker thread must not wait for khelper thread at below
569 * wait_for_completion() if the thread was created with CLONE_VFORK
570 * flag, for khelper thread is already waiting for the thread at
571 * wait_for_completion() in do_fork().
572 */
573 if (wait != UMH_NO_WAIT && current == kmod_thread_locker) {
574 retval = -EBUSY;
575 goto out;
576 }
577
578 /*
579 * Set the completion pointer only if there is a waiter. 552 * Set the completion pointer only if there is a waiter.
580 * This makes it possible to use umh_complete to free 553 * This makes it possible to use umh_complete to free
581 * the data structure in case of UMH_NO_WAIT. 554 * the data structure in case of UMH_NO_WAIT.