diff options
author | Rafael J. Wysocki <rjw@sisk.pl> | 2007-07-19 04:47:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-19 13:04:42 -0400 |
commit | 8cdd4936c17bd8085cb0dfacc4a37ccf8d0ada7b (patch) | |
tree | 0a9ff7cf1b1a797b1267beeb317507210f4dd170 /kernel/kmod.c | |
parent | b10d911749d37dccfa5873d2088aea3f074b9e45 (diff) |
PM: disable usermode helper before hibernation and suspend
Use a hibernation and suspend notifier to disable the user mode helper before
a hibernation/suspend and enable it after the operation.
[akpm@linux-foundation.org: build fix]
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Pavel Machek <pavel@ucw.cz>
Acked-by: Nigel Cunningham <nigel@nigel.suspend2.net>
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.c | 31 |
1 files changed, 30 insertions, 1 deletions
diff --git a/kernel/kmod.c b/kernel/kmod.c index 78d365c524ed..928f3678142a 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c | |||
@@ -33,12 +33,22 @@ | |||
33 | #include <linux/kernel.h> | 33 | #include <linux/kernel.h> |
34 | #include <linux/init.h> | 34 | #include <linux/init.h> |
35 | #include <linux/resource.h> | 35 | #include <linux/resource.h> |
36 | #include <linux/notifier.h> | ||
37 | #include <linux/suspend.h> | ||
36 | #include <asm/uaccess.h> | 38 | #include <asm/uaccess.h> |
37 | 39 | ||
38 | extern int max_threads; | 40 | extern int max_threads; |
39 | 41 | ||
40 | static struct workqueue_struct *khelper_wq; | 42 | static struct workqueue_struct *khelper_wq; |
41 | 43 | ||
44 | /* | ||
45 | * If set, both call_usermodehelper_keys() and call_usermodehelper_pipe() exit | ||
46 | * immediately returning -EBUSY. Used for preventing user land processes from | ||
47 | * being created after the user land has been frozen during a system-wide | ||
48 | * hibernation or suspend operation. | ||
49 | */ | ||
50 | static int usermodehelper_disabled; | ||
51 | |||
42 | #ifdef CONFIG_KMOD | 52 | #ifdef CONFIG_KMOD |
43 | 53 | ||
44 | /* | 54 | /* |
@@ -265,6 +275,24 @@ static void __call_usermodehelper(struct work_struct *work) | |||
265 | } | 275 | } |
266 | } | 276 | } |
267 | 277 | ||
278 | static int usermodehelper_pm_callback(struct notifier_block *nfb, | ||
279 | unsigned long action, | ||
280 | void *ignored) | ||
281 | { | ||
282 | switch (action) { | ||
283 | case PM_HIBERNATION_PREPARE: | ||
284 | case PM_SUSPEND_PREPARE: | ||
285 | usermodehelper_disabled = 1; | ||
286 | return NOTIFY_OK; | ||
287 | case PM_POST_HIBERNATION: | ||
288 | case PM_POST_SUSPEND: | ||
289 | usermodehelper_disabled = 0; | ||
290 | return NOTIFY_OK; | ||
291 | } | ||
292 | |||
293 | return NOTIFY_DONE; | ||
294 | } | ||
295 | |||
268 | /** | 296 | /** |
269 | * call_usermodehelper_setup - prepare to call a usermode helper | 297 | * call_usermodehelper_setup - prepare to call a usermode helper |
270 | * @path - path to usermode executable | 298 | * @path - path to usermode executable |
@@ -374,7 +402,7 @@ int call_usermodehelper_exec(struct subprocess_info *sub_info, | |||
374 | goto out; | 402 | goto out; |
375 | } | 403 | } |
376 | 404 | ||
377 | if (!khelper_wq) { | 405 | if (!khelper_wq || usermodehelper_disabled) { |
378 | retval = -EBUSY; | 406 | retval = -EBUSY; |
379 | goto out; | 407 | goto out; |
380 | } | 408 | } |
@@ -431,4 +459,5 @@ void __init usermodehelper_init(void) | |||
431 | { | 459 | { |
432 | khelper_wq = create_singlethread_workqueue("khelper"); | 460 | khelper_wq = create_singlethread_workqueue("khelper"); |
433 | BUG_ON(!khelper_wq); | 461 | BUG_ON(!khelper_wq); |
462 | pm_notifier(usermodehelper_pm_callback, 0); | ||
434 | } | 463 | } |