mm: Increment kswapd_waiters for throttled direct reclaimers

Throttled direct reclaimers will wake up kswapd and wait for kswapd to
satisfy their page allocation request, even when the failed allocation
lacks the __GFP_KSWAPD_RECLAIM flag in its gfp mask. As a result, kswapd
may think that there are no waiters and thus exit prematurely, causing
throttled direct reclaimers lacking __GFP_KSWAPD_RECLAIM to stall on
waiting for kswapd to wake them up. Incrementing the kswapd_waiters
counter when such direct reclaimers become throttled fixes the problem.

Signed-off-by: Sultan Alsawaf <sultan@kerneltoast.com>
fourteen
Sultan Alsawaf 3 years ago committed by Jenna
parent 0068768b2a
commit 6033cfd36e
  1. 16
      mm/vmscan.c

@ -3188,7 +3188,7 @@ retry:
return 0;
}
static bool allow_direct_reclaim(pg_data_t *pgdat)
static bool allow_direct_reclaim(pg_data_t *pgdat, bool using_kswapd)
{
struct zone *zone;
unsigned long pfmemalloc_reserve = 0;
@ -3217,6 +3217,10 @@ static bool allow_direct_reclaim(pg_data_t *pgdat)
wmark_ok = free_pages > pfmemalloc_reserve / 2;
/* The throttled direct reclaimer is now a kswapd waiter */
if (unlikely(!using_kswapd && !wmark_ok))
atomic_long_inc(&kswapd_waiters);
/* kswapd must be awake if processes are being throttled */
if (!wmark_ok && waitqueue_active(&pgdat->kswapd_wait)) {
pgdat->kswapd_classzone_idx = min(pgdat->kswapd_classzone_idx,
@ -3281,7 +3285,7 @@ static bool throttle_direct_reclaim(gfp_t gfp_mask, struct zonelist *zonelist,
/* Throttle based on the first usable node */
pgdat = zone->zone_pgdat;
if (allow_direct_reclaim(pgdat))
if (allow_direct_reclaim(pgdat, gfp_mask & __GFP_KSWAPD_RECLAIM))
goto out;
break;
}
@ -3303,16 +3307,18 @@ static bool throttle_direct_reclaim(gfp_t gfp_mask, struct zonelist *zonelist,
*/
if (!(gfp_mask & __GFP_FS)) {
wait_event_interruptible_timeout(pgdat->pfmemalloc_wait,
allow_direct_reclaim(pgdat), HZ);
allow_direct_reclaim(pgdat, true), HZ);
goto check_pending;
}
/* Throttle until kswapd wakes the process */
wait_event_killable(zone->zone_pgdat->pfmemalloc_wait,
allow_direct_reclaim(pgdat));
allow_direct_reclaim(pgdat, true));
check_pending:
if (unlikely(!(gfp_mask & __GFP_KSWAPD_RECLAIM)))
atomic_long_dec(&kswapd_waiters);
if (fatal_signal_pending(current))
return true;
@ -3691,7 +3697,7 @@ static int balance_pgdat(pg_data_t *pgdat, int order, int classzone_idx)
* able to safely make forward progress. Wake them
*/
if (waitqueue_active(&pgdat->pfmemalloc_wait) &&
allow_direct_reclaim(pgdat))
allow_direct_reclaim(pgdat, true))
wake_up_all(&pgdat->pfmemalloc_wait);
/* Check if kswapd should be suspending */

Loading…
Cancel
Save