diff options
author | Tejun Heo <tj@kernel.org> | 2011-11-21 15:32:23 -0500 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2011-11-21 15:32:23 -0500 |
commit | 8a32c441c1609f80e55df75422324a1151208f40 (patch) | |
tree | 73884b06cc2db3ea155af9a88815bb5105a4473e /kernel/freezer.c | |
parent | a0acae0e886d44bd5ce6d2f173c1ace0fcf0d9f6 (diff) |
freezer: implement and use kthread_freezable_should_stop()
Writeback and thinkpad_acpi have been using thaw_process() to prevent
deadlock between the freezer and kthread_stop(); unfortunately, this
is inherently racy - nothing prevents freezing from happening between
thaw_process() and kthread_stop().
This patch implements kthread_freezable_should_stop() which enters
refrigerator if necessary but is guaranteed to return if
kthread_stop() is invoked. Both thaw_process() users are converted to
use the new function.
Note that this deadlock condition exists for many of freezable
kthreads. They need to be converted to use the new should_stop or
freezable workqueue.
Tested with synthetic test case.
Signed-off-by: Tejun Heo <tj@kernel.org>
Acked-by: Henrique de Moraes Holschuh <ibm-acpi@hmh.eng.br>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Oleg Nesterov <oleg@redhat.com>
Diffstat (limited to 'kernel/freezer.c')
-rw-r--r-- | kernel/freezer.c | 6 |
1 files changed, 4 insertions, 2 deletions
diff --git a/kernel/freezer.c b/kernel/freezer.c index 732f14f5944f..b83c30e9483a 100644 --- a/kernel/freezer.c +++ b/kernel/freezer.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include <linux/export.h> | 9 | #include <linux/export.h> |
10 | #include <linux/syscalls.h> | 10 | #include <linux/syscalls.h> |
11 | #include <linux/freezer.h> | 11 | #include <linux/freezer.h> |
12 | #include <linux/kthread.h> | ||
12 | 13 | ||
13 | /* | 14 | /* |
14 | * freezing is complete, mark current process as frozen | 15 | * freezing is complete, mark current process as frozen |
@@ -23,7 +24,7 @@ static inline void frozen_process(void) | |||
23 | } | 24 | } |
24 | 25 | ||
25 | /* Refrigerator is place where frozen processes are stored :-). */ | 26 | /* Refrigerator is place where frozen processes are stored :-). */ |
26 | bool __refrigerator(void) | 27 | bool __refrigerator(bool check_kthr_stop) |
27 | { | 28 | { |
28 | /* Hmm, should we be allowed to suspend when there are realtime | 29 | /* Hmm, should we be allowed to suspend when there are realtime |
29 | processes around? */ | 30 | processes around? */ |
@@ -50,7 +51,8 @@ bool __refrigerator(void) | |||
50 | 51 | ||
51 | for (;;) { | 52 | for (;;) { |
52 | set_current_state(TASK_UNINTERRUPTIBLE); | 53 | set_current_state(TASK_UNINTERRUPTIBLE); |
53 | if (!frozen(current)) | 54 | if (!frozen(current) || |
55 | (check_kthr_stop && kthread_should_stop())) | ||
54 | break; | 56 | break; |
55 | was_frozen = true; | 57 | was_frozen = true; |
56 | schedule(); | 58 | schedule(); |