[PATCH 4/6] mm/page_alloc: don't undo another isolation in alloc_contig_range

From: Gregory Price (Meta)

Date: Tue Oct 27 2026 - 00:23:36 EST


An alloc_contig_range() that overlaps a block going offline can leave
the offline spinning until it gets a signal, holding the device hotplug
lock. When isolation fails, alloc_contig_frozen_range() undoes it over
the whole range, clearing the offline's MIGRATE_ISOLATE too:

CPU 1 (offline_pages) CPU 2 (alloc_contig_range)
start_isolate_page_range()
blocks are MIGRATE_ISOLATE
start_isolate_page_range()
-EBUSY on CPU 1's blocks
undo_isolate_page_range()
blocks are MIGRATE_MOVABLE
test_pages_isolated()
never succeeds again

start_isolate_page_range() fails only on a block someone else isolated,
after undoing its own, so this undo only ever clears another caller's.
Return directly, as before alloc_contig_range() went pageblock granular.

With offline_pages() parked after isolating a DIMM block and a 1G
hugetlb allocation made over it, the offline on base still loops 30s
later in 4 of 4 runs:

offline_pages+0x5b2/0x1570
memory_subsys_offline+0x17e/0x470
device_offline+0x250/0x340
state_store+0x88/0x110

With this patch the allocation still fails, and the offline completes in
3 of 3 runs.

Fixes: b2c9e2fbba32 ("mm: make alloc_contig_range work at pageblock granularity")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Gregory Price (Meta) <gourry@xxxxxxxxxx>
---
mm/page_alloc.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 55d3fc4b307f5..bb3c7e95f2ed4 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -7396,9 +7396,13 @@ int alloc_contig_frozen_range_noprof(unsigned long start, unsigned long end,
* put back to page allocator so that buddy can use them.
*/

+ /*
+ * On failure this has undone its own isolation, and any other
+ * isolated blocks in the range belong to someone else, e.g. offline.
+ */
ret = start_isolate_page_range(start, end, mode);
if (ret)
- goto done;
+ return ret;

drain_all_pages(cc.zone);

--
2.53.0-Meta