On Wed, Apr 09, 2025 at 04:02:39PM +0800, Yunsheng Lin wrote:
On 2025/4/8 2:01, Johannes Weiner wrote:
@@ -2934,6 +2981,7 @@ struct page *rmqueue_buddy(struct zone *preferred_zone, struct zone *zone, { struct page *page; unsigned long flags;
- enum rmqueue_mode rmqm = RMQUEUE_NORMAL;
do { page = NULL; @@ -2945,7 +2993,7 @@ struct page *rmqueue_buddy(struct zone *preferred_zone, struct zone *zone, if (alloc_flags & ALLOC_HIGHATOMIC) page = __rmqueue_smallest(zone, order, MIGRATE_HIGHATOMIC); if (!page) {
page = __rmqueue(zone, order, migratetype, alloc_flags);
page = __rmqueue(zone, order, migratetype, alloc_flags, &rmqm);
/* * If the allocation fails, allow OOM handling and
It was not in the diff, but it seems the zone->lock is held inside the do..while loop, doesn't it mean that the freelists are subject to outside changes and rmqm is stale?
Yes. Note that it only loops when there is a bug/corrupted page, so it won't make much difference in practice. But it's still kind of weird.
Thanks for your review, Yunsheng!
Andrew, could you please fold the below fixlet?
---
From 71b1eea7ded41c1f674909f9755c23b9ee9bcb6a Mon Sep 17 00:00:00 2001 From: Johannes Weiner hannes@cmpxchg.org Date: Wed, 9 Apr 2025 09:56:52 -0400 Subject: [PATCH] mm: page_alloc: speed up fallbacks in rmqueue_bulk() fix
reset rmqueue_mode in rmqueue_buddy() error loop, per Yunsheng Lin
Signed-off-by: Johannes Weiner hannes@cmpxchg.org --- mm/page_alloc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index dfb2b3f508af..7ffeeb0f62d3 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -2983,7 +2983,6 @@ struct page *rmqueue_buddy(struct zone *preferred_zone, struct zone *zone, { struct page *page; unsigned long flags; - enum rmqueue_mode rmqm = RMQUEUE_NORMAL;
do { page = NULL; @@ -2996,6 +2995,8 @@ struct page *rmqueue_buddy(struct zone *preferred_zone, struct zone *zone, if (alloc_flags & ALLOC_HIGHATOMIC) page = __rmqueue_smallest(zone, order, MIGRATE_HIGHATOMIC); if (!page) { + enum rmqueue_mode rmqm = RMQUEUE_NORMAL; + page = __rmqueue(zone, order, migratetype, alloc_flags, &rmqm);
/*