mm: page_alloc: fix defrag_mode's retry & OOM path
authorJohannes Weiner <hannes@cmpxchg.org>
Sat, 22 Mar 2025 23:21:45 +0000 (19:21 -0400)
committerAndrew Morton <akpm@linux-foundation.org>
Tue, 1 Apr 2025 22:17:09 +0000 (15:17 -0700)
commit7a95a05f15d570e6087fea59280fe267fe809100
treeeda2ed52d713b9de19c2f9684312c55407c00bf4
parent36eed5400805b294f1df39b0e3ebc5b7971b3c16
mm: page_alloc: fix defrag_mode's retry & OOM path

Brendan points out that defrag_mode doesn't properly clear
ALLOC_NOFRAGMENT on its last-ditch attempt to allocate.  But looking
closer, the problem is actually more severe: it doesn't actually *check*
whether it's already retried, and keeps looping.  This means the OOM path
is never taken, and the thread can loop indefinitely.

This is verified with an intentional OOM test on defrag_mode=1, which
results in the machine hanging.  After this patch, it triggers the OOM
kill reliably and recovers.

Clear ALLOC_NOFRAGMENT properly, and only retry once.

Link: https://lkml.kernel.org/r/20250401041231.GA2117727@cmpxchg.org
Fixes: e3aa7df331bc ("mm: page_alloc: defrag_mode")
Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
Reported-by: Brendan Jackman <jackmanb@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
mm/page_alloc.c