aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/freezer.c
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 /kernel/freezer.c
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 'kernel/freezer.c')
-rw-r--r--kernel/freezer.c25
1 files changed, 25 insertions, 0 deletions
diff --git a/kernel/freezer.c b/kernel/freezer.c
index 95a123844241..b1e7a7b3d2cd 100644
--- a/kernel/freezer.c
+++ b/kernel/freezer.c
@@ -171,3 +171,28 @@ void __thaw_task(struct task_struct *p)
171 } 171 }
172 spin_unlock_irqrestore(&freezer_lock, flags); 172 spin_unlock_irqrestore(&freezer_lock, flags);
173} 173}
174
175/**
176 * __set_freezable - make %current freezable
177 * @with_signal: do we want %TIF_SIGPENDING for notification too?
178 *
179 * Mark %current freezable and enter refrigerator if necessary.
180 */
181bool __set_freezable(bool with_signal)
182{
183 might_sleep();
184
185 /*
186 * Modify flags while holding freezer_lock. This ensures the
187 * freezer notices that we aren't frozen yet or the freezing
188 * condition is visible to try_to_freeze() below.
189 */
190 spin_lock_irq(&freezer_lock);
191 current->flags &= ~PF_NOFREEZE;
192 if (with_signal)
193 current->flags &= ~PF_FREEZER_NOSIG;
194 spin_unlock_irq(&freezer_lock);
195
196 return try_to_freeze();
197}
198EXPORT_SYMBOL(__set_freezable);