mm: zone lock tracepoint instrumentation
Subsystems (12)
v4 cover mm: zone lock tracepoint instrumentation
Zone lock contention can significantly impact allocation and reclaim latency, as it is a central synchronization point in the page allocator and reclaim paths. Improved visibility into its behavior is therefore important for diagnosing performance issues in memory-intensive workloads.
On some production workloads at Meta, we have observed noticeable zone lock contention. Deeper analysis of lock holders and waiters is currently difficult with existing instrumentation.
While generic lock contention_begin/contention_end tracepoints cover the slow path, they do not provide sufficient visibility into lock hold times. In particular, the lack of a release-side event makes it difficult to identify long lock holders and correlate them with waiters. As a result, distinguishing between short bursts of contention and pathological long hold times requires additional instrumentation.
This patch series adds dedicated tracepoint instrumentation to zone lock, following the existing mmap_lock tracing model.
The goal is to enable detailed holder/waiter analysis and lock hold time measurements without affecting the fast path when tracing is disabled.
The series is structured as follows:
1. Introduce zone lock wrappers.
2. Mechanically convert zone lock users to the wrappers.
3. Convert compaction to use the wrappers (requires minor restructuring of compact_lock_irqsave()).
4. Rename zone->lock to zone->_lock.
5. Add zone lock tracepoints.
The tracepoints are added via lightweight inline helpers in the wrappers. When tracing is disabled, the fast path remains unchanged.
Changes in v4:
- Fix build errors in kernel/power/snapshot.c and mm/shuffle.c files.
- Remove EXPORT_SYMBOL().
- Rename header zone_lock.h to mmzone_lock.h.
- Properly indent __acquires() annotation.
Changes in v3:
- Split compact_lock_irqsave() to compact_zone_lock_irqsave() and compact_lruvec_lock_irqsave().
- Rename zone->lock to zone->_lock.
Changes in v2:
- Move mecanical changes from mm/compaction.c to different commit.
- Removed compact_do_zone_trylock() and compact_do_raw_trylock_irqsave().
v1: https://lore.kernel.org/all/[email protected]/
v2: https://lore.kernel.org/all/[email protected]/
v3: https://lore.kernel.org/all/[email protected]/
Dmitry Ilvokhin (5):
mm: introduce zone lock wrappers
mm: convert zone lock users to wrappers
mm: convert compaction to zone lock wrappers
mm: rename zone->lock to zone->_lock
mm: add tracepoints for zone lock
MAINTAINERS | 2 + include/linux/mmzone.h | 7 ++- include/linux/mmzone_lock.h | 100 +++++++++++++++++++++++++++++++ include/trace/events/zone_lock.h | 64 ++++++++++++++++++++ kernel/power/snapshot.c | 5 +- mm/Makefile | 2 +- mm/compaction.c | 58 +++++++++++------- mm/internal.h | 2 +- mm/memory_hotplug.c | 9 +-- mm/mm_init.c | 3 +- mm/page_alloc.c | 89 +++++++++++++-------------- mm/page_isolation.c | 23 +++---- mm/page_owner.c | 2 +- mm/page_reporting.c | 13 ++-- mm/show_mem.c | 5 +- mm/shuffle.c | 9 +-- mm/vmscan.c | 5 +- mm/vmstat.c | 9 +-- mm/zone_lock.c | 28 +++++++++ 19 files changed, 330 insertions(+), 105 deletions(-) create mode 100644 include/linux/mmzone_lock.h create mode 100644 include/trace/events/zone_lock.h create mode 100644 mm/zone_lock.c
Signature · 1 line
2.47.3
PATCH v4 1/5 mm: introduce zone lock wrappers
Add thin wrappers around zone lock acquire/release operations. This prepares the code for future tracepoint instrumentation without modifying individual call sites.
Centralizing zone lock operations behind wrappers allows future instrumentation or debugging hooks to be added without touching all users.
No functional change intended. The wrappers are introduced in preparation for subsequent patches and are not yet used.
--- MAINTAINERS | 1 + include/linux/mmzone_lock.h | 38 +++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 include/linux/mmzone_lock.h
MAINTAINERS +1 -0
@@ -16672,6 +16672,7 @@ F: include/linux/memory.h F: include/linux/mm.h F: include/linux/mm_*.h F: include/linux/mmzone.h +F: include/linux/mmzone_lock.h F: include/linux/mmdebug.h F: include/linux/mmu_notifier.h F: include/linux/pagewalk.h
include/linux/mmzone_lock.h new file +38 -0
@@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LINUX_MMZONE_LOCK_H +#define _LINUX_MMZONE_LOCK_H + +#include <linux/mmzone.h> +#include <linux/spinlock.h> + +static inline void zone_lock_init (struct zone *zone) +{ +spin_lock_init (&zone->lock); +} + +#define zone_lock_irqsave (zone, flags) \ +do { \ + spin_lock_irqsave(&(zone)->lock, flags); \ +} while (0) + +#define zone_trylock_irqsave (zone, flags) \ +({ \ + spin_trylock_irqsave(&(zone)->lock, flags); \ +}) + +static inline void zone_unlock_irqrestore (struct zone *zone,unsigned long flags) +{ +spin_unlock_irqrestore (&zone->lock, flags); +} + +static inline void zone_lock_irq (struct zone *zone) +{ +spin_lock_irq (&zone->lock); +} + +static inline void zone_unlock_irq (struct zone *zone) +{ +spin_unlock_irq (&zone->lock); +} + +#endif /* _LINUX_MMZONE_LOCK_H */
Signature · 1 line
2.47.3
Re: [PATCH v4 1/5] mm: introduce zone lock wrappers
Quoted 8 lines · Dmitry Ilvokhin
Add thin wrappers around zone lock acquire/release operations. This prepares the code for future tracepoint instrumentation without modifying individual call sites.
Centralizing zone lock operations behind wrappers allows future instrumentation or debugging hooks to be added without touching all users.
Quoted 6 lines
No functional change intended. The wrappers are introduced in preparation for subsequent patches and are not yet used.
Signed-off-by Dmitry Ilvokhin <[email protected]>Acked-by Shakeel Butt <[email protected]>---
Signature · 3 lines
Cheers, David
Re: [PATCH v4 1/5] mm: introduce zone lock wrappers
In reply to Dmitry IlvokhinQuoted 11 lines · Dmitry Ilvokhin
Add thin wrappers around zone lock acquire/release operations. This prepares the code for future tracepoint instrumentation without modifying individual call sites.
Centralizing zone lock operations behind wrappers allows future instrumentation or debugging hooks to be added without touching all users.
No functional change intended. The wrappers are introduced in preparation for subsequent patches and are not yet used.
Quoted 8 lines
Signed-off-by Dmitry Ilvokhin <[email protected]>Acked-by Shakeel Butt <[email protected]>--- MAINTAINERS | 1 + include/linux/mmzone_lock.h | 38 +++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 include/linux/mmzone_lock.h
Best Regards,
Yan, Zi
Re: [PATCH v4 1/5] mm: introduce zone lock wrappers
In reply to Dmitry IlvokhinQuoted 8 lines · On Fri, 27 Feb 2026 16:00:23 +0000 Dmitry Ilvokhin <[email protected]> wrote:
Add thin wrappers around zone lock acquire/release operations. This prepares the code for future tracepoint instrumentation without modifying individual call sites.
Centralizing zone lock operations behind wrappers allows future instrumentation or debugging hooks to be added without touching all users.
Quoted 5 lines
No functional change intended. The wrappers are introduced in preparation for subsequent patches and are not yet used.
Signed-off-by Dmitry Ilvokhin <[email protected]>Acked-by Shakeel Butt <[email protected]>
Thanks,
SJ
[...]
Re: [PATCH v4 1/5] mm: introduce zone lock wrappers
In reply to Dmitry IlvokhinQuoted 8 lines · Dmitry Ilvokhin
Add thin wrappers around zone lock acquire/release operations. This prepares the code for future tracepoint instrumentation without modifying individual call sites.
Centralizing zone lock operations behind wrappers allows future instrumentation or debugging hooks to be added without touching all users.
Quoted 5 lines
No functional change intended. The wrappers are introduced in preparation for subsequent patches and are not yet used.
Signed-off-by Dmitry Ilvokhin <[email protected]>Acked-by Shakeel Butt <[email protected]>
*checks patch 2 diffstat*
I think we could do it as mm/zone_lock.h even and not pollute include/linux/ Even kernel/power/snapshot.c could include it in a somewhat ugly way. However we should also later look at moving that particular code somewhere under mm/ really...
Anyway,
Quoted 62 lines
--- MAINTAINERS | 1 + include/linux/mmzone_lock.h | 38 +++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 include/linux/mmzone_lock.hMAINTAINERS +1
-0@@ -16672,6 +16672,7 @@ F: include/linux/memory.h F: include/linux/mm.h F: include/linux/mm_*.h F: include/linux/mmzone.h +F: include/linux/mmzone_lock.h F: include/linux/mmdebug.h F: include/linux/mmu_notifier.h F: include/linux/pagewalk.hinclude/linux/mmzone_lock.h new file +38
-0@@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LINUX_MMZONE_LOCK_H +#define _LINUX_MMZONE_LOCK_H + +#include <linux/mmzone.h> +#include <linux/spinlock.h> + +static inline void zone_lock_init (struct zone *zone) +{ +spin_lock_init (&zone->lock); +} + +#define zone_lock_irqsave (zone, flags) \ +do { \ + spin_lock_irqsave(&(zone)->lock, flags); \ +} while (0) + +#define zone_trylock_irqsave (zone, flags) \ +({ \ + spin_trylock_irqsave(&(zone)->lock, flags); \ +}) + +static inline void zone_unlock_irqrestore (struct zone *zone,unsigned long flags) +{ +spin_unlock_irqrestore (&zone->lock, flags); +} + +static inline void zone_lock_irq (struct zone *zone) +{ +spin_lock_irq (&zone->lock); +} + +static inline void zone_unlock_irq (struct zone *zone) +{ +spin_unlock_irq (&zone->lock); +} + +#endif /* _LINUX_MMZONE_LOCK_H */
PATCH v4 2/5 mm: convert zone lock users to wrappers
In reply to Dmitry IlvokhinReplace direct zone lock acquire/release operations with the newly introduced wrappers.
The changes are purely mechanical substitutions. No functional change intended. Locking semantics and ordering remain unchanged.
The compaction path is left unchanged for now and will be handled separately in the following patch due to additional non-trivial modifications.
--- kernel/power/snapshot.c | 5 +-- mm/compaction.c | 25 +++++++------- mm/memory_hotplug.c | 9 ++--- mm/mm_init.c | 3 +- mm/page_alloc.c | 73 +++++++++++++++++++++-------------------- mm/page_isolation.c | 19 ++++++----- mm/page_reporting.c | 13 ++++---- mm/show_mem.c | 5 +-- mm/shuffle.c | 9 ++--- mm/vmscan.c | 5 +-- mm/vmstat.c | 9 ++--- 11 files changed, 94 insertions(+), 81 deletions(-)
kernel/power/snapshot.c +3 -2
@@ -13,6 +13,7 @@#include <linux/version.h> #include <linux/module.h> #include <linux/mm.h> +#include <linux/mmzone_lock.h> #include <linux/suspend.h> #include <linux/delay.h> #include <linux/bitops.h>
@@ -1251,7 +1252,7 @@ static void mark_free_pages(struct zone *zone)if (zone_is_empty (zone))return ; -spin_lock_irqsave (&zone->lock, flags); +zone_lock_irqsave (zone, flags); max_zone_pfn =zone_end_pfn (zone);for_each_valid_pfn (pfn, zone->zone_start_pfn, max_zone_pfn) {
@@ -1284,7 +1285,7 @@ static void mark_free_pages(struct zone *zone) } } } -spin_unlock_irqrestore (&zone->lock, flags); +zone_unlock_irqrestore (zone, flags); }#ifdef CONFIG_HIGHMEM
mm/compaction.c +14 -11
@@ -24,6 +24,7 @@#include <linux/page_owner.h> #include <linux/psi.h> #include <linux/cpuset.h> +#include <linux/mmzone_lock.h> #include "internal.h" #ifdef CONFIG_COMPACTION
@@ -530,11 +531,14 @@ static bool compact_lock_irqsave(spinlock_t *lock, unsigned long *flags,* Returns true if compaction should abort due to fatal signal pending. * Returns false when compaction can continue. */ -static bool compact_unlock_should_abort (spinlock_t *lock, -unsigned long flags,bool *locked,struct compact_control *cc) + +static bool compact_unlock_should_abort (struct zone *zone, +unsigned long flags, +bool *locked, +struct compact_control *cc) {if (*locked) { -spin_unlock_irqrestore (lock, flags); +zone_unlock_irqrestore (zone, flags); *locked = false; }
@@ -582,9 +586,8 @@ static unsigned long isolate_freepages_block(struct compact_control *cc,* contention, to give chance to IRQs. Abort if fatal signal * pending. */ -if (!(blockpfn %COMPACT_CLUSTER_MAX ) - &&compact_unlock_should_abort (&cc->zone->lock, flags, - &locked, cc)) +if (!(blockpfn %COMPACT_CLUSTER_MAX ) && +compact_unlock_should_abort (cc->zone, flags, &locked, cc))break ; nr_scanned++;
@@ -649,7 +652,7 @@ static unsigned long isolate_freepages_block(struct compact_control *cc, }if (locked) -spin_unlock_irqrestore (&cc->zone->lock, flags); +zone_unlock_irqrestore (cc->zone, flags);/* * Be careful to not go outside of the pageblock.
@@ -1555,7 +1558,7 @@ static void fast_isolate_freepages(struct compact_control *cc)if (!area->nr_free)continue ; -spin_lock_irqsave (&cc->zone->lock, flags); +zone_lock_irqsave (cc->zone, flags); freelist = &area->free_list[MIGRATE_MOVABLE ];list_for_each_entry_reverse (freepage, freelist, buddy_list) {unsigned long pfn;
@@ -1614,7 +1617,7 @@ static void fast_isolate_freepages(struct compact_control *cc) } } -spin_unlock_irqrestore (&cc->zone->lock, flags); +zone_unlock_irqrestore (cc->zone, flags);/* Skip fast search if enough freepages isolated */ if (cc->nr_freepages >= cc->nr_migratepages)
@@ -1988,7 +1991,7 @@ static unsigned long fast_find_migrateblock(struct compact_control *cc)if (!area->nr_free)continue ; -spin_lock_irqsave (&cc->zone->lock, flags); +zone_lock_irqsave (cc->zone, flags); freelist = &area->free_list[MIGRATE_MOVABLE ];list_for_each_entry (freepage, freelist, buddy_list) {unsigned long free_pfn;
@@ -2021,7 +2024,7 @@ static unsigned long fast_find_migrateblock(struct compact_control *cc)break ; } } -spin_unlock_irqrestore (&cc->zone->lock, flags); +zone_unlock_irqrestore (cc->zone, flags); } cc->total_migrate_scanned += nr_scanned;
mm/memory_hotplug.c +5 -4
@@ -36,6 +36,7 @@#include <linux/rmap.h> #include <linux/module.h> #include <linux/node.h> +#include <linux/mmzone_lock.h> #include <asm/tlbflush.h>
@@ -1190,9 +1191,9 @@ int online_pages(unsigned long pfn, unsigned long nr_pages,* Fixup the number of isolated pageblocks before marking the sections * onlining, such that undo_isolate_page_range() works correctly. */ -spin_lock_irqsave (&zone->lock, flags); +zone_lock_irqsave (zone, flags); zone->nr_isolate_pageblock += nr_pages / pageblock_nr_pages; -spin_unlock_irqrestore (&zone->lock, flags); +zone_unlock_irqrestore (zone, flags);/* * If this zone is not populated, then it is not in zonelist.
@@ -2041,9 +2042,9 @@ int offline_pages(unsigned long start_pfn, unsigned long nr_pages,* effectively stale; nobody should be touching them. Fixup the number * of isolated pageblocks, memory onlining will properly revert this. */ -spin_lock_irqsave (&zone->lock, flags); +zone_lock_irqsave (zone, flags); zone->nr_isolate_pageblock -= nr_pages / pageblock_nr_pages; -spin_unlock_irqrestore (&zone->lock, flags); +zone_unlock_irqrestore (zone, flags);lru_cache_enable ();zone_pcp_enable (zone);
mm/mm_init.c +2 -1
@@ -32,6 +32,7 @@#include <linux/vmstat.h> #include <linux/kexec_handover.h> #include <linux/hugetlb.h> +#include <linux/mmzone_lock.h> #include "internal.h" #include "slab.h" #include "shuffle.h"
@@ -1425,7 +1426,7 @@ static void __meminit zone_init_internals(struct zone *zone, enum zone_type idx,zone_set_nid (zone, nid); zone->name = zone_names[idx]; zone->zone_pgdat =NODE_DATA (nid); -spin_lock_init (&zone->lock); +zone_lock_init (zone);zone_seqlock_init (zone);zone_pcp_init (zone); }
mm/page_alloc.c +37 -36
266 lines not on this page · raw message
mm/page_isolation.c +10 -9
@@ -10,6 +10,7 @@#include <linux/hugetlb.h> #include <linux/page_owner.h> #include <linux/migrate.h> +#include <linux/mmzone_lock.h> #include "internal.h" #define CREATE_TRACE_POINTS
@@ -173,7 +174,7 @@ static int set_migratetype_isolate(struct page *page, enum pb_isolate_mode mode,if (PageUnaccepted (page))accept_page (page); -spin_lock_irqsave (&zone->lock, flags); +zone_lock_irqsave (zone, flags);/* * We assume the caller intended to SET migrate type to isolate.
@@ -181,7 +182,7 @@ static int set_migratetype_isolate(struct page *page, enum pb_isolate_mode mode,* set it before us. */ if (is_migrate_isolate_page (page)) { -spin_unlock_irqrestore (&zone->lock, flags); +zone_unlock_irqrestore (zone, flags);return -EBUSY ; }
@@ -200,15 +201,15 @@ static int set_migratetype_isolate(struct page *page, enum pb_isolate_mode mode, mode);if (!unmovable) {if (!pageblock_isolate_and_move_free_pages (zone, page)) { -spin_unlock_irqrestore (&zone->lock, flags); +zone_unlock_irqrestore (zone, flags);return -EBUSY ; } zone->nr_isolate_pageblock++; -spin_unlock_irqrestore (&zone->lock, flags); +zone_unlock_irqrestore (zone, flags);return 0 ; } -spin_unlock_irqrestore (&zone->lock, flags); +zone_unlock_irqrestore (zone, flags);if (mode ==PB_ISOLATE_MODE_MEM_OFFLINE ) {/* * printk() with zone->lock held will likely trigger a
@@ -229,7 +230,7 @@ static void unset_migratetype_isolate(struct page *page)struct page *buddy; zone =page_zone (page); -spin_lock_irqsave (&zone->lock, flags); +zone_lock_irqsave (zone, flags);if (!is_migrate_isolate_page (page)) goto out;
@@ -280,7 +281,7 @@ static void unset_migratetype_isolate(struct page *page) } zone->nr_isolate_pageblock--; out: -spin_unlock_irqrestore (&zone->lock, flags); +zone_unlock_irqrestore (zone, flags); } static inline struct page *
@@ -641,9 +642,9 @@ int test_pages_isolated(unsigned long start_pfn, unsigned long end_pfn,/* Check all pages are free or marked as ISOLATED */ zone =page_zone (page); -spin_lock_irqsave (&zone->lock, flags); +zone_lock_irqsave (zone, flags); pfn =__test_page_isolated_in_pageblock (start_pfn, end_pfn, mode); -spin_unlock_irqrestore (&zone->lock, flags); +zone_unlock_irqrestore (zone, flags); ret = pfn < end_pfn ? -EBUSY :0 ;
mm/page_reporting.c +7 -6
@@ -1,6 +1,7 @@// SPDX-License-Identifier: GPL-2.0 #include <linux/mm.h> #include <linux/mmzone.h> +#include <linux/mmzone_lock.h> #include <linux/page_reporting.h> #include <linux/gfp.h> #include <linux/export.h>
@@ -161,7 +162,7 @@ page_reporting_cycle(struct page_reporting_dev_info *prdev, struct zone *zone,if (list_empty (list))return err; -spin_lock_irq (&zone->lock); +zone_lock_irq (zone);/* * Limit how many calls we will be making to the page reporting
@@ -219,7 +220,7 @@ page_reporting_cycle(struct page_reporting_dev_info *prdev, struct zone *zone,list_rotate_to_front (&page->lru, list);/* release lock before waiting on report processing */ -spin_unlock_irq (&zone->lock); +zone_unlock_irq (zone);/* begin processing pages in local list */ err = prdev->report (prdev, sgl,PAGE_REPORTING_CAPACITY );
@@ -231,7 +232,7 @@ page_reporting_cycle(struct page_reporting_dev_info *prdev, struct zone *zone, budget--;/* reacquire zone lock and resume processing */ -spin_lock_irq (&zone->lock); +zone_lock_irq (zone);/* flush reported pages from the sg list */ page_reporting_drain (prdev, sgl,PAGE_REPORTING_CAPACITY , !err);
@@ -251,7 +252,7 @@ page_reporting_cycle(struct page_reporting_dev_info *prdev, struct zone *zone,if (!list_entry_is_head (next, list, lru) && !list_is_first (&next->lru, list))list_rotate_to_front (&next->lru, list); -spin_unlock_irq (&zone->lock); +zone_unlock_irq (zone);return err; }
@@ -296,9 +297,9 @@ page_reporting_process_zone(struct page_reporting_dev_info *prdev, err = prdev->report (prdev, sgl, leftover);/* flush any remaining pages out from the last report */ -spin_lock_irq (&zone->lock); +zone_lock_irq (zone);page_reporting_drain (prdev, sgl, leftover, !err); -spin_unlock_irq (&zone->lock); +zone_unlock_irq (zone); }return err;
mm/show_mem.c +3 -2
@@ -12,6 +12,7 @@#include <linux/hugetlb.h> #include <linux/mm.h> #include <linux/mmzone.h> +#include <linux/mmzone_lock.h> #include <linux/swap.h> #include <linux/vmstat.h>
@@ -363,7 +364,7 @@ static void show_free_areas(unsigned int filter, nodemask_t *nodemask, int max_zshow_node (zone);printk (KERN_CONT "%s: " , zone->name); -spin_lock_irqsave (&zone->lock, flags); +zone_lock_irqsave (zone, flags);for (order =0 ; order <NR_PAGE_ORDERS ; order++) {struct free_area *area = &zone->free_area[order];int type;
@@ -377,7 +378,7 @@ static void show_free_areas(unsigned int filter, nodemask_t *nodemask, int max_z types[order] |=1 << type; } } -spin_unlock_irqrestore (&zone->lock, flags); +zone_unlock_irqrestore (zone, flags);for (order =0 ; order <NR_PAGE_ORDERS ; order++) {printk (KERN_CONT "%lu*%lukB " , nr[order],K (1UL ) << order);
mm/shuffle.c +5 -4
@@ -4,6 +4,7 @@#include <linux/mm.h> #include <linux/init.h> #include <linux/mmzone.h> +#include <linux/mmzone_lock.h> #include <linux/random.h> #include <linux/moduleparam.h> #include "internal.h"
@@ -85,7 +86,7 @@ void __meminit __shuffle_zone(struct zone *z)const int order =SHUFFLE_ORDER ;const int order_pages =1 << order; -spin_lock_irqsave (&z->lock, flags); +zone_lock_irqsave (z, flags); start_pfn =ALIGN (start_pfn, order_pages);for (i = start_pfn; i < end_pfn; i += order_pages) {unsigned long j;
@@ -138,12 +139,12 @@ void __meminit __shuffle_zone(struct zone *z)/* take it easy on the zone lock */ if ((i % (100 * order_pages)) ==0 ) { -spin_unlock_irqrestore (&z->lock, flags); +zone_unlock_irqrestore (z, flags);cond_resched (); -spin_lock_irqsave (&z->lock, flags); +zone_lock_irqsave (z, flags); } } -spin_unlock_irqrestore (&z->lock, flags); +zone_unlock_irqrestore (z, flags); }/*
mm/vmscan.c +3 -2
@@ -58,6 +58,7 @@#include <linux/random.h> #include <linux/mmu_notifier.h> #include <linux/parser.h> +#include <linux/mmzone_lock.h> #include <asm/tlbflush.h> #include <asm/div64.h>
@@ -7139,9 +7140,9 @@ static int balance_pgdat(pg_data_t *pgdat, int order, int highest_zoneidx)/* Increments are under the zone lock */ zone = pgdat->node_zones + i; -spin_lock_irqsave (&zone->lock, flags); +zone_lock_irqsave (zone, flags); zone->watermark_boost -=min (zone->watermark_boost, zone_boosts[i]); -spin_unlock_irqrestore (&zone->lock, flags); +zone_unlock_irqrestore (zone, flags); }/*
mm/vmstat.c +5 -4
@@ -28,6 +28,7 @@#include <linux/mm_inline.h> #include <linux/page_owner.h> #include <linux/sched/isolation.h> +#include <linux/mmzone_lock.h> #include "internal.h"
@@ -1535,10 +1536,10 @@ static void walk_zones_in_node(struct seq_file *m, pg_data_t *pgdat,continue ;if (!nolock) -spin_lock_irqsave (&zone->lock, flags); +zone_lock_irqsave (zone, flags);if (!nolock) - spin_unlock_irqrestore(&zone->lock, flags); + zone_unlock_irqrestore(zone, flags); } }#endif
@@ -1603,9 +1604,9 @@ static void pagetypeinfo_showfree_print(struct seq_file *m, } }seq_printf (m,"%s%6lu " , overflow ?">" :"" , freecount); -spin_unlock_irq (&zone->lock); +zone_unlock_irq (zone);cond_resched (); -spin_lock_irq (&zone->lock); +zone_lock_irq (zone); }seq_putc (m,'\n' ); }
Signature · 1 line
2.47.3
Re: [PATCH v4 2/5] mm: convert zone lock users to wrappers
Quoted 14 lines · Dmitry Ilvokhin
Replace direct zone lock acquire/release operations with the newly introduced wrappers.
The changes are purely mechanical substitutions. No functional change intended. Locking semantics and ordering remain unchanged.
The compaction path is left unchanged for now and will be handled separately in the following patch due to additional non-trivial modifications.
Signed-off-by Dmitry Ilvokhin <[email protected]>Acked-by Shakeel Butt <[email protected]>Reviewed-by SeongJae Park <[email protected]>---
[...]
mm/compaction.c static bool compact_lock_irqsave(spinlock_t *lock, unsigned long *flags, · line 538
Quoted 12 lines
#ifdef
CONFIG_COMPACTIONmm/compaction.c +5
-2@@ -530,11 +531,14 @@ static bool compact_lock_irqsave(spinlock_t *lock, unsigned long *flags,* Returns true if compaction should abort due to fatal signal pending. * Returns false when compaction can continue. */ -static bool compact_unlock_should_abort (spinlock_t *lock, -unsigned long flags,bool *locked,struct compact_control *cc) + +static bool compact_unlock_should_abort (struct zone *zone, +unsigned long flags, +bool *locked, +struct compact_control *cc)
We tend to use two-tabs on second parameter line; like the existing code did.
Besides that
Signature · 3 lines
Cheers, David
Re: [PATCH v4 2/5] mm: convert zone lock users to wrappers
Quoted 35 lines · David Hildenbrand (Arm)
Quoted 14 lines · Dmitry Ilvokhin
Replace direct zone lock acquire/release operations with the newly introduced wrappers.
The changes are purely mechanical substitutions. No functional change intended. Locking semantics and ordering remain unchanged.
The compaction path is left unchanged for now and will be handled separately in the following patch due to additional non-trivial modifications.
Signed-off-by Dmitry Ilvokhin <[email protected]>Acked-by Shakeel Butt <[email protected]>Reviewed-by SeongJae Park <[email protected]>---
[...]
mm/compaction.c static bool compact_lock_irqsave(spinlock_t *lock, unsigned long *flags, · line 538
Quoted 12 lines
#ifdef
CONFIG_COMPACTIONmm/compaction.c +5
-2@@ -530,11 +531,14 @@ static bool compact_lock_irqsave(spinlock_t *lock, unsigned long *flags,* Returns true if compaction should abort due to fatal signal pending. * Returns false when compaction can continue. */ -static bool compact_unlock_should_abort (spinlock_t *lock, -unsigned long flags,bool *locked,struct compact_control *cc) + +static bool compact_unlock_should_abort (struct zone *zone, +unsigned long flags, +bool *locked, +struct compact_control *cc)We tend to use two-tabs on second parameter line; like the existing code did.
Quoted 4 lines
Besides that
Thanks, David. Noted. Appreciate the review and ack.
Quoted 4 lines
Signature · 3 lines
Cheers, David
Re: [PATCH v4 2/5] mm: convert zone lock users to wrappers
In reply to Dmitry IlvokhinQuoted 13 lines · Dmitry Ilvokhin
Replace direct zone lock acquire/release operations with the newly introduced wrappers.
The changes are purely mechanical substitutions. No functional change intended. Locking semantics and ordering remain unchanged.
The compaction path is left unchanged for now and will be handled separately in the following patch due to additional non-trivial modifications.
Signed-off-by Dmitry Ilvokhin <[email protected]>Acked-by Shakeel Butt <[email protected]>Reviewed-by SeongJae Park <[email protected]>
Quoted 14 lines
--- kernel/power/snapshot.c | 5 +-- mm/compaction.c | 25 +++++++------- mm/memory_hotplug.c | 9 ++--- mm/mm_init.c | 3 +- mm/page_alloc.c | 73 +++++++++++++++++++++-------------------- mm/page_isolation.c | 19 ++++++----- mm/page_reporting.c | 13 ++++---- mm/show_mem.c | 5 +-- mm/shuffle.c | 9 ++--- mm/vmscan.c | 5 +-- mm/vmstat.c | 9 ++--- 11 files changed, 94 insertions(+), 81 deletions(-)
Best Regards,
Yan, Zi
Re: [PATCH v4 2/5] mm: convert zone lock users to wrappers
In reply to Dmitry IlvokhinQuoted 6 lines · Dmitry Ilvokhin
Replace direct zone lock acquire/release operations with the newly introduced wrappers.
The changes are purely mechanical substitutions. No functional change intended. Locking semantics and ordering remain unchanged.
Quoted 7 lines
The compaction path is left unchanged for now and will be handled separately in the following patch due to additional non-trivial modifications.
Signed-off-by Dmitry Ilvokhin <[email protected]>Acked-by Shakeel Butt <[email protected]>Reviewed-by SeongJae Park <[email protected]>
PATCH v4 3/5 mm: convert compaction to zone lock wrappers
In reply to Dmitry IlvokhinCompaction uses compact_lock_irqsave(), which currently operates on a raw spinlock_t pointer so it can be used for both zone->lock and lruvec->lru_lock. Since zone lock operations are now wrapped, compact_lock_irqsave() can no longer directly operate on a spinlock_t when the lock belongs to a zone.
Split the helper into compact_zone_lock_irqsave() and compact_lruvec_lock_irqsave(), duplicating the small amount of shared logic. As there are only two call sites and both statically know the lock type, this avoids introducing additional abstraction or runtime dispatch in the compaction path.
No functional change intended.
--- mm/compaction.c | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-)
mm/compaction.c +24 -9
@@ -503,19 +503,36 @@ static bool test_and_set_skip(struct compact_control *cc, struct page *page)* * Always returns true which makes it easier to track lock state in callers. */ -static bool compact_lock_irqsave (spinlock_t *lock,unsigned long *flags, -struct compact_control *cc) -__acquires (lock) +static bool compact_zone_lock_irqsave (struct zone *zone, +unsigned long *flags, +struct compact_control *cc) + __acquires(&zone->lock) {/* Track if the lock is contended in async mode */ if (cc->mode ==MIGRATE_ASYNC && !cc->contended) { -if (spin_trylock_irqsave (lock, *flags)) +if (zone_trylock_irqsave (zone, *flags))return true; cc->contended = true; } -spin_lock_irqsave (lock, *flags); +zone_lock_irqsave (zone, *flags); +return true; +} + +static bool compact_lruvec_lock_irqsave (struct lruvec *lruvec, +unsigned long *flags, +struct compact_control *cc) + __acquires(&lruvec->lru_lock) +{ +if (cc->mode ==MIGRATE_ASYNC && !cc->contended) { +if (spin_trylock_irqsave (&lruvec->lru_lock, *flags)) +return true; + + cc->contended = true; + } + +spin_lock_irqsave (&lruvec->lru_lock, *flags);return true; }
@@ -531,7 +548,6 @@ static bool compact_lock_irqsave(spinlock_t *lock, unsigned long *flags,* Returns true if compaction should abort due to fatal signal pending. * Returns false when compaction can continue. */ - static bool compact_unlock_should_abort(struct zone *zone, unsigned long flags, bool *locked,
@@ -616,8 +632,7 @@ static unsigned long isolate_freepages_block(struct compact_control *cc,/* If we already hold the lock, we can skip some rechecking. */ if (!locked) { - locked =compact_lock_irqsave (&cc->zone->lock, - &flags, cc); + locked =compact_zone_lock_irqsave (cc->zone, &flags, cc);/* Recheck this is a buddy page under lock */ if (!PageBuddy (page))
@@ -1163,7 +1178,7 @@ isolate_migratepages_block(struct compact_control *cc, unsigned long low_pfn,if (locked)unlock_page_lruvec_irqrestore (locked, flags); -compact_lock_irqsave (&lruvec->lru_lock, &flags, cc); +compact_lruvec_lock_irqsave (lruvec, &flags, cc); locked = lruvec;lruvec_memcg_debug (lruvec, folio);
Signature · 1 line
2.47.3
Re: [PATCH v4 3/5] mm: convert compaction to zone lock wrappers
Quoted 25 lines · Dmitry Ilvokhin
Compaction uses
compact_lock_irqsave(), which currently operates on a rawspinlock_tpointer so it can be used for bothzone->lockandlruvec->lru_lock. Since zone lock operations are now wrapped,compact_lock_irqsave()can no longer directly operate on aspinlock_twhen the lock belongs to a zone.Split the helper into
compact_zone_lock_irqsave()andcompact_lruvec_lock_irqsave(), duplicating the small amount of shared logic. As there are only two call sites and both statically know the lock type, this avoids introducing additional abstraction or runtime dispatch in the compaction path.No functional change intended.
Signed-off-by Dmitry Ilvokhin <[email protected]>Acked-by Shakeel Butt <[email protected]>--- mm/compaction.c | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-)mm/compaction.c +0
-0
mm/compaction.c static bool test_and_set_skip(struct compact_control *cc, struct page *page) · line 508
Quoted 9 lines
mm/compaction.c +3
-3@@ -503,19 +503,36 @@ static bool test_and_set_skip(struct compact_control *cc, struct page *page)* * Always returns true which makes it easier to track lock state in callers. */ -static bool compact_lock_irqsave(spinlock_t *lock, unsigned long *flags, - struct compact_control *cc) - __acquires(lock) +static bool compact_zone_lock_irqsave (struct zone *zone, +unsigned long *flags, +struct compact_control *cc)
... two tabs :)
Signature · 3 lines
Cheers, David
Re: [PATCH v4 3/5] mm: convert compaction to zone lock wrappers
In reply to Dmitry IlvokhinQuoted 12 lines · Dmitry Ilvokhin
Compaction uses
compact_lock_irqsave(), which currently operates on a rawspinlock_tpointer so it can be used for bothzone->lockandlruvec->lru_lock. Since zone lock operations are now wrapped,compact_lock_irqsave()can no longer directly operate on aspinlock_twhen the lock belongs to a zone.Split the helper into
compact_zone_lock_irqsave()andcompact_lruvec_lock_irqsave(), duplicating the small amount of shared logic. As there are only two call sites and both statically know the lock type, this avoids introducing additional abstraction or runtime dispatch in the compaction path.
Quoted 8 lines
No functional change intended.
Signed-off-by Dmitry Ilvokhin <[email protected]>Acked-by Shakeel Butt <[email protected]>--- mm/compaction.c | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-)
Best Regards,
Yan, Zi
Re: [PATCH v4 3/5] mm: convert compaction to zone lock wrappers
In reply to Dmitry IlvokhinQuoted 12 lines · On Fri, 27 Feb 2026 16:00:25 +0000 Dmitry Ilvokhin <[email protected]> wrote:
Compaction uses
compact_lock_irqsave(), which currently operates on a rawspinlock_tpointer so it can be used for bothzone->lockandlruvec->lru_lock. Since zone lock operations are now wrapped,compact_lock_irqsave()can no longer directly operate on aspinlock_twhen the lock belongs to a zone.Split the helper into
compact_zone_lock_irqsave()andcompact_lruvec_lock_irqsave(), duplicating the small amount of shared logic. As there are only two call sites and both statically know the lock type, this avoids introducing additional abstraction or runtime dispatch in the compaction path.
Quoted 4 lines
No functional change intended.
Signed-off-by Dmitry Ilvokhin <[email protected]>Acked-by Shakeel Butt <[email protected]>
Thanks,
SJ
[...]
Re: [PATCH v4 3/5] mm: convert compaction to zone lock wrappers
In reply to Dmitry IlvokhinQuoted 12 lines · Dmitry Ilvokhin
Compaction uses
compact_lock_irqsave(), which currently operates on a rawspinlock_tpointer so it can be used for bothzone->lockandlruvec->lru_lock. Since zone lock operations are now wrapped,compact_lock_irqsave()can no longer directly operate on aspinlock_twhen the lock belongs to a zone.Split the helper into
compact_zone_lock_irqsave()andcompact_lruvec_lock_irqsave(), duplicating the small amount of shared logic. As there are only two call sites and both statically know the lock type, this avoids introducing additional abstraction or runtime dispatch in the compaction path.
Quoted 4 lines
No functional change intended.
Signed-off-by Dmitry Ilvokhin <[email protected]>Acked-by Shakeel Butt <[email protected]>
PATCH v4 4/5 mm: rename zone->lock to zone->_lock
In reply to Dmitry IlvokhinThis intentionally breaks direct users of zone->lock at compile time so all call sites are converted to the zone lock wrappers. Without the rename, present and future out-of-tree code could continue using spin_lock(&zone->lock) and bypass the wrappers and tracing infrastructure.
No functional change intended.
--- include/linux/mmzone.h | 7 +++++-- include/linux/mmzone_lock.h | 12 ++++++------ mm/compaction.c | 4 ++-- mm/internal.h | 2 +- mm/page_alloc.c | 16 ++++++++-------- mm/page_isolation.c | 4 ++-- mm/page_owner.c | 2 +- 7 files changed, 25 insertions(+), 22 deletions(-)
include/linux/mmzone.h +5 -2
@@ -1009,8 +1009,11 @@ struct zone {/* zone flags, see below */ unsigned long flags; -/* Primarily protects free_area */ -spinlock_t lock; +/* +* Primarily protects free_area. Should be accessed via zone_lock_* +* helpers. +*/ +spinlock_t _lock;/* Pages to be freed when next trylock succeeds */ struct llist_head trylock_free_pages;
include/linux/mmzone_lock.h +6 -6
@@ -7,32 +7,32 @@static inline void zone_lock_init (struct zone *zone) { -spin_lock_init (&zone->lock); +spin_lock_init (&zone->_lock); }#define zone_lock_irqsave (zone, flags) \ do { \ - spin_lock_irqsave(&(zone)->lock, flags); \ + spin_lock_irqsave(&(zone)->_lock, flags); \ } while (0)#define zone_trylock_irqsave (zone, flags) \ ({ \ - spin_trylock_irqsave(&(zone)->lock, flags); \ + spin_trylock_irqsave(&(zone)->_lock, flags); \ })static inline void zone_unlock_irqrestore (struct zone *zone,unsigned long flags) { -spin_unlock_irqrestore (&zone->lock, flags); +spin_unlock_irqrestore (&zone->_lock, flags); }static inline void zone_lock_irq (struct zone *zone) { -spin_lock_irq (&zone->lock); +spin_lock_irq (&zone->_lock); }static inline void zone_unlock_irq (struct zone *zone) { -spin_unlock_irq (&zone->lock); +spin_unlock_irq (&zone->_lock); }#endif /* _LINUX_MMZONE_LOCK_H */
mm/compaction.c +2 -2
@@ -506,7 +506,7 @@ static bool test_and_set_skip(struct compact_control *cc, struct page *page)static bool compact_zone_lock_irqsave (struct zone *zone,unsigned long *flags,struct compact_control *cc) - __acquires(&zone->lock) + __acquires(&zone->_lock) {/* Track if the lock is contended in async mode */ if (cc->mode ==MIGRATE_ASYNC && !cc->contended) {
@@ -1402,7 +1402,7 @@ static bool suitable_migration_target(struct compact_control *cc,int order = cc->order >0 ? cc->order : pageblock_order;/* -* We are checking page_order without zone->lock taken. But +* We are checking page_order without zone->_lock taken. But * the only small danger is that we skip a potentially suitable * pageblock, so it's not worth to check order for valid range. */
mm/internal.h +1 -1
@@ -710,7 +710,7 @@ static inline unsigned int buddy_order(struct page *page)* (d) a page and its buddy are in the same zone. * * For recording whether a page is in the buddy system, we set PageBuddy. -* Setting, clearing, and testing PageBuddy is serialized by zone->lock. +* Setting, clearing, and testing PageBuddy is serialized by zone->_lock. * * For recording page's order, we use page_private(page). */
mm/page_alloc.c +8 -8
@@ -815,7 +815,7 @@ compaction_capture(struct capture_control *capc, struct page *page,static inline void account_freepages (struct zone *zone,int nr_pages,int migratetype) { -lockdep_assert_held (&zone->lock); +lockdep_assert_held (&zone->_lock);if (is_migrate_isolate (migratetype))return ;
@@ -2473,7 +2473,7 @@ enum rmqueue_mode {/* * Do the hard work of removing an element from the buddy allocator. -* Call me with the zone->lock already held. +* Call me with the zone->_lock already held. */ static __always_inline struct page * __rmqueue(struct zone *zone, unsigned int order, int migratetype,
@@ -2501,7 +2501,7 @@ __rmqueue(struct zone *zone, unsigned int order, int migratetype,* fallbacks modes with increasing levels of fragmentation risk. * * The fallback logic is expensive and rmqueue_bulk() calls in -* a loop with the zone->lock held, meaning the freelists are +* a loop with the zone->_lock held, meaning the freelists are * not subject to any outside changes. Remember in *mode where * we found pay dirt, to save us the search on the next call. */
@@ -3203,7 +3203,7 @@ void __putback_isolated_page(struct page *page, unsigned int order, int mt)struct zone *zone =page_zone (page);/* zone lock should be held when this function is called */ -lockdep_assert_held (&zone->lock); +lockdep_assert_held (&zone->_lock);/* Return isolated page to tail of freelist. */ __free_one_page(page, page_to_pfn(page), zone, order, mt,
@@ -7086,7 +7086,7 @@ int alloc_contig_frozen_range_noprof(unsigned long start, unsigned long end,* pages. Because of this, we reserve the bigger range and * once this is done free the pages we are not interested in. * -* We don't have to hold zone->lock here because the pages are +* We don't have to hold zone->_lock here because the pages are * isolated thus they won't get removed from buddy. */ outer_start =find_large_buddy (start);
@@ -7655,7 +7655,7 @@ void accept_page(struct page *page)return ; } -/* Unlocks zone->lock */ +/* Unlocks zone->_lock */ __accept_page (zone, &flags, page); }
@@ -7672,7 +7672,7 @@ static bool try_to_accept_memory_one(struct zone *zone)return false; } -/* Unlocks zone->lock */ +/* Unlocks zone->_lock */ __accept_page (zone, &flags, page);return true;
@@ -7813,7 +7813,7 @@ struct page *alloc_frozen_pages_nolock_noprof(gfp_t gfp_flags, int nid, unsigned/* * Best effort allocation from percpu free list. -* If it's empty attempt to spin_trylock zone->lock. +* If it's empty attempt to spin_trylock zone->_lock. */ page =get_page_from_freelist (alloc_gfp, order, alloc_flags, &ac);
mm/page_isolation.c +2 -2
@@ -212,7 +212,7 @@ static int set_migratetype_isolate(struct page *page, enum pb_isolate_mode mode,zone_unlock_irqrestore (zone, flags);if (mode ==PB_ISOLATE_MODE_MEM_OFFLINE ) {/* -* printk() with zone->lock held will likely trigger a +* printk() with zone->_lock held will likely trigger a * lockdep splat, so defer it here. */ dump_page (unmovable,"unmovable page" );
@@ -553,7 +553,7 @@ void undo_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn)/* * Test all pages in the range is free(means isolated) or not. * all pages in [start_pfn...end_pfn) must be in the same zone. -* zone->lock must be held before call this. +* zone->_lock must be held before call this. * * Returns the last tested pfn. */
mm/page_owner.c +1 -1
@@ -799,7 +799,7 @@ static void init_pages_in_zone(struct zone *zone)continue ;/* -* To avoid having to grab zone->lock, be a little +* To avoid having to grab zone->_lock, be a little * careful when reading buddy page order. The only * danger is that we skip too much and potentially miss * some early allocated pages, which is better than
Signature · 1 line
2.47.3
Re: [PATCH v4 4/5] mm: rename zone->lock to zone->_lock
Quoted 6 lines · Dmitry Ilvokhin
This intentionally breaks direct users of
zone->lockat compile time so all call sites are converted to the zone lock wrappers. Without the rename, present and future out-of-tree code could continue usingspin_lock(&zone->lock)and bypass the wrappers and tracing infrastructure.
Quoted 7 lines
No functional change intended.
Suggested-by Andrew Morton <[email protected]>Signed-off-by Dmitry Ilvokhin <[email protected]>Acked-by Shakeel Butt <[email protected]>Acked-by SeongJae Park <[email protected]>---
Signature · 3 lines
Cheers, David
Re: [PATCH v4 4/5] mm: rename zone->lock to zone->_lock
In reply to Dmitry IlvokhinQuoted 12 lines · Dmitry Ilvokhin
This intentionally breaks direct users of
zone->lockat compile time so all call sites are converted to the zone lock wrappers. Without the rename, present and future out-of-tree code could continue usingspin_lock(&zone->lock)and bypass the wrappers and tracing infrastructure.No functional change intended.
Suggested-by Andrew Morton <[email protected]>Signed-off-by Dmitry Ilvokhin <[email protected]>Acked-by Shakeel Butt <[email protected]>Acked-by SeongJae Park <[email protected]>
Quoted 10 lines
--- include/linux/mmzone.h | 7 +++++-- include/linux/mmzone_lock.h | 12 ++++++------ mm/compaction.c | 4 ++-- mm/internal.h | 2 +- mm/page_alloc.c | 16 ++++++++-------- mm/page_isolation.c | 4 ++-- mm/page_owner.c | 2 +- 7 files changed, 25 insertions(+), 22 deletions(-)
Best Regards,
Yan, Zi
Re: [PATCH v4 4/5] mm: rename zone->lock to zone->_lock
In reply to Dmitry IlvokhinQuoted 6 lines · Dmitry Ilvokhin
This intentionally breaks direct users of
zone->lockat compile time so all call sites are converted to the zone lock wrappers. Without the rename, present and future out-of-tree code could continue usingspin_lock(&zone->lock)and bypass the wrappers and tracing infrastructure.
Quoted 6 lines
No functional change intended.
Suggested-by Andrew Morton <[email protected]>Signed-off-by Dmitry Ilvokhin <[email protected]>Acked-by Shakeel Butt <[email protected]>Acked-by SeongJae Park <[email protected]>
I see some more instances of 'zone->lock' in comments in include/linux/mmzone.h and under Documentation/ but otherwise LGTM.
Andrew Morton
maintainerRe: [PATCH v4 4/5] mm: rename zone->lock to zone->_lock
Quoted 9 lines · On Mon, 2 Mar 2026 15:10:03 +0100 "Vlastimil Babka (SUSE)" <[email protected]>…
Quoted 8 lines · Dmitry Ilvokhin
This intentionally breaks direct users of
zone->lockat compile time so all call sites are converted to the zone lock wrappers. Without the rename, present and future out-of-tree code could continue usingspin_lock(&zone->lock)and bypass the wrappers and tracing infrastructure.No functional change intended.
Quoted 8 lines
Quoted 4 lines
Suggested-by Andrew Morton <[email protected]>Signed-off-by Dmitry Ilvokhin <[email protected]>Acked-by Shakeel Butt <[email protected]>Acked-by SeongJae Park <[email protected]>I see some more instances of '
zone->lock' in comments ininclude/linux/mmzone.hand underDocumentation/but otherwise LGTM.
I fixed (most of) that in the previous version but my fix was lost.
include/linux/mmzone.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
include/linux/mmzone.h renamed from include/linux/mmzone.h~mm-rename-zone-lock-to-zone-_lock-fix +5 -5
@@ -1037,12 +1037,12 @@ struct zone {* Locking rules: * * zone_start_pfn and spanned_pages are protected by span_seqlock. -* It is a seqlock because it has to be read outside of zone->lock, +* It is a seqlock because it has to be read outside of zone_lock, * and it is done in the main allocator path. But, it is written * quite infrequently. * -* The span_seq lock is declared along with zone->lock because it is -* frequently read in proximity to zone->lock. It's good to +* The span_seq lock is declared along with zone_lock because it is +* frequently read in proximity to zone_lock. It's good to * give them a chance of being in the same cacheline. * * Write access to present_pages at runtime should be protected by
@@ -1065,7 +1065,7 @@ struct zone {/* * Number of isolated pageblock. It is used to solve incorrect * freepage counting problem due to racy retrieving migratetype -* of pageblock. Protected by zone->lock. +* of pageblock. Protected by zone_lock. */ unsigned long nr_isolate_pageblock;#endif
@@ -1502,7 +1502,7 @@ typedef struct pglist_data {* manipulate node_size_lock without checking for CONFIG_MEMORY_HOTPLUG * or CONFIG_DEFERRED_STRUCT_PAGE_INIT. * -* Nests above zone->lock and zone->span_seqlock +* Nests above zone_lock and zone->span_seqlock */ spinlock_t node_size_lock;#endif
_
Re: [PATCH v4 4/5] mm: rename zone->lock to zone->_lock
Quoted 16 lines · Andrew Morton
Quoted 14 lines · On Mon, 2 Mar 2026 15:10:03 +0100 "Vlastimil Babka (SUSE)" <[email protected]>…
Quoted 12 lines · Dmitry Ilvokhin
This intentionally breaks direct users of
zone->lockat compile time so all call sites are converted to the zone lock wrappers. Without the rename, present and future out-of-tree code could continue usingspin_lock(&zone->lock)and bypass the wrappers and tracing infrastructure.No functional change intended.
Suggested-by Andrew Morton <[email protected]>Signed-off-by Dmitry Ilvokhin <[email protected]>Acked-by Shakeel Butt <[email protected]>Acked-by SeongJae Park <[email protected]>
Quoted 5 lines
Quoted 3 lines
I see some more instances of '
zone->lock' in comments ininclude/linux/mmzone.hand underDocumentation/but otherwise LGTM.I fixed (most of) that in the previous version but my fix was lost.
Thanks for the fixups, Andrew.
I still see a few 'zone->lock' references in Documentation remain on mm-new. This patch cleans them up, as noted by Vlastimil.
I'm happy to adjust this patch if anything else needs attention.
From 9142d5a8b60038fa424a6033253960682e5a51f4 Mon Sep 17 00:00:00 2001
From: Dmitry Ilvokhin <[email protected]>
Date: Tue, 3 Mar 2026 06:13:13 -0800
Subject: [PATCH] mm: fix remaining zone->lock references
--- Documentation/mm/physical_memory.rst | 4 ++-- Documentation/trace/events-kmem.rst | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-)
Documentation/mm/physical_memory.rst +2 -2
@@ -500,11 +500,11 @@ General ``nr_isolate_pageblock`` Number of isolated pageblocks. It is used to solve incorrect freepage counting problem due to racy retrieving migratetype of pageblock. Protected by - ``zone->lock``. Defined only when ``CONFIG_MEMORY_ISOLATION`` is enabled. + ``zone_lock``. Defined only when ``CONFIG_MEMORY_ISOLATION`` is enabled. ``span_seqlock`` The seqlock to protect ``zone_start_pfn`` and ``spanned_pages``. It is a - seqlock because it has to be read outside of ``zone->lock``, and it is done in + seqlock because it has to be read outside of ``zone_lock``, and it is done in the main allocator path. However, the seqlock is written quite infrequently. Defined only when ``CONFIG_MEMORY_HOTPLUG`` is enabled.
Documentation/trace/events-kmem.rst +4 -4
@@ -57,7 +57,7 @@ the per-CPU allocator (high performance) or the buddy allocator. If pages are allocated directly from the buddy allocator, the mm_page_alloc_zone_locked event is triggered. This event is important as high -amounts of activity imply high activity on the zone->lock. Taking this lock +amounts of activity imply high activity on the zone_lock. Taking this lock impairs performance by disabling interrupts, dirtying cache lines between CPUs and serialising many CPUs.
@@ -79,11 +79,11 @@ contention on the lruvec->lru_lock. mm_page_pcpu_drain page=%p pfn=%lu order=%d cpu=%d migratetype=%d In front of the page allocator is a per-cpu page allocator. It exists only -for order-0 pages, reduces contention on the zone->lock and reduces the +for order-0 pages, reduces contention on the zone_lock and reduces the amount of writing on struct page. When a per-CPU list is empty or pages of the wrong type are allocated, -the zone->lock will be taken once and the per-CPU list refilled. The event +the zone_lock will be taken once and the per-CPU list refilled. The event triggered is mm_page_alloc_zone_locked for each page allocated with the event indicating whether it is for a percpu_refill or not.
@@ -92,7 +92,7 @@ which triggers a mm_page_pcpu_drain event. The individual nature of the events is so that pages can be tracked between allocation and freeing. A number of drain or refill pages that occur -consecutively imply the zone->lock being taken once. Large amounts of per-CPU +consecutively imply the zone_lock being taken once. Large amounts of per-CPU refills and drains could imply an imbalance between CPUs where too much work is being concentrated in one place. It could also indicate that the per-CPU lists should be a larger size. Finally, large amounts of refills on one CPU
Signature · 1 line
2.47.3
Re: [PATCH v4 4/5] mm: rename zone->lock to zone->_lock
Quoted 46 lines · On Tue, 3 Mar 2026 14:25:55 +0000 Dmitry Ilvokhin <[email protected]> wrote:
Quoted 16 lines · Andrew Morton
Quoted 14 lines · On Mon, 2 Mar 2026 15:10:03 +0100 "Vlastimil Babka (SUSE)" <[email protected]>…
Quoted 12 lines · Dmitry Ilvokhin
This intentionally breaks direct users of
zone->lockat compile time so all call sites are converted to the zone lock wrappers. Without the rename, present and future out-of-tree code could continue usingspin_lock(&zone->lock)and bypass the wrappers and tracing infrastructure.No functional change intended.
Suggested-by Andrew Morton <[email protected]>Signed-off-by Dmitry Ilvokhin <[email protected]>Acked-by Shakeel Butt <[email protected]>Acked-by SeongJae Park <[email protected]>Quoted 5 lines
Quoted 3 lines
I see some more instances of '
zone->lock' in comments ininclude/linux/mmzone.hand underDocumentation/but otherwise LGTM.I fixed (most of) that in the previous version but my fix was lost.
Thanks for the fixups, Andrew.
I still see a few '
zone->lock' references in Documentation remain on mm-new. This patch cleans them up, as noted by Vlastimil.I'm happy to adjust this patch if anything else needs attention.
From
9142d5a8b60038fa424a6033253960682e5a51f4Mon Sep 17 00:00:00 2001
From: Dmitry Ilvokhin <[email protected]>
Date: Tue, 3 Mar 2026 06:13:13 -0800
Subject: [PATCH] mm: fix remainingzone->lockreferencesSigned-off-by Dmitry Ilvokhin <[email protected]>--- Documentation/mm/physical_memory.rst | 4 ++-- Documentation/trace/events-kmem.rst | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-)Documentation/mm/physical_memory.rst +0
-0
Documentation/mm/physical_memory.rst General · line 503
Quoted 5 lines
Documentation/mm/physical_memory.rst +1
-1@@ -500,11 +500,11 @@ General ``nr_isolate_pageblock`` Number of isolated pageblocks. It is used to solve incorrect freepage counting problem due to racy retrieving migratetype of pageblock. Protected by - ``zone->lock``. Defined only when ``CONFIG_MEMORY_ISOLATION`` is enabled. + ``zone_lock``. Defined only when ``CONFIG_MEMORY_ISOLATION`` is enabled.
Dmitry's original patch [1] was doing 's/zone->lock/zone->_lock/', which aligns to my expectation. But this patch is doing 's/zone->lock/zone_lock/'. Same for the rest of this patch.
I was initially thinking this is just a mistake, but I also found Andrew is doing same change [2], so I'm bit confused. Is this an intentional change?
[1] https://lore.kernel.org/d61500c5784c64e971f4d328c57639303c475f81.1772206930.git.d@ilvokhin.com
[2] https://lore.kernel.org/[email protected]
Thanks,
SJ
[...]
Re: [PATCH v4 4/5] mm: rename zone->lock to zone->_lock
Quoted 58 lines · SeongJae Park
Quoted 46 lines · On Tue, 3 Mar 2026 14:25:55 +0000 Dmitry Ilvokhin <[email protected]> wrote:
Quoted 16 lines · Andrew Morton
Quoted 14 lines · On Mon, 2 Mar 2026 15:10:03 +0100 "Vlastimil Babka (SUSE)" <[email protected]>…
Quoted 12 lines · Dmitry Ilvokhin
This intentionally breaks direct users of
zone->lockat compile time so all call sites are converted to the zone lock wrappers. Without the rename, present and future out-of-tree code could continue usingspin_lock(&zone->lock)and bypass the wrappers and tracing infrastructure.No functional change intended.
Suggested-by Andrew Morton <[email protected]>Signed-off-by Dmitry Ilvokhin <[email protected]>Acked-by Shakeel Butt <[email protected]>Acked-by SeongJae Park <[email protected]>Quoted 5 lines
Quoted 3 lines
I see some more instances of '
zone->lock' in comments ininclude/linux/mmzone.hand underDocumentation/but otherwise LGTM.I fixed (most of) that in the previous version but my fix was lost.
Thanks for the fixups, Andrew.
I still see a few '
zone->lock' references in Documentation remain on mm-new. This patch cleans them up, as noted by Vlastimil.I'm happy to adjust this patch if anything else needs attention.
From
9142d5a8b60038fa424a6033253960682e5a51f4Mon Sep 17 00:00:00 2001
From: Dmitry Ilvokhin <[email protected]>
Date: Tue, 3 Mar 2026 06:13:13 -0800
Subject: [PATCH] mm: fix remainingzone->lockreferencesSigned-off-by Dmitry Ilvokhin <[email protected]>--- Documentation/mm/physical_memory.rst | 4 ++-- Documentation/trace/events-kmem.rst | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-)Documentation/mm/physical_memory.rst +0
-0Documentation/mm/physical_memory.rst General · line 503
Quoted 5 lines
Documentation/mm/physical_memory.rst +1
-1@@ -500,11 +500,11 @@ General ``nr_isolate_pageblock`` Number of isolated pageblocks. It is used to solve incorrect freepage counting problem due to racy retrieving migratetype of pageblock. Protected by - ``zone->lock``. Defined only when ``CONFIG_MEMORY_ISOLATION`` is enabled. + ``zone_lock``. Defined only when ``CONFIG_MEMORY_ISOLATION`` is enabled.Dmitry's original patch [1] was doing 's/zone->lock/zone->_lock/', which aligns to my expectation. But this patch is doing 's/zone->lock/zone_lock/'. Same for the rest of this patch.
Quoted 6 lines
I was initially thinking this is just a mistake, but I also found Andrew is doing same change [2], so I'm bit confused. Is this an intentional change?
[1] https://lore.kernel.org/d61500c5784c64e971f4d328c57639303c475f81.1772206930.git.d@ilvokhin.com
[2] https://lore.kernel.org/[email protected]
Good catch, thanks for pointing this out, SJ.
Originally the mechanical rename was indeed zone->lock -> zone->_lock. However, in Documentation I intentionally switched references to zone_lock instead of zone->_lock. The reasoning is that _lock is now an internal implementation detail, and direct access is discouraged. The intended interface is via the zone_lock_*() / zone_unlock_*() wrappers, so referencing zone_lock in documentation felt more appropriate than mentioning the private struct field (zone->_lock).
That said, I agree this creates inconsistency with the mechanical rename, and I'm happy to adjust either way: either consistently refer to the wrapper API, or keep documentation aligned with zone->_lock.
I slightly prefer referring to the wrapper API, but don't have a strong preference as long as we're consistent.
Quoted 5 lines
Thanks,
SJ[...]
Re: [PATCH v4 4/5] mm: rename zone->lock to zone->_lock
Quoted 68 lines · On Wed, 4 Mar 2026 13:01:45 +0000 Dmitry Ilvokhin <[email protected]> wrote:
Quoted 58 lines · SeongJae Park
Quoted 46 lines · On Tue, 3 Mar 2026 14:25:55 +0000 Dmitry Ilvokhin <[email protected]> wrote:
Quoted 16 lines · Andrew Morton
Quoted 14 lines · On Mon, 2 Mar 2026 15:10:03 +0100 "Vlastimil Babka (SUSE)" <[email protected]>…
Quoted 12 lines · Dmitry Ilvokhin
This intentionally breaks direct users of
zone->lockat compile time so all call sites are converted to the zone lock wrappers. Without the rename, present and future out-of-tree code could continue usingspin_lock(&zone->lock)and bypass the wrappers and tracing infrastructure.No functional change intended.
Suggested-by Andrew Morton <[email protected]>Signed-off-by Dmitry Ilvokhin <[email protected]>Acked-by Shakeel Butt <[email protected]>Acked-by SeongJae Park <[email protected]>Quoted 5 lines
Quoted 3 lines
I see some more instances of '
zone->lock' in comments ininclude/linux/mmzone.hand underDocumentation/but otherwise LGTM.I fixed (most of) that in the previous version but my fix was lost.
Thanks for the fixups, Andrew.
I still see a few '
zone->lock' references in Documentation remain on mm-new. This patch cleans them up, as noted by Vlastimil.I'm happy to adjust this patch if anything else needs attention.
From
9142d5a8b60038fa424a6033253960682e5a51f4Mon Sep 17 00:00:00 2001
From: Dmitry Ilvokhin <[email protected]>
Date: Tue, 3 Mar 2026 06:13:13 -0800
Subject: [PATCH] mm: fix remainingzone->lockreferencesSigned-off-by Dmitry Ilvokhin <[email protected]>--- Documentation/mm/physical_memory.rst | 4 ++-- Documentation/trace/events-kmem.rst | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-)Documentation/mm/physical_memory.rst +0
-0Documentation/mm/physical_memory.rst General · line 503
Quoted 5 lines
Documentation/mm/physical_memory.rst +1
-1@@ -500,11 +500,11 @@ General ``nr_isolate_pageblock`` Number of isolated pageblocks. It is used to solve incorrect freepage counting problem due to racy retrieving migratetype of pageblock. Protected by - ``zone->lock``. Defined only when ``CONFIG_MEMORY_ISOLATION`` is enabled. + ``zone_lock``. Defined only when ``CONFIG_MEMORY_ISOLATION`` is enabled.Dmitry's original patch [1] was doing 's/zone->lock/zone->_lock/', which aligns to my expectation. But this patch is doing 's/zone->lock/zone_lock/'. Same for the rest of this patch.
Quoted 6 lines
I was initially thinking this is just a mistake, but I also found Andrew is doing same change [2], so I'm bit confused. Is this an intentional change?
[1] https://lore.kernel.org/d61500c5784c64e971f4d328c57639303c475f81.1772206930.git.d@ilvokhin.com
[2] https://lore.kernel.org/[email protected]Good catch, thanks for pointing this out, SJ.
Quoted 7 lines
Originally the mechanical rename was indeed
zone->lock->zone->_lock. However, in Documentation I intentionally switched references tozone_lockinstead ofzone->_lock. The reasoning is that_lockis now an internal implementation detail, and direct access is discouraged. The intended interface is via the zone_lock_*() / zone_unlock_*() wrappers, so referencingzone_lockin documentation felt more appropriate than mentioning the private struct field (zone->_lock).
Thank you for this nice and kind clarification, Dmitry! I agree mentioning zone_[un]lock_*() helpers instead of the hidden member (zone->_lock) can be better.
But, I'm concerned if people like me might not aware the intention under 'zone_lock'. If there is a well-known convention that allows people to know it is for 'zone_[un]lock_*()' helpers, making it more clear would be nice, in my humble opinion. If there is such a convention but I'm just missing it, please ignore. If I'm not, for eaxmaple,
"protected by ``zone->lock``" could be re-wrote to "protected by ``zone_[un]lock_*()`` locking helpers" or, "protected by zone lock helper functions (``zone_[un]lock_*()``)" ?
Quoted 7 lines
That said, I agree this creates inconsistency with the mechanical rename, and I'm happy to adjust either way: either consistently refer to the wrapper API, or keep documentation aligned with
zone->_lock.I slightly prefer referring to the wrapper API, but don't have a strong preference as long as we're consistent.
I also think both approaches are good. But for the wrapper approach, I think giving more contexts rather than just ``zone_lock`` to readers would be nice.
Thanks,
SJ
[...]
Re: [PATCH v4 4/5] mm: rename zone->lock to zone->_lock
Quoted 88 lines · On Wed, 4 Mar 2026 07:13:34 -0800 SeongJae Park <[email protected]> wrote:
Quoted 68 lines · On Wed, 4 Mar 2026 13:01:45 +0000 Dmitry Ilvokhin <[email protected]> wrote:
Quoted 58 lines · SeongJae Park
Quoted 46 lines · On Tue, 3 Mar 2026 14:25:55 +0000 Dmitry Ilvokhin <[email protected]> wrote:
Quoted 16 lines · Andrew Morton
Quoted 14 lines · On Mon, 2 Mar 2026 15:10:03 +0100 "Vlastimil Babka (SUSE)" <[email protected]>…
Quoted 12 lines · Dmitry Ilvokhin
This intentionally breaks direct users of
zone->lockat compile time so all call sites are converted to the zone lock wrappers. Without the rename, present and future out-of-tree code could continue usingspin_lock(&zone->lock)and bypass the wrappers and tracing infrastructure.No functional change intended.
Suggested-by Andrew Morton <[email protected]>Signed-off-by Dmitry Ilvokhin <[email protected]>Acked-by Shakeel Butt <[email protected]>Acked-by SeongJae Park <[email protected]>Quoted 5 lines
Quoted 3 lines
I see some more instances of '
zone->lock' in comments ininclude/linux/mmzone.hand underDocumentation/but otherwise LGTM.I fixed (most of) that in the previous version but my fix was lost.
Thanks for the fixups, Andrew.
I still see a few '
zone->lock' references in Documentation remain on mm-new. This patch cleans them up, as noted by Vlastimil.I'm happy to adjust this patch if anything else needs attention.
From
9142d5a8b60038fa424a6033253960682e5a51f4Mon Sep 17 00:00:00 2001
From: Dmitry Ilvokhin <[email protected]>
Date: Tue, 3 Mar 2026 06:13:13 -0800
Subject: [PATCH] mm: fix remainingzone->lockreferencesSigned-off-by Dmitry Ilvokhin <[email protected]>--- Documentation/mm/physical_memory.rst | 4 ++-- Documentation/trace/events-kmem.rst | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-)Documentation/mm/physical_memory.rst +0
-0Documentation/mm/physical_memory.rst General · line 503
Quoted 5 lines
Documentation/mm/physical_memory.rst +1
-1@@ -500,11 +500,11 @@ General ``nr_isolate_pageblock`` Number of isolated pageblocks. It is used to solve incorrect freepage counting problem due to racy retrieving migratetype of pageblock. Protected by - ``zone->lock``. Defined only when ``CONFIG_MEMORY_ISOLATION`` is enabled. + ``zone_lock``. Defined only when ``CONFIG_MEMORY_ISOLATION`` is enabled.Dmitry's original patch [1] was doing 's/zone->lock/zone->_lock/', which aligns to my expectation. But this patch is doing 's/zone->lock/zone_lock/'. Same for the rest of this patch.
Quoted 6 lines
I was initially thinking this is just a mistake, but I also found Andrew is doing same change [2], so I'm bit confused. Is this an intentional change?
[1] https://lore.kernel.org/d61500c5784c64e971f4d328c57639303c475f81.1772206930.git.d@ilvokhin.com
[2] https://lore.kernel.org/[email protected]Good catch, thanks for pointing this out, SJ.
Quoted 7 lines
Originally the mechanical rename was indeed
zone->lock->zone->_lock. However, in Documentation I intentionally switched references tozone_lockinstead ofzone->_lock. The reasoning is that_lockis now an internal implementation detail, and direct access is discouraged. The intended interface is via the zone_lock_*() / zone_unlock_*() wrappers, so referencingzone_lockin documentation felt more appropriate than mentioning the private struct field (zone->_lock).Thank you for this nice and kind clarification, Dmitry! I agree mentioning zone_[un]lock_*() helpers instead of the hidden member (
zone->_lock) can be better.But, I'm concerned if people like me might not aware the intention under '
zone_lock'. If there is a well-known convention that allows people to know it is for 'zone_[un]lock_*()' helpers, making it more clear would be nice, in my humble opinion. If there is such a convention but I'm just missing it, please ignore. If I'm not, for eaxmaple,
Quoted 3 lines
"protected by ``zone->lock``" could be re-wrote to "protected by ``zone_[un]lock_*()`` locking helpers" or, "protected by zone lock helper functions (``zone_[un]lock_*()``)" ?
Maybe too verbose and people who not used to regex might be confused. Mentioning mmzone_lock.h might be better? E.g.,
protected by functions in mmzone_lock.h
Quoted 11 lines
Quoted 8 lines
That said, I agree this creates inconsistency with the mechanical rename, and I'm happy to adjust either way: either consistently refer to the wrapper API, or keep documentation aligned with
zone->_lock.I slightly prefer referring to the wrapper API, but don't have a strong preference as long as we're consistent.
I also think both approaches are good. But for the wrapper approach, I think giving more contexts rather than just ``zone_lock`` to readers would be nice.
Thanks,
SJ
[...]
Vlastimil Babka (SUSE)
maintainerRe: [PATCH v4 4/5] mm: rename zone->lock to zone->_lock
In reply to SeongJae ParkQuoted 97 lines · SeongJae Park
Quoted 68 lines · On Wed, 4 Mar 2026 13:01:45 +0000 Dmitry Ilvokhin <[email protected]> wrote:
Quoted 58 lines · SeongJae Park
Quoted 46 lines · On Tue, 3 Mar 2026 14:25:55 +0000 Dmitry Ilvokhin <[email protected]> wrote:
Quoted 16 lines · Andrew Morton
Quoted 14 lines · On Mon, 2 Mar 2026 15:10:03 +0100 "Vlastimil Babka (SUSE)" <[email protected]>…
Quoted 12 lines · Dmitry Ilvokhin
This intentionally breaks direct users of
zone->lockat compile time so all call sites are converted to the zone lock wrappers. Without the rename, present and future out-of-tree code could continue usingspin_lock(&zone->lock)and bypass the wrappers and tracing infrastructure.No functional change intended.
Suggested-by Andrew Morton <[email protected]>Signed-off-by Dmitry Ilvokhin <[email protected]>Acked-by Shakeel Butt <[email protected]>Acked-by SeongJae Park <[email protected]>Quoted 5 lines
Quoted 3 lines
I see some more instances of '
zone->lock' in comments ininclude/linux/mmzone.hand underDocumentation/but otherwise LGTM.I fixed (most of) that in the previous version but my fix was lost.
Thanks for the fixups, Andrew.
I still see a few '
zone->lock' references in Documentation remain on mm-new. This patch cleans them up, as noted by Vlastimil.I'm happy to adjust this patch if anything else needs attention.
From
9142d5a8b60038fa424a6033253960682e5a51f4Mon Sep 17 00:00:00 2001
From: Dmitry Ilvokhin <[email protected]>
Date: Tue, 3 Mar 2026 06:13:13 -0800
Subject: [PATCH] mm: fix remainingzone->lockreferencesSigned-off-by Dmitry Ilvokhin <[email protected]>--- Documentation/mm/physical_memory.rst | 4 ++-- Documentation/trace/events-kmem.rst | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-)Documentation/mm/physical_memory.rst +0
-0Documentation/mm/physical_memory.rst General · line 503
Quoted 5 lines
Documentation/mm/physical_memory.rst +1
-1@@ -500,11 +500,11 @@ General ``nr_isolate_pageblock`` Number of isolated pageblocks. It is used to solve incorrect freepage counting problem due to racy retrieving migratetype of pageblock. Protected by - ``zone->lock``. Defined only when ``CONFIG_MEMORY_ISOLATION`` is enabled. + ``zone_lock``. Defined only when ``CONFIG_MEMORY_ISOLATION`` is enabled.Dmitry's original patch [1] was doing 's/zone->lock/zone->_lock/', which aligns to my expectation. But this patch is doing 's/zone->lock/zone_lock/'. Same for the rest of this patch.
Quoted 6 lines
I was initially thinking this is just a mistake, but I also found Andrew is doing same change [2], so I'm bit confused. Is this an intentional change?
[1] https://lore.kernel.org/d61500c5784c64e971f4d328c57639303c475f81.1772206930.git.d@ilvokhin.com
[2] https://lore.kernel.org/[email protected]Good catch, thanks for pointing this out, SJ.
Quoted 7 lines
Originally the mechanical rename was indeed
zone->lock->zone->_lock. However, in Documentation I intentionally switched references tozone_lockinstead ofzone->_lock. The reasoning is that_lockis now an internal implementation detail, and direct access is discouraged. The intended interface is via the zone_lock_*() / zone_unlock_*() wrappers, so referencingzone_lockin documentation felt more appropriate than mentioning the private struct field (zone->_lock).Thank you for this nice and kind clarification, Dmitry! I agree mentioning zone_[un]lock_*() helpers instead of the hidden member (
zone->_lock) can be better.But, I'm concerned if people like me might not aware the intention under '
zone_lock'. If there is a well-known convention that allows people to know it is for 'zone_[un]lock_*()' helpers, making it more clear would be nice, in my humble opinion. If there is such a convention but I'm just missing it, please ignore. If I'm not, for eaxmaple,"protected by ``zone->lock``" could be re-wrote to "protected by ``zone_[un]lock_*()`` locking helpers" or, "protected by zone lock helper functions (``zone_[un]lock_*()``)" ?
Quoted 5 lines
That said, I agree this creates inconsistency with the mechanical rename, and I'm happy to adjust either way: either consistently refer to the wrapper API, or keep documentation aligned with
zone->_lock.
Quoted 5 lines
Quoted 2 lines
I slightly prefer referring to the wrapper API, but don't have a strong preference as long as we're consistent.
I also think both approaches are good. But for the wrapper approach, I think giving more contexts rather than just ``zone_lock`` to readers would be nice.
Grep tells me that we also have comments mentioning simply "zone lock", btw. And it's also a term used often in informal conversations. Maybe we could just standardize on that in comments/documentations as it's easier to read. Discovering that the field is called _lock and that wrappers should be used, is hopefully not that difficult.
Re: [PATCH v4 4/5] mm: rename zone->lock to zone->_lock
Quoted 101 lines · On Thu, 5 Mar 2026 10:27:07 +0100 "Vlastimil Babka (SUSE)" <[email protected]>…
Quoted 100 lines · SeongJae Park
Quoted 68 lines · On Wed, 4 Mar 2026 13:01:45 +0000 Dmitry Ilvokhin <[email protected]> wrote:
Quoted 58 lines · SeongJae Park
Quoted 46 lines · On Tue, 3 Mar 2026 14:25:55 +0000 Dmitry Ilvokhin <[email protected]> wrote:
Quoted 16 lines · Andrew Morton
Quoted 14 lines · On Mon, 2 Mar 2026 15:10:03 +0100 "Vlastimil Babka (SUSE)" <[email protected]>…
Quoted 12 lines · Dmitry Ilvokhin
This intentionally breaks direct users of
zone->lockat compile time so all call sites are converted to the zone lock wrappers. Without the rename, present and future out-of-tree code could continue usingspin_lock(&zone->lock)and bypass the wrappers and tracing infrastructure.No functional change intended.
Suggested-by Andrew Morton <[email protected]>Signed-off-by Dmitry Ilvokhin <[email protected]>Acked-by Shakeel Butt <[email protected]>Acked-by SeongJae Park <[email protected]>Quoted 5 lines
Quoted 3 lines
I see some more instances of '
zone->lock' in comments ininclude/linux/mmzone.hand underDocumentation/but otherwise LGTM.I fixed (most of) that in the previous version but my fix was lost.
Thanks for the fixups, Andrew.
I still see a few '
zone->lock' references in Documentation remain on mm-new. This patch cleans them up, as noted by Vlastimil.I'm happy to adjust this patch if anything else needs attention.
From
9142d5a8b60038fa424a6033253960682e5a51f4Mon Sep 17 00:00:00 2001
From: Dmitry Ilvokhin <[email protected]>
Date: Tue, 3 Mar 2026 06:13:13 -0800
Subject: [PATCH] mm: fix remainingzone->lockreferencesSigned-off-by Dmitry Ilvokhin <[email protected]>--- Documentation/mm/physical_memory.rst | 4 ++-- Documentation/trace/events-kmem.rst | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-)Documentation/mm/physical_memory.rst +0
-0Documentation/mm/physical_memory.rst General · line 503
Quoted 5 lines
Documentation/mm/physical_memory.rst +1
-1@@ -500,11 +500,11 @@ General ``nr_isolate_pageblock`` Number of isolated pageblocks. It is used to solve incorrect freepage counting problem due to racy retrieving migratetype of pageblock. Protected by - ``zone->lock``. Defined only when ``CONFIG_MEMORY_ISOLATION`` is enabled. + ``zone_lock``. Defined only when ``CONFIG_MEMORY_ISOLATION`` is enabled.Dmitry's original patch [1] was doing 's/zone->lock/zone->_lock/', which aligns to my expectation. But this patch is doing 's/zone->lock/zone_lock/'. Same for the rest of this patch.
Quoted 6 lines
I was initially thinking this is just a mistake, but I also found Andrew is doing same change [2], so I'm bit confused. Is this an intentional change?
[1] https://lore.kernel.org/d61500c5784c64e971f4d328c57639303c475f81.1772206930.git.d@ilvokhin.com
[2] https://lore.kernel.org/[email protected]Good catch, thanks for pointing this out, SJ.
Quoted 7 lines
Originally the mechanical rename was indeed
zone->lock->zone->_lock. However, in Documentation I intentionally switched references tozone_lockinstead ofzone->_lock. The reasoning is that_lockis now an internal implementation detail, and direct access is discouraged. The intended interface is via the zone_lock_*() / zone_unlock_*() wrappers, so referencingzone_lockin documentation felt more appropriate than mentioning the private struct field (zone->_lock).Thank you for this nice and kind clarification, Dmitry! I agree mentioning zone_[un]lock_*() helpers instead of the hidden member (
zone->_lock) can be better.But, I'm concerned if people like me might not aware the intention under '
zone_lock'. If there is a well-known convention that allows people to know it is for 'zone_[un]lock_*()' helpers, making it more clear would be nice, in my humble opinion. If there is such a convention but I'm just missing it, please ignore. If I'm not, for eaxmaple,"protected by ``zone->lock``" could be re-wrote to "protected by ``zone_[un]lock_*()`` locking helpers" or, "protected by zone lock helper functions (``zone_[un]lock_*()``)" ?
Quoted 7 lines
That said, I agree this creates inconsistency with the mechanical rename, and I'm happy to adjust either way: either consistently refer to the wrapper API, or keep documentation aligned with
zone->_lock.I slightly prefer referring to the wrapper API, but don't have a strong preference as long as we're consistent.
Quoted 8 lines
Quoted 2 lines
I also think both approaches are good. But for the wrapper approach, I think giving more contexts rather than just ``zone_lock`` to readers would be nice.
Grep tells me that we also have comments mentioning simply "zone lock", btw. And it's also a term used often in informal conversations. Maybe we could just standardize on that in comments/documentations as it's easier to read. Discovering that the field is called
_lockand that wrappers should be used, is hopefully not that difficult.
Sounds good, that also works for me.
Thanks,
SJ
Re: [PATCH v4 4/5] mm: rename zone->lock to zone->_lock
In reply to Vlastimil Babka (SUSE)Quoted 101 lines · Vlastimil Babka (SUSE)
Quoted 100 lines · SeongJae Park
Quoted 68 lines · On Wed, 4 Mar 2026 13:01:45 +0000 Dmitry Ilvokhin <[email protected]> wrote:
Quoted 58 lines · SeongJae Park
Quoted 46 lines · On Tue, 3 Mar 2026 14:25:55 +0000 Dmitry Ilvokhin <[email protected]> wrote:
Quoted 16 lines · Andrew Morton
Quoted 14 lines · On Mon, 2 Mar 2026 15:10:03 +0100 "Vlastimil Babka (SUSE)" <[email protected]>…
Quoted 12 lines · Dmitry Ilvokhin
This intentionally breaks direct users of
zone->lockat compile time so all call sites are converted to the zone lock wrappers. Without the rename, present and future out-of-tree code could continue usingspin_lock(&zone->lock)and bypass the wrappers and tracing infrastructure.No functional change intended.
Suggested-by Andrew Morton <[email protected]>Signed-off-by Dmitry Ilvokhin <[email protected]>Acked-by Shakeel Butt <[email protected]>Acked-by SeongJae Park <[email protected]>Quoted 5 lines
Quoted 3 lines
I see some more instances of '
zone->lock' in comments ininclude/linux/mmzone.hand underDocumentation/but otherwise LGTM.I fixed (most of) that in the previous version but my fix was lost.
Thanks for the fixups, Andrew.
I still see a few '
zone->lock' references in Documentation remain on mm-new. This patch cleans them up, as noted by Vlastimil.I'm happy to adjust this patch if anything else needs attention.
From
9142d5a8b60038fa424a6033253960682e5a51f4Mon Sep 17 00:00:00 2001
From: Dmitry Ilvokhin <[email protected]>
Date: Tue, 3 Mar 2026 06:13:13 -0800
Subject: [PATCH] mm: fix remainingzone->lockreferencesSigned-off-by Dmitry Ilvokhin <[email protected]>--- Documentation/mm/physical_memory.rst | 4 ++-- Documentation/trace/events-kmem.rst | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-)Documentation/mm/physical_memory.rst +0
-0Documentation/mm/physical_memory.rst General · line 503
Quoted 5 lines
Documentation/mm/physical_memory.rst +1
-1@@ -500,11 +500,11 @@ General ``nr_isolate_pageblock`` Number of isolated pageblocks. It is used to solve incorrect freepage counting problem due to racy retrieving migratetype of pageblock. Protected by - ``zone->lock``. Defined only when ``CONFIG_MEMORY_ISOLATION`` is enabled. + ``zone_lock``. Defined only when ``CONFIG_MEMORY_ISOLATION`` is enabled.Dmitry's original patch [1] was doing 's/zone->lock/zone->_lock/', which aligns to my expectation. But this patch is doing 's/zone->lock/zone_lock/'. Same for the rest of this patch.
Quoted 6 lines
I was initially thinking this is just a mistake, but I also found Andrew is doing same change [2], so I'm bit confused. Is this an intentional change?
[1] https://lore.kernel.org/d61500c5784c64e971f4d328c57639303c475f81.1772206930.git.d@ilvokhin.com
[2] https://lore.kernel.org/[email protected]Good catch, thanks for pointing this out, SJ.
Quoted 7 lines
Originally the mechanical rename was indeed
zone->lock->zone->_lock. However, in Documentation I intentionally switched references tozone_lockinstead ofzone->_lock. The reasoning is that_lockis now an internal implementation detail, and direct access is discouraged. The intended interface is via the zone_lock_*() / zone_unlock_*() wrappers, so referencingzone_lockin documentation felt more appropriate than mentioning the private struct field (zone->_lock).Thank you for this nice and kind clarification, Dmitry! I agree mentioning zone_[un]lock_*() helpers instead of the hidden member (
zone->_lock) can be better.But, I'm concerned if people like me might not aware the intention under '
zone_lock'. If there is a well-known convention that allows people to know it is for 'zone_[un]lock_*()' helpers, making it more clear would be nice, in my humble opinion. If there is such a convention but I'm just missing it, please ignore. If I'm not, for eaxmaple,"protected by ``zone->lock``" could be re-wrote to "protected by ``zone_[un]lock_*()`` locking helpers" or, "protected by zone lock helper functions (``zone_[un]lock_*()``)" ?
Quoted 7 lines
That said, I agree this creates inconsistency with the mechanical rename, and I'm happy to adjust either way: either consistently refer to the wrapper API, or keep documentation aligned with
zone->_lock.I slightly prefer referring to the wrapper API, but don't have a strong preference as long as we're consistent.
Quoted 8 lines
Quoted 2 lines
I also think both approaches are good. But for the wrapper approach, I think giving more contexts rather than just ``zone_lock`` to readers would be nice.
Grep tells me that we also have comments mentioning simply "zone lock", btw. And it's also a term used often in informal conversations. Maybe we could just standardize on that in comments/documentations as it's easier to read. Discovering that the field is called
_lockand that wrappers should be used, is hopefully not that difficult.
Thanks for the suggestion, Vlastimil. That sounds reasonable to me as well. I'll update the comments and documentation to consistently use "zone lock".
Re: [PATCH v4 4/5] mm: rename zone->lock to zone->_lock
Quoted 111 lines · Dmitry Ilvokhin
Quoted 101 lines · Vlastimil Babka (SUSE)
Quoted 100 lines · SeongJae Park
Quoted 68 lines · On Wed, 4 Mar 2026 13:01:45 +0000 Dmitry Ilvokhin <[email protected]> wrote:
Quoted 58 lines · SeongJae Park
Quoted 46 lines · On Tue, 3 Mar 2026 14:25:55 +0000 Dmitry Ilvokhin <[email protected]> wrote:
Quoted 16 lines · Andrew Morton
Quoted 14 lines · On Mon, 2 Mar 2026 15:10:03 +0100 "Vlastimil Babka (SUSE)" <[email protected]>…
Quoted 12 lines · Dmitry Ilvokhin
This intentionally breaks direct users of
zone->lockat compile time so all call sites are converted to the zone lock wrappers. Without the rename, present and future out-of-tree code could continue usingspin_lock(&zone->lock)and bypass the wrappers and tracing infrastructure.No functional change intended.
Suggested-by Andrew Morton <[email protected]>Signed-off-by Dmitry Ilvokhin <[email protected]>Acked-by Shakeel Butt <[email protected]>Acked-by SeongJae Park <[email protected]>Quoted 5 lines
Quoted 3 lines
I see some more instances of '
zone->lock' in comments ininclude/linux/mmzone.hand underDocumentation/but otherwise LGTM.I fixed (most of) that in the previous version but my fix was lost.
Thanks for the fixups, Andrew.
I still see a few '
zone->lock' references in Documentation remain on mm-new. This patch cleans them up, as noted by Vlastimil.I'm happy to adjust this patch if anything else needs attention.
From
9142d5a8b60038fa424a6033253960682e5a51f4Mon Sep 17 00:00:00 2001
From: Dmitry Ilvokhin <[email protected]>
Date: Tue, 3 Mar 2026 06:13:13 -0800
Subject: [PATCH] mm: fix remainingzone->lockreferencesSigned-off-by Dmitry Ilvokhin <[email protected]>--- Documentation/mm/physical_memory.rst | 4 ++-- Documentation/trace/events-kmem.rst | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-)Documentation/mm/physical_memory.rst +0
-0Documentation/mm/physical_memory.rst General · line 503
Quoted 5 lines
Documentation/mm/physical_memory.rst +1
-1@@ -500,11 +500,11 @@ General ``nr_isolate_pageblock`` Number of isolated pageblocks. It is used to solve incorrect freepage counting problem due to racy retrieving migratetype of pageblock. Protected by - ``zone->lock``. Defined only when ``CONFIG_MEMORY_ISOLATION`` is enabled. + ``zone_lock``. Defined only when ``CONFIG_MEMORY_ISOLATION`` is enabled.Dmitry's original patch [1] was doing 's/zone->lock/zone->_lock/', which aligns to my expectation. But this patch is doing 's/zone->lock/zone_lock/'. Same for the rest of this patch.
Quoted 6 lines
I was initially thinking this is just a mistake, but I also found Andrew is doing same change [2], so I'm bit confused. Is this an intentional change?
[1] https://lore.kernel.org/d61500c5784c64e971f4d328c57639303c475f81.1772206930.git.d@ilvokhin.com
[2] https://lore.kernel.org/[email protected]Good catch, thanks for pointing this out, SJ.
Quoted 7 lines
Originally the mechanical rename was indeed
zone->lock->zone->_lock. However, in Documentation I intentionally switched references tozone_lockinstead ofzone->_lock. The reasoning is that_lockis now an internal implementation detail, and direct access is discouraged. The intended interface is via the zone_lock_*() / zone_unlock_*() wrappers, so referencingzone_lockin documentation felt more appropriate than mentioning the private struct field (zone->_lock).Thank you for this nice and kind clarification, Dmitry! I agree mentioning zone_[un]lock_*() helpers instead of the hidden member (
zone->_lock) can be better.But, I'm concerned if people like me might not aware the intention under '
zone_lock'. If there is a well-known convention that allows people to know it is for 'zone_[un]lock_*()' helpers, making it more clear would be nice, in my humble opinion. If there is such a convention but I'm just missing it, please ignore. If I'm not, for eaxmaple,"protected by ``zone->lock``" could be re-wrote to "protected by ``zone_[un]lock_*()`` locking helpers" or, "protected by zone lock helper functions (``zone_[un]lock_*()``)" ?
Quoted 7 lines
That said, I agree this creates inconsistency with the mechanical rename, and I'm happy to adjust either way: either consistently refer to the wrapper API, or keep documentation aligned with
zone->_lock.I slightly prefer referring to the wrapper API, but don't have a strong preference as long as we're consistent.
Quoted 8 lines
Quoted 2 lines
I also think both approaches are good. But for the wrapper approach, I think giving more contexts rather than just ``zone_lock`` to readers would be nice.
Grep tells me that we also have comments mentioning simply "zone lock", btw. And it's also a term used often in informal conversations. Maybe we could just standardize on that in comments/documentations as it's easier to read. Discovering that the field is called
_lockand that wrappers should be used, is hopefully not that difficult.
Quoted 3 lines
Thanks for the suggestion, Vlastimil. That sounds reasonable to me as well. I'll update the comments and documentation to consistently use "zone lock".
Following the suggestion from SJ and Vlastimil, I prepared fixup to standardize documentation and comments on the term "zone lock".
The patch is based on top of the current mm-new.
Andrew, please let me know if you would prefer a respin of the series instead.
From 267cda3e0e160f97b346009bc48819bfeed92e52 Mon Sep 17 00:00:00 2001
From: Dmitry Ilvokhin <[email protected]>
Date: Thu, 5 Mar 2026 10:36:17 -0800
Subject: [PATCH] mm: documentation: standardize on "zone lock" terminology
During review of the zone lock tracing series it was suggested to standardize documentation and comments on the term "zone lock" instead of using zone_lock or referring to the internal field zone->_lock.
Update references accordingly.
--- Documentation/mm/physical_memory.rst | 4 ++-- Documentation/trace/events-kmem.rst | 8 ++++---- mm/compaction.c | 2 +- mm/internal.h | 2 +- mm/page_alloc.c | 12 ++++++------ mm/page_isolation.c | 4 ++-- mm/page_owner.c | 2 +- 7 files changed, 17 insertions(+), 17 deletions(-)
Documentation/mm/physical_memory.rst +2 -2
@@ -500,11 +500,11 @@ General ``nr_isolate_pageblock`` Number of isolated pageblocks. It is used to solve incorrect freepage counting problem due to racy retrieving migratetype of pageblock. Protected by - ``zone_lock``. Defined only when ``CONFIG_MEMORY_ISOLATION`` is enabled. + zone lock. Defined only when ``CONFIG_MEMORY_ISOLATION`` is enabled. ``span_seqlock`` The seqlock to protect ``zone_start_pfn`` and ``spanned_pages``. It is a - seqlock because it has to be read outside of ``zone_lock``, and it is done in + seqlock because it has to be read outside of zone lock, and it is done in the main allocator path. However, the seqlock is written quite infrequently. Defined only when ``CONFIG_MEMORY_HOTPLUG`` is enabled.
Documentation/trace/events-kmem.rst +4 -4
@@ -57,7 +57,7 @@ the per-CPU allocator (high performance) or the buddy allocator. If pages are allocated directly from the buddy allocator, the mm_page_alloc_zone_locked event is triggered. This event is important as high -amounts of activity imply high activity on the zone_lock. Taking this lock +amounts of activity imply high activity on the zone lock. Taking this lock impairs performance by disabling interrupts, dirtying cache lines between CPUs and serialising many CPUs.
@@ -79,11 +79,11 @@ contention on the lruvec->lru_lock. mm_page_pcpu_drain page=%p pfn=%lu order=%d cpu=%d migratetype=%d In front of the page allocator is a per-cpu page allocator. It exists only -for order-0 pages, reduces contention on the zone_lock and reduces the +for order-0 pages, reduces contention on the zone lock and reduces the amount of writing on struct page. When a per-CPU list is empty or pages of the wrong type are allocated, -the zone_lock will be taken once and the per-CPU list refilled. The event +the zone lock will be taken once and the per-CPU list refilled. The event triggered is mm_page_alloc_zone_locked for each page allocated with the event indicating whether it is for a percpu_refill or not.
@@ -92,7 +92,7 @@ which triggers a mm_page_pcpu_drain event. The individual nature of the events is so that pages can be tracked between allocation and freeing. A number of drain or refill pages that occur -consecutively imply the zone_lock being taken once. Large amounts of per-CPU +consecutively imply the zone lock being taken once. Large amounts of per-CPU refills and drains could imply an imbalance between CPUs where too much work is being concentrated in one place. It could also indicate that the per-CPU lists should be a larger size. Finally, large amounts of refills on one CPU
mm/compaction.c +1 -1
@@ -1419,7 +1419,7 @@ static bool suitable_migration_target(struct compact_control *cc,int order = cc->order >0 ? cc->order : pageblock_order;/* -* We are checking page_order without zone->_lock taken. But +* We are checking page_order without zone lock taken. But * the only small danger is that we skip a potentially suitable * pageblock, so it's not worth to check order for valid range. */
mm/internal.h +1 -1
@@ -727,7 +727,7 @@ static inline unsigned int buddy_order(struct page *page)* (d) a page and its buddy are in the same zone. * * For recording whether a page is in the buddy system, we set PageBuddy. -* Setting, clearing, and testing PageBuddy is serialized by zone->_lock. +* Setting, clearing, and testing PageBuddy is serialized by zone lock. * * For recording page's order, we use page_private(page). */
mm/page_alloc.c +6 -6
@@ -2440,7 +2440,7 @@ enum rmqueue_mode {/* * Do the hard work of removing an element from the buddy allocator. -* Call me with the zone->_lock already held. +* Call me with the zone lock already held. */ static __always_inline struct page * __rmqueue(struct zone *zone, unsigned int order, int migratetype,
@@ -2468,7 +2468,7 @@ __rmqueue(struct zone *zone, unsigned int order, int migratetype,* fallbacks modes with increasing levels of fragmentation risk. * * The fallback logic is expensive and rmqueue_bulk() calls in -* a loop with the zone->_lock held, meaning the freelists are +* a loop with the zone lock held, meaning the freelists are * not subject to any outside changes. Remember in *mode where * we found pay dirt, to save us the search on the next call. */
@@ -7046,7 +7046,7 @@ int alloc_contig_frozen_range_noprof(unsigned long start, unsigned long end,* pages. Because of this, we reserve the bigger range and * once this is done free the pages we are not interested in. * -* We don't have to hold zone->_lock here because the pages are +* We don't have to hold zone lock here because the pages are * isolated thus they won't get removed from buddy. */ outer_start =find_large_buddy (start);
@@ -7615,7 +7615,7 @@ void accept_page(struct page *page)return ; } -/* Unlocks zone->_lock */ +/* Unlocks zone lock */ __accept_page (zone, &flags, page); }
@@ -7632,7 +7632,7 @@ static bool try_to_accept_memory_one(struct zone *zone)return false; } -/* Unlocks zone->_lock */ +/* Unlocks zone lock */ __accept_page (zone, &flags, page);return true;
@@ -7773,7 +7773,7 @@ struct page *alloc_frozen_pages_nolock_noprof(gfp_t gfp_flags, int nid, unsigned/* * Best effort allocation from percpu free list. -* If it's empty attempt to spin_trylock zone->_lock. +* If it's empty attempt to spin_trylock zone lock. */ page =get_page_from_freelist (alloc_gfp, order, alloc_flags, &ac);
mm/page_isolation.c +2 -2
@@ -212,7 +212,7 @@ static int set_migratetype_isolate(struct page *page, enum pb_isolate_mode mode,zone_unlock_irqrestore (zone, flags);if (mode ==PB_ISOLATE_MODE_MEM_OFFLINE ) {/* -* printk() with zone->_lock held will likely trigger a +* printk() with zone lock held will likely trigger a * lockdep splat, so defer it here. */ dump_page (unmovable,"unmovable page" );
@@ -553,7 +553,7 @@ void undo_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn)/* * Test all pages in the range is free(means isolated) or not. * all pages in [start_pfn...end_pfn) must be in the same zone. -* zone->_lock must be held before call this. +* zone lock must be held before call this. * * Returns the last tested pfn. */
mm/page_owner.c +1 -1
@@ -799,7 +799,7 @@ static void init_pages_in_zone(struct zone *zone)continue ;/* -* To avoid having to grab zone->_lock, be a little +* To avoid having to grab zone lock, be a little * careful when reading buddy page order. The only * danger is that we skip too much and potentially miss * some early allocated pages, which is better than
Signature · 1 line
2.47.3
SeongJae Park
Acked-byRe: [PATCH v4 4/5] mm: rename zone->lock to zone->_lock
On Thu, 5 Mar 2026 18:59:43 +0000 Dmitry Ilvokhin <[email protected]> wrote:
[...]
Quoted 13 lines
Following the suggestion from SJ and Vlastimil, I prepared fixup to standardize documentation and comments on the term "zone lock".
The patch is based on top of the current mm-new.
Andrew, please let me know if you would prefer a respin of the series instead.
From
267cda3e0e160f97b346009bc48819bfeed92e52Mon Sep 17 00:00:00 2001
From: Dmitry Ilvokhin <[email protected]>
Date: Thu, 5 Mar 2026 10:36:17 -0800
Subject: [PATCH] mm: documentation: standardize on "zone lock" terminology
Quoted 8 lines
During review of the zone lock tracing series it was suggested to standardize documentation and comments on the term "zone lock" instead of using
zone_lockor referring to the internal fieldzone->_lock.Update references accordingly.
Signed-off-by Dmitry Ilvokhin <[email protected]>
THanks,
SJ
[...]
Re: [PATCH v4 4/5] mm: rename zone->lock to zone->_lock
In reply to Dmitry IlvokhinQuoted 129 lines · Dmitry Ilvokhin
Quoted 111 lines · Dmitry Ilvokhin
Quoted 101 lines · Vlastimil Babka (SUSE)
Quoted 100 lines · SeongJae Park
Quoted 68 lines · On Wed, 4 Mar 2026 13:01:45 +0000 Dmitry Ilvokhin <[email protected]> wrote:
Quoted 58 lines · SeongJae Park
Quoted 46 lines · On Tue, 3 Mar 2026 14:25:55 +0000 Dmitry Ilvokhin <[email protected]> wrote:
Quoted 16 lines · Andrew Morton
Quoted 14 lines · On Mon, 2 Mar 2026 15:10:03 +0100 "Vlastimil Babka (SUSE)" <[email protected]>…
Quoted 12 lines · Dmitry Ilvokhin
This intentionally breaks direct users of
zone->lockat compile time so all call sites are converted to the zone lock wrappers. Without the rename, present and future out-of-tree code could continue usingspin_lock(&zone->lock)and bypass the wrappers and tracing infrastructure.No functional change intended.
Suggested-by Andrew Morton <[email protected]>Signed-off-by Dmitry Ilvokhin <[email protected]>Acked-by Shakeel Butt <[email protected]>Acked-by SeongJae Park <[email protected]>Quoted 5 lines
Quoted 3 lines
I see some more instances of '
zone->lock' in comments ininclude/linux/mmzone.hand underDocumentation/but otherwise LGTM.I fixed (most of) that in the previous version but my fix was lost.
Thanks for the fixups, Andrew.
I still see a few '
zone->lock' references in Documentation remain on mm-new. This patch cleans them up, as noted by Vlastimil.I'm happy to adjust this patch if anything else needs attention.
From
9142d5a8b60038fa424a6033253960682e5a51f4Mon Sep 17 00:00:00 2001
From: Dmitry Ilvokhin <[email protected]>
Date: Tue, 3 Mar 2026 06:13:13 -0800
Subject: [PATCH] mm: fix remainingzone->lockreferencesSigned-off-by Dmitry Ilvokhin <[email protected]>--- Documentation/mm/physical_memory.rst | 4 ++-- Documentation/trace/events-kmem.rst | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-)Documentation/mm/physical_memory.rst +0
-0Documentation/mm/physical_memory.rst General · line 503
Quoted 5 lines
Documentation/mm/physical_memory.rst +1
-1@@ -500,11 +500,11 @@ General ``nr_isolate_pageblock`` Number of isolated pageblocks. It is used to solve incorrect freepage counting problem due to racy retrieving migratetype of pageblock. Protected by - ``zone->lock``. Defined only when ``CONFIG_MEMORY_ISOLATION`` is enabled. + ``zone_lock``. Defined only when ``CONFIG_MEMORY_ISOLATION`` is enabled.Dmitry's original patch [1] was doing 's/zone->lock/zone->_lock/', which aligns to my expectation. But this patch is doing 's/zone->lock/zone_lock/'. Same for the rest of this patch.
Quoted 6 lines
I was initially thinking this is just a mistake, but I also found Andrew is doing same change [2], so I'm bit confused. Is this an intentional change?
[1] https://lore.kernel.org/d61500c5784c64e971f4d328c57639303c475f81.1772206930.git.d@ilvokhin.com
[2] https://lore.kernel.org/[email protected]Good catch, thanks for pointing this out, SJ.
Quoted 7 lines
Originally the mechanical rename was indeed
zone->lock->zone->_lock. However, in Documentation I intentionally switched references tozone_lockinstead ofzone->_lock. The reasoning is that_lockis now an internal implementation detail, and direct access is discouraged. The intended interface is via the zone_lock_*() / zone_unlock_*() wrappers, so referencingzone_lockin documentation felt more appropriate than mentioning the private struct field (zone->_lock).Thank you for this nice and kind clarification, Dmitry! I agree mentioning zone_[un]lock_*() helpers instead of the hidden member (
zone->_lock) can be better.But, I'm concerned if people like me might not aware the intention under '
zone_lock'. If there is a well-known convention that allows people to know it is for 'zone_[un]lock_*()' helpers, making it more clear would be nice, in my humble opinion. If there is such a convention but I'm just missing it, please ignore. If I'm not, for eaxmaple,"protected by ``zone->lock``" could be re-wrote to "protected by ``zone_[un]lock_*()`` locking helpers" or, "protected by zone lock helper functions (``zone_[un]lock_*()``)" ?
Quoted 7 lines
That said, I agree this creates inconsistency with the mechanical rename, and I'm happy to adjust either way: either consistently refer to the wrapper API, or keep documentation aligned with
zone->_lock.I slightly prefer referring to the wrapper API, but don't have a strong preference as long as we're consistent.
Quoted 8 lines
Quoted 2 lines
I also think both approaches are good. But for the wrapper approach, I think giving more contexts rather than just ``zone_lock`` to readers would be nice.
Grep tells me that we also have comments mentioning simply "zone lock", btw. And it's also a term used often in informal conversations. Maybe we could just standardize on that in comments/documentations as it's easier to read. Discovering that the field is called
_lockand that wrappers should be used, is hopefully not that difficult.Quoted 3 lines
Thanks for the suggestion, Vlastimil. That sounds reasonable to me as well. I'll update the comments and documentation to consistently use "zone lock".
Following the suggestion from SJ and Vlastimil, I prepared fixup to standardize documentation and comments on the term "zone lock".
The patch is based on top of the current mm-new.
Andrew, please let me know if you would prefer a respin of the series instead.
From
267cda3e0e160f97b346009bc48819bfeed92e52Mon Sep 17 00:00:00 2001
From: Dmitry Ilvokhin <[email protected]>
Date: Thu, 5 Mar 2026 10:36:17 -0800
Subject: [PATCH] mm: documentation: standardize on "zone lock" terminology
Quoted 8 lines
During review of the zone lock tracing series it was suggested to standardize documentation and comments on the term "zone lock" instead of using
zone_lockor referring to the internal fieldzone->_lock.Update references accordingly.
Signed-off-by Dmitry Ilvokhin <[email protected]>
Thanks!
Re: [PATCH v4 4/5] mm: rename zone->lock to zone->_lock
In reply to Dmitry IlvokhinQuoted 27 lines · Dmitry Ilvokhin
This intentionally breaks direct users of
zone->lockat compile time so all call sites are converted to the zone lock wrappers. Without the rename, present and future out-of-tree code could continue usingspin_lock(&zone->lock)and bypass the wrappers and tracing infrastructure.No functional change intended.
Suggested-by Andrew Morton <[email protected]>Signed-off-by Dmitry Ilvokhin <[email protected]>Acked-by Shakeel Butt <[email protected]>Acked-by SeongJae Park <[email protected]>--- include/linux/mmzone.h | 7 +++++-- include/linux/mmzone_lock.h | 12 ++++++------ mm/compaction.c | 4 ++-- mm/internal.h | 2 +- mm/page_alloc.c | 16 ++++++++-------- mm/page_isolation.c | 4 ++-- mm/page_owner.c | 2 +- 7 files changed, 25 insertions(+), 22 deletions(-)include/linux/mmzone.h +0
-0
include/linux/mmzone.h struct zone { · line 1016
Quoted 10 lines
include/linux/mmzone.h +5
-2@@ -1009,8 +1009,11 @@ struct zone {/* zone flags, see below */ unsigned long flags; -/* Primarily protects free_area */ -spinlock_t lock; +/* +* Primarily protects free_area. Should be accessed via zone_lock_* +* helpers. +*/ +spinlock_t _lock;
I really don't like this uglification.
Suggestion:
spinlock_t __private lock;
include/linux/mmzone_lock.h line 10
Quoted 12 lines
include/linux/mmzone.h +0
-0/* Pages to be freed when next trylock succeeds */ struct llist_head trylock_free_pages;include/linux/mmzone_lock.h +0
-1@@ -7,32 +7,32 @@static inline void zone_lock_init (struct zone *zone) { -spin_lock_init (&zone->lock);
and then ACCESS_PRIVATE() all over these helpers. This will not make a difference to the compiler, but it will work with sparse.
It's not that I don't understand what you're doing, but we're going to need to look to this code and refer to this code 20 years from now, I would rather not refer to zone->_lock :)
Signature · 1 line
Pedro
PATCH v4 5/5 mm: add tracepoints for zone lock
In reply to Dmitry IlvokhinAdd tracepoint instrumentation to zone lock acquire/release operations via the previously introduced wrappers.
The implementation follows the mmap_lock tracepoint pattern: a lightweight inline helper checks whether the tracepoint is enabled and calls into an out-of-line helper when tracing is active. When CONFIG_TRACING is disabled, helpers compile to empty inline stubs.
The fast path is unaffected when tracing is disabled.
--- MAINTAINERS | 1 + include/linux/mmzone_lock.h | 64 +++++++++++++++++++++++++++++++- include/trace/events/zone_lock.h | 64 ++++++++++++++++++++++++++++++++ mm/Makefile | 2 +- mm/zone_lock.c | 28 ++++++++++++++ 5 files changed, 157 insertions(+), 2 deletions(-) create mode 100644 include/trace/events/zone_lock.h create mode 100644 mm/zone_lock.c
MAINTAINERS +1 -0
@@ -16681,6 +16681,7 @@ F: include/linux/pgtable.h F: include/linux/ptdump.h F: include/linux/vmpressure.h F: include/linux/vmstat.h +F: include/trace/events/zone_lock.h F: kernel/fork.c F: mm/Kconfig F: mm/debug.c
include/linux/mmzone_lock.h +63 -1
95 lines not on this page · raw message
include/trace/events/zone_lock.h new file +64 -0
64 lines not on this page · raw message
mm/Makefile +1 -1
@@ -55,7 +55,7 @@ obj-y := filemap.o mempool.o oom_kill.o fadvise.o \ mm_init.o percpu.o slab_common.o \ compaction.o show_mem.o \ interval_tree.o list_lru.o workingset.o \ - debug.o gup.o mmap_lock.o vma_init.o $(mmu-y) + debug.o gup.o mmap_lock.o zone_lock.o vma_init.o $(mmu-y) # Give 'page_alloc' its own module-parameter namespace page-alloc-y := page_alloc.o
mm/zone_lock.c new file +28 -0
@@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-2.0 +#define CREATE_TRACE_POINTS +#include <trace/events/zone_lock.h> + +#include <linux/mmzone_lock.h> + +EXPORT_TRACEPOINT_SYMBOL (zone_lock_start_locking); +EXPORT_TRACEPOINT_SYMBOL (zone_lock_acquire_returned); +EXPORT_TRACEPOINT_SYMBOL (zone_lock_released); + +#ifdef CONFIG_TRACING + +void __zone_lock_do_trace_start_locking (struct zone *zone) +{ +trace_zone_lock_start_locking (zone); +} + +void __zone_lock_do_trace_acquire_returned (struct zone *zone,bool success) +{ +trace_zone_lock_acquire_returned (zone, success); +} + +void __zone_lock_do_trace_released (struct zone *zone) +{ +trace_zone_lock_released (zone); +} + +#endif /* CONFIG_TRACING */
Signature · 1 line
2.47.3
Steven Rostedt
maintainerRe: [PATCH v4 5/5] mm: add tracepoints for zone lock
include/linux/mmzone_lock.h static inline void zone_lock_init(struct zone *zone) · line 66
Quoted 11 lines · On Fri, 27 Feb 2026 16:00:27 +0000 Dmitry Ilvokhin <[email protected]> wrote:
static inline void
zone_lock_init(struct zone *zone){include/linux/mmzone_lock.h +4
-0@@ -12,26 +59,41 @@ static inline void zone_lock_init(struct zone *zone)#define zone_lock_irqsave (zone, flags) \ do { \ + bool success = true; \ + \ + __zone_lock_trace_start_locking(zone); \ spin_lock_irqsave(&(zone)->_lock, flags); \ + __zone_lock_trace_acquire_returned(zone, success); \
Why the "success" variable and not just:
__zone_lock_trace_acquire_returned(zone, true);
?
Quoted 16 lines
include/linux/mmzone_lock.h +7
-1} while (0)#define zone_trylock_irqsave (zone, flags) \ ({ \ - spin_trylock_irqsave(&(zone)->_lock, flags); \ + bool success; \ + \ + __zone_lock_trace_start_locking(zone); \ + success = spin_trylock_irqsave(&(zone)->_lock, flags); \ + __zone_lock_trace_acquire_returned(zone, success); \ + success; \ })static inline void zone_unlock_irqrestore (struct zone *zone,unsigned long flags) { +__zone_lock_trace_released (zone);
include/linux/mmzone_lock.h static inline void zone_lock_init(struct zone *zone) · line 91
Quoted 10 lines
include/linux/mmzone_lock.h +4
-0spin_unlock_irqrestore (&zone->_lock, flags); }static inline void zone_lock_irq (struct zone *zone) { +bool success = true; + +__zone_lock_trace_start_locking (zone);spin_lock_irq (&zone->_lock); +__zone_lock_trace_acquire_returned (zone, success);
Same here.
include/linux/mmzone_lock.h static inline void zone_lock_init(struct zone *zone) · line 99
Quoted 8 lines
include/linux/mmzone_lock.h +1
-0}static inline void zone_unlock_irq (struct zone *zone) { +__zone_lock_trace_released (zone);spin_unlock_irq (&zone->_lock); }
-- Steve
Re: [PATCH v4 5/5] mm: add tracepoints for zone lock
Quoted 17 lines · Steven Rostedt
include/linux/mmzone_lock.h static inline void zone_lock_init(struct zone *zone) · line 66
Quoted 11 lines · On Fri, 27 Feb 2026 16:00:27 +0000 Dmitry Ilvokhin <[email protected]> wrote:
static inline void
zone_lock_init(struct zone *zone){include/linux/mmzone_lock.h +4
-0@@ -12,26 +59,41 @@ static inline void zone_lock_init(struct zone *zone)#define zone_lock_irqsave (zone, flags) \ do { \ + bool success = true; \ + \ + __zone_lock_trace_start_locking(zone); \ spin_lock_irqsave(&(zone)->_lock, flags); \ + __zone_lock_trace_acquire_returned(zone, success); \Why the "success" variable and not just:
Quoted 3 lines
__zone_lock_trace_acquire_returned(zone, true);?
Good point, passing true directly is cleaner. Happy to respin if needed.
Re: [PATCH v4 5/5] mm: add tracepoints for zone lock
In reply to Dmitry IlvokhinQuoted 8 lines · Dmitry Ilvokhin
Add tracepoint instrumentation to zone lock acquire/release operations via the previously introduced wrappers.
The implementation follows the
mmap_locktracepoint pattern: a lightweight inline helper checks whether the tracepoint is enabled and calls into an out-of-line helper when tracing is active. WhenCONFIG_TRACINGis disabled, helpers compile to empty inline stubs.
Quoted 4 lines
The fast path is unaffected when tracing is disabled.
Signed-off-by Dmitry Ilvokhin <[email protected]>Acked-by Shakeel Butt <[email protected]>
Agree with Steven; otherwise
Quoted 18 lines · Dmitry Ilvokhin
Zone lock contention can significantly impact allocation and reclaim latency, as it is a central synchronization point in the page allocator and reclaim paths. Improved visibility into its behavior is therefore important for diagnosing performance issues in memory-intensive workloads.
On some production workloads at Meta, we have observed noticeable zone lock contention. Deeper analysis of lock holders and waiters is currently difficult with existing instrumentation.
While generic lock contention_begin/contention_end tracepoints cover the slow path, they do not provide sufficient visibility into lock hold times. In particular, the lack of a release-side event makes it difficult to identify long lock holders and correlate them with waiters. As a result, distinguishing between short bursts of contention and pathological long hold times requires additional instrumentation.
Quoted 2 lines
This patch series adds dedicated tracepoint instrumentation to zone lock, following the existing
mmap_locktracing model.
I don't like this at all. We have CONFIG_LOCK_STAT. That should be improved insted of coming up with one-offs for every single lock that someone deems "special".
Quoted 19 lines · Matthew Wilcox
Quoted 18 lines · Dmitry Ilvokhin
Zone lock contention can significantly impact allocation and reclaim latency, as it is a central synchronization point in the page allocator and reclaim paths. Improved visibility into its behavior is therefore important for diagnosing performance issues in memory-intensive workloads.
On some production workloads at Meta, we have observed noticeable zone lock contention. Deeper analysis of lock holders and waiters is currently difficult with existing instrumentation.
While generic lock contention_begin/contention_end tracepoints cover the slow path, they do not provide sufficient visibility into lock hold times. In particular, the lack of a release-side event makes it difficult to identify long lock holders and correlate them with waiters. As a result, distinguishing between short bursts of contention and pathological long hold times requires additional instrumentation.
Quoted 6 lines
Quoted 2 lines
This patch series adds dedicated tracepoint instrumentation to zone lock, following the existing
mmap_locktracing model.I don't like this at all. We have
CONFIG_LOCK_STAT. That should be improved insted of coming up with one-offs for every single lock that someone deems "special".
Thanks for the feedback, Matthew.
CONFIG_LOCK_STAT provides useful statistics, but it is primarily a debug facility and is generally too heavyweight for the production environments.
The motivation for this series was to provide lightweight observability for the zone lock in production workloads.
I agree that improving generic lock instrumentation would be preferable. I did consider whether something similar could be done generically for spinlocks, but the unlock path there is typically just a single atomic store, so adding generic lightweight instrumentation without affecting the fast path is difficult.
In parallel, I've been experimenting with improving observability for sleepable locks by adding a contended_release tracepoint, which would allow correlating lock holders and waiters in a more generic way. I've posted an RFC here:
https://lore.kernel.org/all/[email protected]/
I'd appreciate feedback on whether that direction makes sense for improving the generic lock tracing infrastructure.
Quoted 9 lines · Dmitry Ilvokhin
Quoted 7 lines · Matthew Wilcox
Quoted 2 lines · Dmitry Ilvokhin
This patch series adds dedicated tracepoint instrumentation to zone lock, following the existing
mmap_locktracing model.I don't like this at all. We have
CONFIG_LOCK_STAT. That should be improved insted of coming up with one-offs for every single lock that someone deems "special".
Quoted 5 lines
Thanks for the feedback, Matthew.
CONFIG_LOCK_STATprovides useful statistics, but it is primarily a debug facility and is generally too heavyweight for the production environments.
Yes, agreed. I think that is what needs to change.
Quoted 2 lines
The motivation for this series was to provide lightweight observability for the zone lock in production workloads.
I read that. But first it was the mmap lock. Now it's the zone lock. Which lock will be next? This is too heavyweight a procedure to follow for each lock of interest.
Quoted 5 lines
I agree that improving generic lock instrumentation would be preferable. I did consider whether something similar could be done generically for spinlocks, but the unlock path there is typically just a single atomic store, so adding generic lightweight instrumentation without affecting the fast path is difficult.
This is why we have tracepoint_enabled() and friends. But ... LOCK_STAT doesn't affect the unlock path at all. It only changes the acquire side to call lock_acquired() (and lock_contended() if the trylock failed).
Quoted 9 lines
In parallel, I've been experimenting with improving observability for sleepable locks by adding a
contended_releasetracepoint, which would allow correlating lock holders and waiters in a more generic way. I've posted an RFC here:https://lore.kernel.org/all/[email protected]/
I'd appreciate feedback on whether that direction makes sense for improving the generic lock tracing infrastructure.
It seems fine to me, but I don't have the depth in the locking code to give it the thorough review it deserves.
Steven Rostedt
maintainerQuoted 5 lines · On Mon, 9 Mar 2026 14:47:29 +0000 Matthew Wilcox <[email protected]> wrote:
Quoted 3 lines
CONFIG_LOCK_STATprovides useful statistics, but it is primarily a debug facility and is generally too heavyweight for the production environments.Yes, agreed. I think that is what needs to change.
The biggest issue with making a generic light weight LOCK_STAT is that locks are extremely optimized. Any addition of generic lock encoding will cause a noticeable overhead when compiled in, even when disabled.
Most of the lock code is inlined for the fast path. Now if we want to add lock stats, we would need to add hooks into those inlined paths. This will undoubtedly increase the size of text, which will have an impact on I$.
The other issue is the data we store for the lock. A lock is usually just a word (or long) in size, embedded in a structure. LOCKDEP and LOCK_STAT adds a key per lock. This increases the data size of the kernel.
LOCK_STAT was designed on top of LOCKDEP. Perhaps a lighter version of LOCK_STAT could be designed without LOCKDEP, but it would be a project on its own.
-- Steve
Quoted 3 lines · Steven Rostedt
The biggest issue with making a generic light weight
LOCK_STATis that locks are extremely optimized. Any addition of generic lock encoding will cause a noticeable overhead when compiled in, even when disabled.
I'm not sure that's true. Taking the current Debian kernel config leads to a "call" instruction to acquire a spinlock:
void __insert_inode_hash(struct inode *inode, unsigned long hashval)
{
struct hlist_head *b = inode_hashtable + hash(inode->i_sb, hashval);
spin_lock(&inode_hash_lock);
spin_lock(&inode->i_lock);
hlist_add_head_rcu(&inode->i_hash, b);
spin_unlock(&inode->i_lock);
spin_unlock(&inode_hash_lock);
}compiles to:
[...]
280: 23 35 00 00 00 00 and 0x0(%rip),%esi # 286 <__insert_inode_hash+0x56>
282: R_X86_64_PC32 .data..ro_after_init+0x10
286: 48 8d 2c f0 lea (%rax,%rsi,8),%rbp
28a: e8 00 00 00 00 call 28f <__insert_inode_hash+0x5f>
28b: R_X86_64_PLT32 _raw_spin_lock-0x4
28f: 4c 89 e7 mov %r12,%rdi
292: e8 00 00 00 00 call 297 <__insert_inode_hash+0x67>
293: R_X86_64_PLT32 _raw_spin_lock-0x4[...]
Debian doesn't do anything too weird here:
#
# Lock Debugging (spinlocks, mutexes, etc...)
#CONFIG_LOCK_DEBUGGING_SUPPORT=y
# CONFIG_PROVE_LOCKING is not set
# CONFIG_LOCK_STAT is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_DEBUG_MUTEXES is not set
# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set
# CONFIG_DEBUG_RWSEMS is not set
# CONFIG_DEBUG_LOCK_ALLOC is not set
# CONFIG_DEBUG_ATOMIC_SLEEP is not set
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
# CONFIG_LOCK_TORTURE_TEST is not set
# CONFIG_WW_MUTEX_SELFTEST is not set
# CONFIG_SCF_TORTURE_TEST is not set
# CONFIG_CSD_LOCK_WAIT_DEBUG is not set
(The spinlock code is too complex for me to follow what config options influence whether it's a function call; you probably have enough of it in your head that you'd know)
Quoted 3 lines
The other issue is the data we store for the lock. A lock is usually just a word (or long) in size, embedded in a structure. LOCKDEP and
LOCK_STATadds a key per lock. This increases the data size of the kernel.
It does, but perhaps for a light weight lockstat, we could do better than that. For example it could use the return address to look up which lock is being accessed rather than embedding a key in each lock.
Steven Rostedt
maintainerQuoted 30 lines · On Mon, 9 Mar 2026 20:45:31 +0000 Matthew Wilcox <[email protected]> wrote:
Quoted 3 lines · Steven Rostedt
The biggest issue with making a generic light weight
LOCK_STATis that locks are extremely optimized. Any addition of generic lock encoding will cause a noticeable overhead when compiled in, even when disabled.I'm not sure that's true. Taking the current Debian kernel config leads to a "call" instruction to acquire a spinlock:
void
__insert_inode_hash(struct inode *inode, unsigned long hashval){ struct hlist_head *b = inode_hashtable + hash(inode->i_sb, hashval); spin_lock(&inode_hash_lock); spin_lock(&inode->i_lock); hlist_add_head_rcu(&inode->i_hash, b); spin_unlock(&inode->i_lock); spin_unlock(&inode_hash_lock); }compiles to:
[...]
280: 23 35 00 00 00 00 and 0x0(%rip),%esi # 286 <__insert_inode_hash+0x56> 282: R_X86_64_PC32 .data..ro_after_init+0x10 286: 48 8d 2c f0 lea (%rax,%rsi,8),%rbp 28a: e8 00 00 00 00 call 28f <__insert_inode_hash+0x5f> 28b: R_X86_64_PLT32 _raw_spin_lock-0x4 28f: 4c 89 e7 mov %r12,%rdi 292: e8 00 00 00 00 call 297 <__insert_inode_hash+0x67> 293: R_X86_64_PLT32 _raw_spin_lock-0x4
Quoted 1 line
[...]
Ah, you're correct. Looks like it's an arch specific thing. I was going back to my memory from around 2006, but it appears that only a few archs inline spinlocks anymore. Thomas made it a bit easier to see what does and does not do that (in 2009).
6beb000923882 ("locking: Make inlining decision Kconfig based")
So, perhaps adding code to the spinlocks will not be as much of a hit on I$.
Quoted 3 lines
(The spinlock code is too complex for me to follow what config options influence whether it's a function call; you probably have enough of it in your head that you'd know)
Yeah, I feel like I'm always relearning the code every time I have to jump in and understand it again.
Quoted 8 lines
Quoted 4 lines
The other issue is the data we store for the lock. A lock is usually just a word (or long) in size, embedded in a structure. LOCKDEP and
LOCK_STATadds a key per lock. This increases the data size of the kernel.It does, but perhaps for a light weight lockstat, we could do better than that. For example it could use the return address to look up which lock is being accessed rather than embedding a key in each lock.
Right.
-- Steve
Thanks for the discussion and for the feedback on generic lock instrumentation.
Following up on the earlier points about lightweight LOCK_STAT and tracepoints.
While the thread has focused on spin_lock() calls, the real gap is on the unlock path: there is currently no release-side tracepoint to correlate holders and waiters or measure contended hold times.
A possible generic solution is a trace_contended_release() for spin locks, for example:
if (trace_contended_release_enabled() &&
atomic_read(&lock->val) & ~_Q_LOCKED_MASK)
trace_contended_release(lock);This might work on x86, but could increase code size and regress performance on arches where spin_unlock() is inlined, such as arm64 under !PREEMPTION.
So even a generic release-side tracepoint has nontrivial downsides (not to mention lightweight LOCK_STAT, since a disabled tracepoint is about as lightweight as it gets, the more stats we add, the less lightweight the mechanism becomes).
The zone lock wrappers provide a practical, production-safe solution to observe this specific high-contention lock, if the generic approach proves impractical.
On Mon, Mar 16, 2026 at 05:40:50PM +0000, Dmitry Ilvokhin wrote:
[...]
Quoted 10 lines
A possible generic solution is a
trace_contended_release()for spin locks, for example:if (trace_contended_release_enabled() && atomic_read(&lock->val) & ~_Q_LOCKED_MASK) trace_contended_release(lock);This might work on x86, but could increase code size and regress performance on arches where
spin_unlock()is inlined, such as arm64 under !PREEMPTION.
I took a stab at this idea and submitted an RFC [1].
The implementation builds on your earlier observation from Matthew that _raw_spin_unlock() is not inlined in most configurations. In those cases, when the tracepoint is disabled, this adds a single NOP on the fast path, with the conditional check staying out of line. The measured text size increase in this configuration is +983 bytes.
For configurations where _raw_spin_unlock() is inlined, the instrumentation does increase code size more noticeably (+71 KB in my measurements), since the check and out of line call is replicated at each call site.
This provides a generic release-side signal for contended locks,
allowing: correlation of lock holders with waiters and measurement of contended hold times
This RFC addressing the same visibility gap without introducing per-lock instrumentation.
If this tradeoff is acceptable, this could be a generic alternative to lock-specific tracepoints.
[1]: https://lore.kernel.org/all/51aad0415b78c5a39f2029722118fa01eac77538.1773858853.git.d@ilvokhin.com
Andrew Morton
maintainerQuoted 32 lines · On Thu, 19 Mar 2026 13:22:54 +0000 Dmitry Ilvokhin <[email protected]> wrote:
On Mon, Mar 16, 2026 at 05:40:50PM +0000, Dmitry Ilvokhin wrote:
[...]
Quoted 10 lines
A possible generic solution is a
trace_contended_release()for spin locks, for example:if (trace_contended_release_enabled() && atomic_read(&lock->val) & ~_Q_LOCKED_MASK) trace_contended_release(lock);This might work on x86, but could increase code size and regress performance on arches where
spin_unlock()is inlined, such as arm64 under !PREEMPTION.I took a stab at this idea and submitted an RFC [1].
The implementation builds on your earlier observation from Matthew that
_raw_spin_unlock()is not inlined in most configurations. In those cases, when the tracepoint is disabled, this adds a single NOP on the fast path, with the conditional check staying out of line. The measured text size increase in this configuration is +983 bytes.For configurations where
_raw_spin_unlock()is inlined, the instrumentation does increase code size more noticeably (+71 KB in my measurements), since the check and out of line call is replicated at each call site.This provides a generic release-side signal for contended locks,
allowing: correlation of lock holders with waiters and measurement of contended hold times
Quoted 7 lines
This RFC addressing the same visibility gap without introducing per-lock instrumentation.
If this tradeoff is acceptable, this could be a generic alternative to lock-specific tracepoints.
[1]: https://lore.kernel.org/all/51aad0415b78c5a39f2029722118fa01eac77538.1773858853.git.d@ilvokhin.com
That submission has met a disappointing response.
How should I proceed with this series "mm: zone lock tracepoint instrumentation"? It's not urgent so I'm inclined to put this on hold while you pursue "locking: Add contended_release tracepoint to spinning locks"?
Please send that v2 sometime and hopefully Steven can help push it along?
Quoted 40 lines · Andrew Morton
Quoted 38 lines · On Thu, 19 Mar 2026 13:22:54 +0000 Dmitry Ilvokhin <[email protected]> wrote:
On Mon, Mar 16, 2026 at 05:40:50PM +0000, Dmitry Ilvokhin wrote:
[...]
Quoted 10 lines
A possible generic solution is a
trace_contended_release()for spin locks, for example:if (trace_contended_release_enabled() && atomic_read(&lock->val) & ~_Q_LOCKED_MASK) trace_contended_release(lock);This might work on x86, but could increase code size and regress performance on arches where
spin_unlock()is inlined, such as arm64 under !PREEMPTION.I took a stab at this idea and submitted an RFC [1].
The implementation builds on your earlier observation from Matthew that
_raw_spin_unlock()is not inlined in most configurations. In those cases, when the tracepoint is disabled, this adds a single NOP on the fast path, with the conditional check staying out of line. The measured text size increase in this configuration is +983 bytes.For configurations where
_raw_spin_unlock()is inlined, the instrumentation does increase code size more noticeably (+71 KB in my measurements), since the check and out of line call is replicated at each call site.This provides a generic release-side signal for contended locks,
allowing: correlation of lock holders with waiters and measurement of contended hold timesThis RFC addressing the same visibility gap without introducing per-lock instrumentation.
If this tradeoff is acceptable, this could be a generic alternative to lock-specific tracepoints.
Quoted 8 lines
Quoted 1 line
[1]: https://lore.kernel.org/all/51aad0415b78c5a39f2029722118fa01eac77538.1773858853.git.d@ilvokhin.com
That submission has met a disappointing response.
How should I proceed with this series "mm: zone lock tracepoint instrumentation"? It's not urgent so I'm inclined to put this on hold while you pursue "locking: Add
contended_releasetracepoint to spinning locks"?
Thanks for the follow-up, Andrew.
My current plan is to focus on the "locking: Add contended_release tracepoint to spinning locks" work and drive it to a clear conclusion:
either by getting feedback that it's not a good direction, or by getting it into mainline.
In the meantime, it seems reasonable to drop the "mm: zone lock tracepoint instrumentation" patchset from mm-new to avoid confusion until the direction is clearer. I can revisit and respin it if the more generic locking approach doesn't pan out.
Quoted 2 lines
Please send that v2 sometime and hopefully Steven can help push it along?
I'll send the next version of the generic locking series soon. Any help in pushing it along would be appreciated.
Steven Rostedt
maintainerQuoted 4 lines · On Wed, 25 Mar 2026 12:14:35 +0000 Dmitry Ilvokhin <[email protected]> wrote:
Quoted 1 line
Please send that v2 sometime and hopefully Steven can help push it along?
I'll send the next version of the generic locking series soon. Any help in pushing it along would be appreciated.
I'll see what I can do when I see v2!
-- Steve