Revert "BACKPORT: mm: page_alloc: close migratetype race between freeing and stealing"

This reverts commit 7bd0ba0831.

Change-Id: If6c99eaf01e9aa030d038e06dd005cb858b69a19
Bug: 420771453
Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
This commit is contained in:
Kalesh Singh
2025-05-27 21:11:55 -07:00
parent 9ed2d2fba2
commit 135ab7374e

View File

@@ -1380,15 +1380,18 @@ static void free_pcppages_bulk(struct zone *zone, int count,
spin_unlock_irqrestore(&zone->lock, flags); spin_unlock_irqrestore(&zone->lock, flags);
} }
static void free_one_page(struct zone *zone, struct page *page, static void free_one_page(struct zone *zone,
unsigned long pfn, unsigned int order, struct page *page, unsigned long pfn,
fpi_t fpi_flags) unsigned int order,
int migratetype, fpi_t fpi_flags)
{ {
unsigned long flags; unsigned long flags;
int migratetype;
spin_lock_irqsave(&zone->lock, flags); spin_lock_irqsave(&zone->lock, flags);
if (unlikely(has_isolate_pageblock(zone) ||
is_migrate_isolate(migratetype))) {
migratetype = get_pfnblock_migratetype(page, pfn); migratetype = get_pfnblock_migratetype(page, pfn);
}
__free_one_page(page, pfn, zone, order, migratetype, fpi_flags); __free_one_page(page, pfn, zone, order, migratetype, fpi_flags);
spin_unlock_irqrestore(&zone->lock, flags); spin_unlock_irqrestore(&zone->lock, flags);
} }
@@ -1416,15 +1419,17 @@ skip_prepare:
fpi_flags, &skip_free_pages_ok); fpi_flags, &skip_free_pages_ok);
if (skip_free_pages_ok) if (skip_free_pages_ok)
return; return;
/*
spin_lock_irqsave(&zone->lock, flags); * Calling get_pfnblock_migratetype() without spin_lock_irqsave() here
* is used to avoid calling get_pfnblock_migratetype() under the lock.
* This will reduce the lock holding time.
*/
migratetype = get_pfnblock_migratetype(page, pfn); migratetype = get_pfnblock_migratetype(page, pfn);
trace_android_vh_free_unref_page_bypass(page, order, migratetype, &skip_free_unref_page); trace_android_vh_free_unref_page_bypass(page, order, migratetype, &skip_free_unref_page);
if (skip_free_unref_page) { if (skip_free_unref_page)
spin_unlock_irqrestore(&zone->lock, flags);
return; return;
}
spin_lock_irqsave(&zone->lock, flags);
if (unlikely(has_isolate_pageblock(zone) || if (unlikely(has_isolate_pageblock(zone) ||
is_migrate_isolate(migratetype))) { is_migrate_isolate(migratetype))) {
migratetype = get_pfnblock_migratetype(page, pfn); migratetype = get_pfnblock_migratetype(page, pfn);
@@ -2640,7 +2645,7 @@ void free_unref_page(struct page *page, unsigned int order)
struct per_cpu_pages *pcp; struct per_cpu_pages *pcp;
struct zone *zone; struct zone *zone;
unsigned long pfn = page_to_pfn(page); unsigned long pfn = page_to_pfn(page);
int migratetype; int migratetype, pcpmigratetype;
bool skip_free_unref_page = false; bool skip_free_unref_page = false;
if (!free_pages_prepare(page, order, FPI_NONE)) if (!free_pages_prepare(page, order, FPI_NONE))
@@ -2654,29 +2659,29 @@ void free_unref_page(struct page *page, unsigned int order)
* get those areas back if necessary. Otherwise, we may have to free * get those areas back if necessary. Otherwise, we may have to free
* excessively into the page allocator * excessively into the page allocator
*/ */
migratetype = get_pfnblock_migratetype(page, pfn); migratetype = pcpmigratetype = get_pfnblock_migratetype(page, pfn);
trace_android_vh_free_unref_page_bypass(page, order, migratetype, &skip_free_unref_page); trace_android_vh_free_unref_page_bypass(page, order, migratetype, &skip_free_unref_page);
if (skip_free_unref_page) if (skip_free_unref_page)
return; return;
if (unlikely(migratetype > MIGRATE_RECLAIMABLE)) { if (unlikely(migratetype > MIGRATE_RECLAIMABLE)) {
if (unlikely(is_migrate_isolate(migratetype))) { if (unlikely(is_migrate_isolate(migratetype))) {
free_one_page(page_zone(page), page, pfn, order, FPI_NONE); free_one_page(page_zone(page), page, pfn, order, migratetype, FPI_NONE);
return; return;
} }
#ifdef CONFIG_CMA #ifdef CONFIG_CMA
if (!cma_has_pcplist() || migratetype != MIGRATE_CMA) if (!cma_has_pcplist() || migratetype != MIGRATE_CMA)
#endif #endif
migratetype = MIGRATE_MOVABLE; pcpmigratetype = MIGRATE_MOVABLE;
} }
zone = page_zone(page); zone = page_zone(page);
pcp_trylock_prepare(UP_flags); pcp_trylock_prepare(UP_flags);
pcp = pcp_spin_trylock(zone->per_cpu_pageset); pcp = pcp_spin_trylock(zone->per_cpu_pageset);
if (pcp) { if (pcp) {
free_unref_page_commit(zone, pcp, page, migratetype, order); free_unref_page_commit(zone, pcp, page, pcpmigratetype, order);
pcp_spin_unlock(pcp); pcp_spin_unlock(pcp);
} else { } else {
free_one_page(zone, page, pfn, order, FPI_NONE); free_one_page(zone, page, pfn, order, migratetype, FPI_NONE);
} }
pcp_trylock_finish(UP_flags); pcp_trylock_finish(UP_flags);
} }
@@ -2709,7 +2714,7 @@ void free_unref_page_list(struct list_head *list)
migratetype = get_pfnblock_migratetype(page, pfn); migratetype = get_pfnblock_migratetype(page, pfn);
if (unlikely(is_migrate_isolate(migratetype))) { if (unlikely(is_migrate_isolate(migratetype))) {
list_del(&page->lru); list_del(&page->lru);
free_one_page(page_zone(page), page, pfn, 0, FPI_NONE); free_one_page(page_zone(page), page, pfn, 0, migratetype, FPI_NONE);
continue; continue;
} }
} }
@@ -2736,16 +2741,6 @@ void free_unref_page_list(struct list_head *list)
pcp_trylock_finish(UP_flags); pcp_trylock_finish(UP_flags);
} }
/*
* Free isolated pages directly to the
* allocator, see comment in free_unref_page.
*/
if (is_migrate_isolate(migratetype)) {
free_one_page(zone, page, page_to_pfn(page),
0, FPI_NONE);
continue;
}
batch_count = 0; batch_count = 0;
/* /*
@@ -2757,7 +2752,7 @@ void free_unref_page_list(struct list_head *list)
if (unlikely(!pcp)) { if (unlikely(!pcp)) {
pcp_trylock_finish(UP_flags); pcp_trylock_finish(UP_flags);
free_one_page(zone, page, pfn, free_one_page(zone, page, pfn,
0, FPI_NONE); 0, migratetype, FPI_NONE);
locked_zone = NULL; locked_zone = NULL;
continue; continue;
} }
@@ -7009,14 +7004,13 @@ bool take_page_off_buddy(struct page *page)
bool put_page_back_buddy(struct page *page) bool put_page_back_buddy(struct page *page)
{ {
struct zone *zone = page_zone(page); struct zone *zone = page_zone(page);
unsigned long pfn = page_to_pfn(page);
unsigned long flags; unsigned long flags;
int migratetype = get_pfnblock_migratetype(page, pfn);
bool ret = false; bool ret = false;
spin_lock_irqsave(&zone->lock, flags); spin_lock_irqsave(&zone->lock, flags);
if (put_page_testzero(page)) { if (put_page_testzero(page)) {
unsigned long pfn = page_to_pfn(page);
int migratetype = get_pfnblock_migratetype(page, pfn);
ClearPageHWPoisonTakenOff(page); ClearPageHWPoisonTakenOff(page);
__free_one_page(page, pfn, zone, 0, migratetype, FPI_NONE); __free_one_page(page, pfn, zone, 0, migratetype, FPI_NONE);
if (TestClearPageHWPoison(page)) { if (TestClearPageHWPoison(page)) {