Skip to content

Commit 6e70834

Browse files
mjkravetzBrian Maly
authored andcommitted
mm: perform 'last chance' reclaim efforts before allocation failure
In get_page_from_freelist(), perform an additional (last_chance) zone scan while calling zone_reclaim() before returning failure. This 'last chance' functionality is only enabled when the code is about to return an allocation failure or retry the allocation. Only 'easy' reclaim is performed on the preferred node. Orabug: 31295499 Signed-off-by: Mike Kravetz <[email protected]> Reviewed-by: Khalid Aziz <[email protected]> Signed-off-by: Brian Maly <[email protected]>
1 parent 769912d commit 6e70834

File tree

2 files changed

+24
-8
lines changed

2 files changed

+24
-8
lines changed

mm/internal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,5 +450,6 @@ unsigned long reclaim_clean_pages_from_list(struct zone *zone,
450450
#define ALLOC_CPUSET 0x40 /* check for correct cpuset */
451451
#define ALLOC_CMA 0x80 /* allow allocations from CMA areas */
452452
#define ALLOC_FAIR 0x100 /* fair zone allocation */
453+
#define ALLOC_LAST_CHANCE 0x200 /* take extra measures before failure */
453454

454455
#endif /* __MM_INTERNAL_H */

mm/page_alloc.c

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2124,6 +2124,7 @@ get_page_from_freelist(gfp_t gfp_mask, unsigned int order, int alloc_flags,
21242124
(gfp_mask & __GFP_WRITE);
21252125
int nr_fair_skipped = 0;
21262126
bool zonelist_rescan;
2127+
bool skip_reclaim = zone_reclaim_mode == 0;
21272128

21282129
zonelist_scan:
21292130
zonelist_rescan = false;
@@ -2208,7 +2209,7 @@ get_page_from_freelist(gfp_t gfp_mask, unsigned int order, int alloc_flags,
22082209
did_zlc_setup = 1;
22092210
}
22102211

2211-
if (zone_reclaim_mode == 0 ||
2212+
if (skip_reclaim ||
22122213
!zone_allows_reclaim(ac->preferred_zone, zone))
22132214
goto this_zone_full;
22142215

@@ -2288,6 +2289,17 @@ get_page_from_freelist(gfp_t gfp_mask, unsigned int order, int alloc_flags,
22882289
zonelist_rescan = true;
22892290
}
22902291

2292+
if (unlikely((alloc_flags & ALLOC_LAST_CHANCE) &&
2293+
!zonelist_rescan && skip_reclaim)) {
2294+
/*
2295+
* We have already performed a scan or two in the case
2296+
* of NUMA/zlc without success. If previous scans skipped
2297+
* reclaim, scan one more time with reclaim before failing.
2298+
*/
2299+
skip_reclaim = false;
2300+
zonelist_rescan = true;
2301+
}
2302+
22912303
if (zonelist_rescan)
22922304
goto zonelist_scan;
22932305

@@ -2691,7 +2703,7 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
26912703
{
26922704
const gfp_t wait = gfp_mask & __GFP_WAIT;
26932705
struct page *page = NULL;
2694-
int alloc_flags;
2706+
int alloc_flags = 0;
26952707
unsigned long pages_reclaimed = 0;
26962708
unsigned long did_some_progress;
26972709
enum migrate_mode migration_mode = MIGRATE_ASYNC;
@@ -2710,17 +2722,17 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
27102722
return NULL;
27112723
}
27122724

2713-
retry:
2714-
if (!(gfp_mask & __GFP_NO_KSWAPD))
2715-
wake_all_kswapds(order, ac);
2716-
27172725
/*
2718-
* OK, we're below the kswapd watermark and have kicked background
2719-
* reclaim. Now things get more complex, so set up alloc_flags according
2726+
* Things are getting more complex, so set up alloc_flags according
27202727
* to how we want to proceed.
27212728
*/
27222729
alloc_flags = gfp_to_alloc_flags(gfp_mask);
27232730

2731+
retry:
2732+
/* We're below the kswapd watermark so kick background reclaim. */
2733+
if (!(gfp_mask & __GFP_NO_KSWAPD))
2734+
wake_all_kswapds(order, ac);
2735+
27242736
/*
27252737
* Find the true preferred zone if the allocation is unconstrained by
27262738
* cpusets.
@@ -2830,6 +2842,9 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
28302842
if (page)
28312843
goto got_pg;
28322844

2845+
/* Make last chance efforts before failing or on retry */
2846+
alloc_flags |= ALLOC_LAST_CHANCE;
2847+
28332848
/* Check if we should retry the allocation */
28342849
pages_reclaimed += did_some_progress;
28352850
if (should_alloc_retry(gfp_mask, order, did_some_progress,

0 commit comments

Comments
 (0)