aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c15
-rw-r--r--fs/fs-writeback.c4
-rw-r--r--include/linux/freezer.h6
-rw-r--r--include/linux/kthread.h1
-rw-r--r--kernel/freezer.c6
-rw-r--r--kernel/kthread.c25
-rw-r--r--mm/backing-dev.c8
7 files changed, 42 insertions, 23 deletions
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index 7b828680b21d..4b11fc91fa7d 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -2456,8 +2456,9 @@ static int hotkey_kthread(void *data)
2456 u32 poll_mask, event_mask; 2456 u32 poll_mask, event_mask;
2457 unsigned int si, so; 2457 unsigned int si, so;
2458 unsigned long t; 2458 unsigned long t;
2459 unsigned int change_detector, must_reset; 2459 unsigned int change_detector;
2460 unsigned int poll_freq; 2460 unsigned int poll_freq;
2461 bool was_frozen;
2461 2462
2462 mutex_lock(&hotkey_thread_mutex); 2463 mutex_lock(&hotkey_thread_mutex);
2463 2464
@@ -2488,14 +2489,14 @@ static int hotkey_kthread(void *data)
2488 t = 100; /* should never happen... */ 2489 t = 100; /* should never happen... */
2489 } 2490 }
2490 t = msleep_interruptible(t); 2491 t = msleep_interruptible(t);
2491 if (unlikely(kthread_should_stop())) 2492 if (unlikely(kthread_freezable_should_stop(&was_frozen)))
2492 break; 2493 break;
2493 must_reset = try_to_freeze(); 2494
2494 if (t > 0 && !must_reset) 2495 if (t > 0 && !was_frozen)
2495 continue; 2496 continue;
2496 2497
2497 mutex_lock(&hotkey_thread_data_mutex); 2498 mutex_lock(&hotkey_thread_data_mutex);
2498 if (must_reset || hotkey_config_change != change_detector) { 2499 if (was_frozen || hotkey_config_change != change_detector) {
2499 /* forget old state on thaw or config change */ 2500 /* forget old state on thaw or config change */
2500 si = so; 2501 si = so;
2501 t = 0; 2502 t = 0;
@@ -2528,10 +2529,6 @@ exit:
2528static void hotkey_poll_stop_sync(void) 2529static void hotkey_poll_stop_sync(void)
2529{ 2530{
2530 if (tpacpi_hotkey_task) { 2531 if (tpacpi_hotkey_task) {
2531 if (frozen(tpacpi_hotkey_task) ||
2532 freezing(tpacpi_hotkey_task))
2533 thaw_process(tpacpi_hotkey_task);
2534
2535 kthread_stop(tpacpi_hotkey_task); 2532 kthread_stop(tpacpi_hotkey_task);
2536 tpacpi_hotkey_task = NULL; 2533 tpacpi_hotkey_task = NULL;
2537 mutex_lock(&hotkey_thread_mutex); 2534 mutex_lock(&hotkey_thread_mutex);
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 73c3992b2bb4..271fde50f0ee 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -947,7 +947,7 @@ int bdi_writeback_thread(void *data)
947 947
948 trace_writeback_thread_start(bdi); 948 trace_writeback_thread_start(bdi);
949 949
950 while (!kthread_should_stop()) { 950 while (!kthread_freezable_should_stop(NULL)) {
951 /* 951 /*
952 * Remove own delayed wake-up timer, since we are already awake 952 * Remove own delayed wake-up timer, since we are already awake
953 * and we'll take care of the preriodic write-back. 953 * and we'll take care of the preriodic write-back.
@@ -977,8 +977,6 @@ int bdi_writeback_thread(void *data)
977 */ 977 */
978 schedule(); 978 schedule();
979 } 979 }
980
981 try_to_freeze();
982 } 980 }
983 981
984 /* Flush any work that raced with us exiting */ 982 /* Flush any work that raced with us exiting */
diff --git a/include/linux/freezer.h b/include/linux/freezer.h
index 7a9427e9fe47..d02b78448b0f 100644
--- a/include/linux/freezer.h
+++ b/include/linux/freezer.h
@@ -47,7 +47,7 @@ static inline bool should_send_signal(struct task_struct *p)
47/* Takes and releases task alloc lock using task_lock() */ 47/* Takes and releases task alloc lock using task_lock() */
48extern int thaw_process(struct task_struct *p); 48extern int thaw_process(struct task_struct *p);
49 49
50extern bool __refrigerator(void); 50extern bool __refrigerator(bool check_kthr_stop);
51extern int freeze_processes(void); 51extern int freeze_processes(void);
52extern int freeze_kernel_threads(void); 52extern int freeze_kernel_threads(void);
53extern void thaw_processes(void); 53extern void thaw_processes(void);
@@ -57,7 +57,7 @@ static inline bool try_to_freeze(void)
57 might_sleep(); 57 might_sleep();
58 if (likely(!freezing(current))) 58 if (likely(!freezing(current)))
59 return false; 59 return false;
60 return __refrigerator(); 60 return __refrigerator(false);
61} 61}
62 62
63extern bool freeze_task(struct task_struct *p, bool sig_only); 63extern bool freeze_task(struct task_struct *p, bool sig_only);
@@ -180,7 +180,7 @@ static inline void set_freeze_flag(struct task_struct *p) {}
180static inline void clear_freeze_flag(struct task_struct *p) {} 180static inline void clear_freeze_flag(struct task_struct *p) {}
181static inline int thaw_process(struct task_struct *p) { return 1; } 181static inline int thaw_process(struct task_struct *p) { return 1; }
182 182
183static inline bool __refrigerator(void) { return false; } 183static inline bool __refrigerator(bool check_kthr_stop) { return false; }
184static inline int freeze_processes(void) { return -ENOSYS; } 184static inline int freeze_processes(void) { return -ENOSYS; }
185static inline int freeze_kernel_threads(void) { return -ENOSYS; } 185static inline int freeze_kernel_threads(void) { return -ENOSYS; }
186static inline void thaw_processes(void) {} 186static inline void thaw_processes(void) {}
diff --git a/include/linux/kthread.h b/include/linux/kthread.h
index 5cac19b3a266..0714b24c0e45 100644
--- a/include/linux/kthread.h
+++ b/include/linux/kthread.h
@@ -35,6 +35,7 @@ struct task_struct *kthread_create_on_node(int (*threadfn)(void *data),
35void kthread_bind(struct task_struct *k, unsigned int cpu); 35void kthread_bind(struct task_struct *k, unsigned int cpu);
36int kthread_stop(struct task_struct *k); 36int kthread_stop(struct task_struct *k);
37int kthread_should_stop(void); 37int kthread_should_stop(void);
38bool kthread_freezable_should_stop(bool *was_frozen);
38void *kthread_data(struct task_struct *k); 39void *kthread_data(struct task_struct *k);
39 40
40int kthreadd(void *unused); 41int kthreadd(void *unused);
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 :-). */
26bool __refrigerator(void) 27bool __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();
diff --git a/kernel/kthread.c b/kernel/kthread.c
index b6d216a92639..1c36deaae2f1 100644
--- a/kernel/kthread.c
+++ b/kernel/kthread.c
@@ -59,6 +59,31 @@ int kthread_should_stop(void)
59EXPORT_SYMBOL(kthread_should_stop); 59EXPORT_SYMBOL(kthread_should_stop);
60 60
61/** 61/**
62 * kthread_freezable_should_stop - should this freezable kthread return now?
63 * @was_frozen: optional out parameter, indicates whether %current was frozen
64 *
65 * kthread_should_stop() for freezable kthreads, which will enter
66 * refrigerator if necessary. This function is safe from kthread_stop() /
67 * freezer deadlock and freezable kthreads should use this function instead
68 * of calling try_to_freeze() directly.
69 */
70bool kthread_freezable_should_stop(bool *was_frozen)
71{
72 bool frozen = false;
73
74 might_sleep();
75
76 if (unlikely(freezing(current)))
77 frozen = __refrigerator(true);
78
79 if (was_frozen)
80 *was_frozen = frozen;
81
82 return kthread_should_stop();
83}
84EXPORT_SYMBOL_GPL(kthread_freezable_should_stop);
85
86/**
62 * kthread_data - return data value specified on kthread creation 87 * kthread_data - return data value specified on kthread creation
63 * @task: kthread task in question 88 * @task: kthread task in question
64 * 89 *
diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index 71034f41a2ba..7ba8feae11b8 100644
--- a/mm/backing-dev.c
+++ b/mm/backing-dev.c
@@ -600,14 +600,10 @@ static void bdi_wb_shutdown(struct backing_dev_info *bdi)
600 600
601 /* 601 /*
602 * Finally, kill the kernel thread. We don't need to be RCU 602 * Finally, kill the kernel thread. We don't need to be RCU
603 * safe anymore, since the bdi is gone from visibility. Force 603 * safe anymore, since the bdi is gone from visibility.
604 * unfreeze of the thread before calling kthread_stop(), otherwise
605 * it would never exet if it is currently stuck in the refrigerator.
606 */ 604 */
607 if (bdi->wb.task) { 605 if (bdi->wb.task)
608 thaw_process(bdi->wb.task);
609 kthread_stop(bdi->wb.task); 606 kthread_stop(bdi->wb.task);
610 }
611} 607}
612 608
613/* 609/*