6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vishal Moola (Oracle) vishal.moola@gmail.com
commit a84edd52f0a0fa193f0f685769939cf84510755b upstream.
The compaction code doesn't take references on pages until we're certain we should attempt to handle it.
In the hugetlb case, isolate_or_dissolve_huge_page() may return -EBUSY without taking a reference to the folio associated with our pfn. If our folio's refcount drops to 0, compound_nr() becomes unpredictable, making low_pfn and nr_scanned unreliable. The user-visible effect is minimal - this should rarely happen (if ever).
Fix this by storing the folio statistics earlier on the stack (just like the THP and Buddy cases).
Also revert commit 66fe1cf7f581 ("mm: compaction: use helper compound_nr in isolate_migratepages_block") to make backporting easier.
Link: https://lkml.kernel.org/r/20250401021025.637333-1-vishal.moola@gmail.com Fixes: 369fa227c219 ("mm: make alloc_contig_range handle free hugetlb pages") Signed-off-by: Vishal Moola (Oracle) vishal.moola@gmail.com Acked-by: Oscar Salvador osalvador@suse.de Reviewed-by: Zi Yan ziy@nvidia.com Cc: Miaohe Lin linmiaohe@huawei.com Cc: Oscar Salvador osalvador@suse.de Cc: stable@vger.kernel.org Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- mm/compaction.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
--- a/mm/compaction.c +++ b/mm/compaction.c @@ -980,13 +980,13 @@ isolate_migratepages_block(struct compac }
if (PageHuge(page)) { + const unsigned int order = compound_order(page); /* * skip hugetlbfs if we are not compacting for pages * bigger than its order. THPs and other compound pages * are handled below. */ if (!cc->alloc_contig) { - const unsigned int order = compound_order(page);
if (order <= MAX_PAGE_ORDER) { low_pfn += (1UL << order) - 1; @@ -1010,8 +1010,8 @@ isolate_migratepages_block(struct compac /* Do not report -EBUSY down the chain */ if (ret == -EBUSY) ret = 0; - low_pfn += compound_nr(page) - 1; - nr_scanned += compound_nr(page) - 1; + low_pfn += (1UL << order) - 1; + nr_scanned += (1UL << order) - 1; goto isolate_fail; }