diff options
-rw-r--r-- | drivers/platform/x86/thinkpad_acpi.c | 15 | ||||
-rw-r--r-- | fs/fs-writeback.c | 4 | ||||
-rw-r--r-- | include/linux/freezer.h | 6 | ||||
-rw-r--r-- | include/linux/kthread.h | 1 | ||||
-rw-r--r-- | kernel/freezer.c | 6 | ||||
-rw-r--r-- | kernel/kthread.c | 25 | ||||
-rw-r--r-- | mm/backing-dev.c | 8 |
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: | |||
2528 | static void hotkey_poll_stop_sync(void) | 2529 | static 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() */ |
48 | extern int thaw_process(struct task_struct *p); | 48 | extern int thaw_process(struct task_struct *p); |
49 | 49 | ||
50 | extern bool __refrigerator(void); | 50 | extern bool __refrigerator(bool check_kthr_stop); |
51 | extern int freeze_processes(void); | 51 | extern int freeze_processes(void); |
52 | extern int freeze_kernel_threads(void); | 52 | extern int freeze_kernel_threads(void); |
53 | extern void thaw_processes(void); | 53 | extern 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 | ||
63 | extern bool freeze_task(struct task_struct *p, bool sig_only); | 63 | extern bool freeze_task(struct task_struct *p, bool sig_only); |
@@ -180,7 +180,7 @@ static inline void set_freeze_flag(struct task_struct *p) {} | |||
180 | static inline void clear_freeze_flag(struct task_struct *p) {} | 180 | static inline void clear_freeze_flag(struct task_struct *p) {} |
181 | static inline int thaw_process(struct task_struct *p) { return 1; } | 181 | static inline int thaw_process(struct task_struct *p) { return 1; } |
182 | 182 | ||
183 | static inline bool __refrigerator(void) { return false; } | 183 | static inline bool __refrigerator(bool check_kthr_stop) { return false; } |
184 | static inline int freeze_processes(void) { return -ENOSYS; } | 184 | static inline int freeze_processes(void) { return -ENOSYS; } |
185 | static inline int freeze_kernel_threads(void) { return -ENOSYS; } | 185 | static inline int freeze_kernel_threads(void) { return -ENOSYS; } |
186 | static inline void thaw_processes(void) {} | 186 | static 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), | |||
35 | void kthread_bind(struct task_struct *k, unsigned int cpu); | 35 | void kthread_bind(struct task_struct *k, unsigned int cpu); |
36 | int kthread_stop(struct task_struct *k); | 36 | int kthread_stop(struct task_struct *k); |
37 | int kthread_should_stop(void); | 37 | int kthread_should_stop(void); |
38 | bool kthread_freezable_should_stop(bool *was_frozen); | ||
38 | void *kthread_data(struct task_struct *k); | 39 | void *kthread_data(struct task_struct *k); |
39 | 40 | ||
40 | int kthreadd(void *unused); | 41 | int 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 :-). */ |
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(); |
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) | |||
59 | EXPORT_SYMBOL(kthread_should_stop); | 59 | EXPORT_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 | */ | ||
70 | bool 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 | } | ||
84 | EXPORT_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 | /* |