diff options
Diffstat (limited to 'mm/vmscan.c')
| -rw-r--r-- | mm/vmscan.c | 24 | 
1 files changed, 13 insertions, 11 deletions
| diff --git a/mm/vmscan.c b/mm/vmscan.c index bd9a72bc4a1b..ab2505c3ef54 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -2921,18 +2921,20 @@ static bool prepare_kswapd_sleep(pg_data_t *pgdat, int order, long remaining,  		return false;  	/* -	 * There is a potential race between when kswapd checks its watermarks -	 * and a process gets throttled. There is also a potential race if -	 * processes get throttled, kswapd wakes, a large process exits therby -	 * balancing the zones that causes kswapd to miss a wakeup. If kswapd -	 * is going to sleep, no process should be sleeping on pfmemalloc_wait -	 * so wake them now if necessary. If necessary, processes will wake -	 * kswapd and get throttled again +	 * The throttled processes are normally woken up in balance_pgdat() as +	 * soon as pfmemalloc_watermark_ok() is true. But there is a potential +	 * race between when kswapd checks the watermarks and a process gets +	 * throttled. There is also a potential race if processes get +	 * throttled, kswapd wakes, a large process exits thereby balancing the +	 * zones, which causes kswapd to exit balance_pgdat() before reaching +	 * the wake up checks. If kswapd is going to sleep, no process should +	 * be sleeping on pfmemalloc_wait, so wake them now if necessary. If +	 * the wake up is premature, processes will wake kswapd and get +	 * throttled again. The difference from wake ups in balance_pgdat() is +	 * that here we are under prepare_to_wait().  	 */ -	if (waitqueue_active(&pgdat->pfmemalloc_wait)) { -		wake_up(&pgdat->pfmemalloc_wait); -		return false; -	} +	if (waitqueue_active(&pgdat->pfmemalloc_wait)) +		wake_up_all(&pgdat->pfmemalloc_wait);  	return pgdat_balanced(pgdat, order, classzone_idx);  } | 
