summaryrefslogtreecommitdiff
path: root/patches/mm_page_alloc__Explicitly_acquire_the_zone_lock_in___free_pages_ok.patch
diff options
context:
space:
mode:
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.patch61
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)