Commit 2c4c3e29897d ("mm/page_alloc: simplify __alloc_pages_slowpath()
flow") retries an allocation once with reserve_flags when the caller
becomes eligible for reserves, guarded by can_retry_reserves.

A restart after a cpuset update or a zonelist rebuild retries with
can_retry_reserves already set to false, so a caller that cannot
reclaim (GFP_NOWAIT | __GFP_MEMALLOC), fails without trying reserves.

Reset can_retry_reserves on restart. Only a cpuset or zonelist change
restarts the slowpath, so the retry still runs at most once per change.

With a kprobe helping to make the race deterministic, an allocation
can be made to return NULL. With this patch the allocation will succeed.

Fixes: 2c4c3e29897d ("mm/page_alloc: simplify __alloc_pages_slowpath() flow")
Cc: [email protected]
Signed-off-by: Gregory Price (Meta) <[email protected]>
---
 mm/page_alloc.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index a8cac5e01066..f1048168c90c 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -4783,7 +4783,7 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
        unsigned int zonelist_iter_cookie;
        int reserve_flags;
        bool compact_first = false;
-       bool can_retry_reserves = true;
+       bool can_retry_reserves;
        unsigned long alloc_start_time = jiffies;
 
        if (unlikely(nofail)) {
@@ -4805,6 +4805,7 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
        no_progress_loops = 0;
        compact_result = COMPACT_SKIPPED;
        compact_priority = DEF_COMPACT_PRIORITY;
+       can_retry_reserves = true;
        cpuset_mems_cookie = read_mems_allowed_begin();
        zonelist_iter_cookie = zonelist_iter_begin();
 
-- 
2.56.0


Reply via email to