]> www.infradead.org Git - users/willy/pagecache.git/commit
mm/contig_alloc: fix alloc_contig_range when __GFP_COMP and order < MAX_ORDER
authorJinjiang Tu <tujinjiang@huawei.com>
Wed, 12 Mar 2025 08:47:05 +0000 (16:47 +0800)
committerAndrew Morton <akpm@linux-foundation.org>
Fri, 14 Mar 2025 22:52:39 +0000 (15:52 -0700)
commit8c52207939c5cb3e06b79e13678afcc21b4c1aac
tree8a6db36fbf8714ed20c3122a11ed352bc8eae916
parent78a60329a0d71d2beecbdbc1c649c2b7545086a9
mm/contig_alloc: fix alloc_contig_range when __GFP_COMP and order < MAX_ORDER

When calling alloc_contig_range() with __GFP_COMP and the order of
requested pfn range is pageblock_order, less than MAX_ORDER, I triggered
WARNING as follows:

 PFN range: requested [21501050882150105600), allocated [21501050882150106112)
 WARNING: CPU: 3 PID: 580 at mm/page_alloc.c:6877 alloc_contig_range+0x280/0x340

alloc_contig_range() marks pageblocks of the requested pfn range to be
isolated, migrate these pages if they are in use and will be freed to
MIGRATE_ISOLATED freelist.

Suppose two alloc_contig_range() calls at the same time and the requested
pfn range are [0x80280000, 0x80280200) and [0x80280200, 0x80280400)
respectively.  Suppose the two memory range are in use, then
alloc_contig_range() will migrate and free these pages to MIGRATE_ISOLATED
freelist.  __free_one_page() will merge MIGRATE_ISOLATE buddy to larger
buddy, resulting in a MAX_ORDER buddy.  Finally, find_large_buddy() in
alloc_contig_range() returns a MAX_ORDER buddy and results in WARNING.

To fix it, call free_contig_range() to free the excess pfn range.

Link: https://lkml.kernel.org/r/20250312084705.2938220-1-tujinjiang@huawei.com
Fixes: e98337d11bbd ("mm/contig_alloc: support __GFP_COMP")
Signed-off-by: Jinjiang Tu <tujinjiang@huawei.com>
Cc: David Hildenbrand <david@redhat.com>
Cc: Kefeng Wang <wangkefeng.wang@huawei.com>
Cc: Nanyong Sun <sunnanyong@huawei.com>
Cc: Yu Zhao <yuzhao@google.com>
Cc: Zi Yan <ziy@nvidia.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
mm/page_alloc.c