Commit b1296cc4 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki Committed by Linus Torvalds

freezer: fix racy usage of try_to_freeze in kswapd

Currently we can miss freeze_process()->signal_wake_up() in kswapd() if it
happens between try_to_freeze() and prepare_to_wait().  To prevent this
from happening we should check freezing(current) before calling schedule().
Signed-off-by: default avatarRafael J. Wysocki <rjw@sisk.pl>
Cc: Pavel Machek <pavel@ucw.cz>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent d1d241cc
...@@ -1323,8 +1323,6 @@ static int kswapd(void *p) ...@@ -1323,8 +1323,6 @@ static int kswapd(void *p)
for ( ; ; ) { for ( ; ; ) {
unsigned long new_order; unsigned long new_order;
try_to_freeze();
prepare_to_wait(&pgdat->kswapd_wait, &wait, TASK_INTERRUPTIBLE); prepare_to_wait(&pgdat->kswapd_wait, &wait, TASK_INTERRUPTIBLE);
new_order = pgdat->kswapd_max_order; new_order = pgdat->kswapd_max_order;
pgdat->kswapd_max_order = 0; pgdat->kswapd_max_order = 0;
...@@ -1335,12 +1333,19 @@ static int kswapd(void *p) ...@@ -1335,12 +1333,19 @@ static int kswapd(void *p)
*/ */
order = new_order; order = new_order;
} else { } else {
schedule(); if (!freezing(current))
schedule();
order = pgdat->kswapd_max_order; order = pgdat->kswapd_max_order;
} }
finish_wait(&pgdat->kswapd_wait, &wait); finish_wait(&pgdat->kswapd_wait, &wait);
balance_pgdat(pgdat, order); if (!try_to_freeze()) {
/* We can speed up thawing tasks if we don't call
* balance_pgdat after returning from the refrigerator
*/
balance_pgdat(pgdat, order);
}
} }
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment