diff options
Diffstat (limited to 'patches/mm_page_alloc__Explicitly_acquire_the_zone_lock_in___free_pages_ok.patch')
-rw-r--r-- | patches/mm_page_alloc__Explicitly_acquire_the_zone_lock_in___free_pages_ok.patch | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/patches/mm_page_alloc__Explicitly_acquire_the_zone_lock_in___free_pages_ok.patch b/patches/mm_page_alloc__Explicitly_acquire_the_zone_lock_in___free_pages_ok.patch new file mode 100644 index 000000000000..730320dc1268 --- /dev/null +++ b/patches/mm_page_alloc__Explicitly_acquire_the_zone_lock_in___free_pages_ok.patch @@ -0,0 +1,61 @@ +Subject: mm/page_alloc: Explicitly acquire the zone lock in __free_pages_ok +From: Mel Gorman <mgorman@techsingularity.net> +Date: Wed May 12 10:54:56 2021 +0100 + +From: Mel Gorman <mgorman@techsingularity.net> + +__free_pages_ok() disables IRQs before calling a common helper +free_one_page() that acquires the zone lock. This is not safe according +to Documentation/locking/locktypes.rst and in this context, IRQ disabling +is not protecting a per_cpu_pages structure either or a local_lock would +be used. + +This patch explicitly acquires the lock with spin_lock_irqsave instead of +relying on a helper. This removes the last instance of local_irq_save() +in page_alloc.c. + +Signed-off-by: Mel Gorman <mgorman@techsingularity.net> +Signed-off-by: Thomas Gleixner <tglx@linutronix.de> +Acked-by: Vlastimil Babka <vbabka@suse.cz> +Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> +Signed-off-by: Thomas Gleixner <tglx@linutronix.de> + + +--- + mm/page_alloc.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) +--- +diff --git a/mm/page_alloc.c b/mm/page_alloc.c +index 7892cbaf2e76..ef68d4e06837 100644 +--- a/mm/page_alloc.c ++++ b/mm/page_alloc.c +@@ -1579,21 +1579,21 @@ static void __free_pages_ok(struct page *page, unsigned int order, + unsigned long flags; + int migratetype; + unsigned long pfn = page_to_pfn(page); ++ struct zone *zone = page_zone(page); + + if (!free_pages_prepare(page, order, true, fpi_flags)) + return; + + migratetype = get_pfnblock_migratetype(page, pfn); + +- /* +- * TODO FIX: Disable IRQs before acquiring IRQ-safe zone->lock +- * and protect vmstat updates. +- */ +- local_irq_save(flags); ++ spin_lock_irqsave(&zone->lock, flags); + __count_vm_events(PGFREE, 1 << order); +- free_one_page(page_zone(page), page, pfn, order, migratetype, +- fpi_flags); +- local_irq_restore(flags); ++ if (unlikely(has_isolate_pageblock(zone) || ++ is_migrate_isolate(migratetype))) { ++ migratetype = get_pfnblock_migratetype(page, pfn); ++ } ++ __free_one_page(page, pfn, zone, order, migratetype, fpi_flags); ++ spin_unlock_irqrestore(&zone->lock, flags); + } + + void __free_pages_core(struct page *page, unsigned int order) |