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

From: Vlastimil Babka (SUSE)

Date: Tue Nov 03 2026 - 11:53:23 EST


On 10/27/26 05:22, Gregory Price (Meta) wrote:
> 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>

I've applied this single patch to page_alloc/for-next-fixes and will drop
the version from Josef [1]. Also transferred Zi's R-b since it's the same
code change (plus comment).

[1]
https://lore.kernel.org/all/20261027-pgalloc-ai-hotfixes-v1-1-9c7d1aca801e@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);
>