Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 7ac7751

Browse files
Mel Gormanhnaz
authored andcommitted
mm: vmscan: do not throttle based on pfmemalloc reserves if node has no ZONE_NORMAL
throttle_direct_reclaim() is meant to trigger during swap-over-network during which the min watermark is treated as a pfmemalloc reserve. It throttes on the first node in the zonelist but this is flawed. The user-visible impact is that a process running on CPU whose local memory node has no ZONE_NORMAL will stall for prolonged periods of time, possibly indefintely. This is due to throttle_direct_reclaim thinking the pfmemalloc reserves are depleted when in fact they don't exist on that node. On a NUMA machine running a 32-bit kernel (I know) allocation requests from CPUs on node 1 would detect no pfmemalloc reserves and the process gets throttled. This patch adjusts throttling of direct reclaim to throttle based on the first node in the zonelist that has a usable ZONE_NORMAL or lower zone. Signed-off-by: Mel Gorman <[email protected]> Cc: <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 3e4dd75 commit 7ac7751

File tree

1 file changed

+27
-6
lines changed

1 file changed

+27
-6
lines changed

mm/vmscan.c

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2540,10 +2540,17 @@ static bool pfmemalloc_watermark_ok(pg_data_t *pgdat)
25402540

25412541
for (i = 0; i <= ZONE_NORMAL; i++) {
25422542
zone = &pgdat->node_zones[i];
2543+
if (!populated_zone(zone))
2544+
continue;
2545+
25432546
pfmemalloc_reserve += min_wmark_pages(zone);
25442547
free_pages += zone_page_state(zone, NR_FREE_PAGES);
25452548
}
25462549

2550+
/* If there are no reserves (unexpected config) then do not throttle */
2551+
if (!pfmemalloc_reserve)
2552+
return true;
2553+
25472554
wmark_ok = free_pages > pfmemalloc_reserve / 2;
25482555

25492556
/* kswapd must be awake if processes are being throttled */
@@ -2568,9 +2575,9 @@ static bool pfmemalloc_watermark_ok(pg_data_t *pgdat)
25682575
static bool throttle_direct_reclaim(gfp_t gfp_mask, struct zonelist *zonelist,
25692576
nodemask_t *nodemask)
25702577
{
2578+
struct zoneref *z;
25712579
struct zone *zone;
2572-
int high_zoneidx = gfp_zone(gfp_mask);
2573-
pg_data_t *pgdat;
2580+
pg_data_t *pgdat = NULL;
25742581

25752582
/*
25762583
* Kernel threads should not be throttled as they may be indirectly
@@ -2589,10 +2596,24 @@ static bool throttle_direct_reclaim(gfp_t gfp_mask, struct zonelist *zonelist,
25892596
if (fatal_signal_pending(current))
25902597
goto out;
25912598

2592-
/* Check if the pfmemalloc reserves are ok */
2593-
first_zones_zonelist(zonelist, high_zoneidx, NULL, &zone);
2594-
pgdat = zone->zone_pgdat;
2595-
if (pfmemalloc_watermark_ok(pgdat))
2599+
/*
2600+
* Check if the pfmemalloc reserves are ok by finding the first node
2601+
* with a usable ZONE_NORMAL or lower zone
2602+
*/
2603+
for_each_zone_zonelist_nodemask(zone, z, zonelist,
2604+
gfp_mask, nodemask) {
2605+
if (zone_idx(zone) > ZONE_NORMAL)
2606+
continue;
2607+
2608+
/* Throttle based on the first usable node */
2609+
pgdat = zone->zone_pgdat;
2610+
if (pfmemalloc_watermark_ok(pgdat))
2611+
goto out;
2612+
break;
2613+
}
2614+
2615+
/* If no zone was usable by the allocation flags then do not throttle */
2616+
if (!pgdat)
25962617
goto out;
25972618

25982619
/* Account for the throttling */

0 commit comments

Comments
 (0)