Message ID | 20210414133931.4555-9-mgorman@techsingularity.net |
---|---|
State | New |
Headers | show |
Series | Use local_lock for pcp protection and reduce stat overhead | expand |
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@techsingularity.net> Acked-by: Vlastimil Babka <vbabka@suse.cz> > --- > 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) >
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)
__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> --- mm/page_alloc.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-)