On 4/14/21 3:39 PM, Mel Gorman wrote: > __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. \o/ > Signed-off-by: Mel Gorman <mgorman@xxxxxxxxxxxxxxxxxxx> Acked-by: Vlastimil Babka <vbabka@xxxxxxx> > --- > mm/page_alloc.c | 13 +++++-------- > 1 file changed, 5 insertions(+), 8 deletions(-) > > diff --git a/mm/page_alloc.c b/mm/page_alloc.c > index 1ed370668e7f..6791e9361076 100644 > --- a/mm/page_alloc.c > +++ b/mm/page_alloc.c > @@ -1559,21 +1559,18 @@ 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)) > 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); > + migratetype = check_migratetype_isolated(zone, page, pfn, migratetype); > + __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) >