Commit 5d2cd426 authored by Kemeng Shi's avatar Kemeng Shi Committed by Liu Shixin
Browse files

mm/compaction: correctly return failure with bogus compound_order in strict mode

mainline inclusion
from mainline-v6.7-rc1
commit 3da0272a4c7d0d37b47b28e87014f421296fc2be
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/IAR7B3

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=3da0272a4c7d0d37b47b28e87014f421296fc2be

--------------------------------

In strict mode, we should return 0 if there is any hole in pageblock.  If
we successfully isolated pages at beginning at pageblock and then have a
bogus compound_order outside pageblock in next page.  We will abort search
loop with blockpfn > end_pfn.  Although we will limit blockpfn to end_pfn,
we will treat it as a successful isolation in strict mode as blockpfn is
not < end_pfn and return partial isolated pages.  Then
isolate_freepages_range may success unexpectly with hole in isolated
range.

Link: https://lkml.kernel.org/r/20230901155141.249860-4-shikemeng@huaweicloud.com


Fixes: 9fcd6d2e ("mm, compaction: skip compound pages by order in free scanner")
Signed-off-by: default avatarKemeng Shi <shikemeng@huaweicloud.com>
Reviewed-by: default avatarBaolin Wang <baolin.wang@linux.alibaba.com>
Acked-by: default avatarMel Gorman <mgorman@techsingularity.net>
Cc: David Hildenbrand <david@redhat.com>
Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Conflicts:
	mm/compaction.c
[ Conflict because MAX_ORDER is redefined in commit 23baf831
  and context conflicts with commit 56d48d8d and dc13292c. ]
Signed-off-by: default avatarLiu Shixin <liushixin2@huawei.com>
parent c41f0a18
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -599,10 +599,11 @@ static unsigned long isolate_freepages_block(struct compact_control *cc,
		if (PageCompound(page)) {
			const unsigned int order = compound_order(page);

			if (likely(order < MAX_ORDER)) {
			if (blockpfn + (1UL << order) <= end_pfn) {
				blockpfn += (1UL << order) - 1;
				cursor += (1UL << order) - 1;
			}

			goto isolate_fail;
		}

@@ -657,8 +658,7 @@ static unsigned long isolate_freepages_block(struct compact_control *cc,
		spin_unlock_irqrestore(&cc->zone->lock, flags);

	/*
	 * There is a tiny chance that we have read bogus compound_order(),
	 * so be careful to not go outside of the pageblock.
	 * Be careful to not go outside of the pageblock.
	 */
	if (unlikely(blockpfn > end_pfn))
		blockpfn = end_pfn;