aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/freezer.h
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2011-11-21 15:32:25 -0500
committerTejun Heo <tj@kernel.org>2011-11-21 15:32:25 -0500
commit96ee6d8539c9fc6742908d85eb9723abb5c91854 (patch)
tree0c042d74508c777c33744e5a917ac16e057f073b /include/linux/freezer.h
parent948246f70a811c872b9d93bb4a8ab5823c4c79e0 (diff)
freezer: fix set_freezable[_with_signal]() race
A kthread doing set_freezable*() may race with on-going PM freeze and the freezer might think all tasks are frozen while the new freezable kthread is merrily proceeding to execute code paths which aren't supposed to be executing during PM freeze. Reimplement set_freezable[_with_signal]() using __set_freezable() such that freezable PF flags are modified under freezer_lock and try_to_freeze() is called afterwards. This eliminates race condition against freezing. Note: Separated out from larger patch to resolve fix order dependency Oleg pointed out. Signed-off-by: Tejun Heo <tj@kernel.org> Cc: Oleg Nesterov <oleg@redhat.com>
Diffstat (limited to 'include/linux/freezer.h')
-rw-r--r--include/linux/freezer.h9
1 files changed, 5 insertions, 4 deletions
diff --git a/include/linux/freezer.h b/include/linux/freezer.h
index 3d50913d39d0..a0f1b3a3604f 100644
--- a/include/linux/freezer.h
+++ b/include/linux/freezer.h
@@ -49,6 +49,7 @@ static inline bool try_to_freeze(void)
49} 49}
50 50
51extern bool freeze_task(struct task_struct *p, bool sig_only); 51extern bool freeze_task(struct task_struct *p, bool sig_only);
52extern bool __set_freezable(bool with_signal);
52 53
53#ifdef CONFIG_CGROUP_FREEZER 54#ifdef CONFIG_CGROUP_FREEZER
54extern bool cgroup_freezing(struct task_struct *task); 55extern bool cgroup_freezing(struct task_struct *task);
@@ -106,18 +107,18 @@ static inline int freezer_should_skip(struct task_struct *p)
106/* 107/*
107 * Tell the freezer that the current task should be frozen by it 108 * Tell the freezer that the current task should be frozen by it
108 */ 109 */
109static inline void set_freezable(void) 110static inline bool set_freezable(void)
110{ 111{
111 current->flags &= ~PF_NOFREEZE; 112 return __set_freezable(false);
112} 113}
113 114
114/* 115/*
115 * Tell the freezer that the current task should be frozen by it and that it 116 * Tell the freezer that the current task should be frozen by it and that it
116 * should send a fake signal to the task to freeze it. 117 * should send a fake signal to the task to freeze it.
117 */ 118 */
118static inline void set_freezable_with_signal(void) 119static inline bool set_freezable_with_signal(void)
119{ 120{
120 current->flags &= ~(PF_NOFREEZE | PF_FREEZER_NOSIG); 121 return __set_freezable(true);
121} 122}
122 123
123/* 124/*