aboutsummaryrefslogtreecommitdiff
path: root/kernel/freezer.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2011-11-21 12:32:23 -0800
committerTejun Heo <tj@kernel.org>2011-11-21 12:32:23 -0800
commit8a32c441c1609f80e55df75422324a1151208f40 (patch)
tree73884b06cc2db3ea155af9a88815bb5105a4473e /kernel/freezer.c
parenta0acae0e886d44bd5ce6d2f173c1ace0fcf0d9f6 (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.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/kernel/freezer.c b/kernel/freezer.c
index 732f14f5944..b83c30e9483 100644
--- a/kernel/freezer.c
+++ b/kernel/freezer.c
@@ -9,6 +9,7 @@
#include <linux/export.h>
#include <linux/syscalls.h>
#include <linux/freezer.h>
+#include <linux/kthread.h>
/*
* freezing is complete, mark current process as frozen
@@ -23,7 +24,7 @@ static inline void frozen_process(void)
}
/* Refrigerator is place where frozen processes are stored :-). */
-bool __refrigerator(void)
+bool __refrigerator(bool check_kthr_stop)
{
/* Hmm, should we be allowed to suspend when there are realtime
processes around? */
@@ -50,7 +51,8 @@ bool __refrigerator(void)
for (;;) {
set_current_state(TASK_UNINTERRUPTIBLE);
- if (!frozen(current))
+ if (!frozen(current) ||
+ (check_kthr_stop && kthread_should_stop()))
break;
was_frozen = true;
schedule();