Add 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.
Signed-off-by: Dmitry Ilvokhin <d@ilvokhin.com>
---
MAINTAINERS | 2 +
include/linux/zone_lock.h | 64 +++++++++++++++++++++++++++++++-
include/trace/events/zone_lock.h | 64 ++++++++++++++++++++++++++++++++
mm/Makefile | 2 +-
mm/zone_lock.c | 31 ++++++++++++++++
5 files changed, 161 insertions(+), 2 deletions(-)
create mode 100644 include/trace/events/zone_lock.h
create mode 100644 mm/zone_lock.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 61e3d1f5bf43..b5aa2bb5d2ba 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -16681,6 +16681,7 @@ F: include/linux/ptdump.h
F: include/linux/vmpressure.h
F: include/linux/vmstat.h
F: include/linux/zone_lock.h
+F: include/trace/events/zone_lock.h
F: kernel/fork.c
F: mm/Kconfig
F: mm/debug.c
@@ -16700,6 +16701,7 @@ F: mm/sparse.c
F: mm/util.c
F: mm/vmpressure.c
F: mm/vmstat.c
+F: mm/zone_lock.c
N: include/linux/page[-_]*
MEMORY MANAGEMENT - EXECMEM
diff --git a/include/linux/zone_lock.h b/include/linux/zone_lock.h
index 5ce1aa38d500..f32ff0fae266 100644
--- a/include/linux/zone_lock.h
+++ b/include/linux/zone_lock.h
@@ -4,6 +4,53 @@
#include <linux/mmzone.h>
#include <linux/spinlock.h>
+#include <linux/tracepoint-defs.h>
+
+DECLARE_TRACEPOINT(zone_lock_start_locking);
+DECLARE_TRACEPOINT(zone_lock_acquire_returned);
+DECLARE_TRACEPOINT(zone_lock_released);
+
+#ifdef CONFIG_TRACING
+
+void __zone_lock_do_trace_start_locking(struct zone *zone);
+void __zone_lock_do_trace_acquire_returned(struct zone *zone, bool success);
+void __zone_lock_do_trace_released(struct zone *zone);
+
+static inline void __zone_lock_trace_start_locking(struct zone *zone)
+{
+ if (tracepoint_enabled(zone_lock_start_locking))
+ __zone_lock_do_trace_start_locking(zone);
+}
+
+static inline void __zone_lock_trace_acquire_returned(struct zone *zone,
+ bool success)
+{
+ if (tracepoint_enabled(zone_lock_acquire_returned))
+ __zone_lock_do_trace_acquire_returned(zone, success);
+}
+
+static inline void __zone_lock_trace_released(struct zone *zone)
+{
+ if (tracepoint_enabled(zone_lock_released))
+ __zone_lock_do_trace_released(zone);
+}
+
+#else /* !CONFIG_TRACING */
+
+static inline void __zone_lock_trace_start_locking(struct zone *zone)
+{
+}
+
+static inline void __zone_lock_trace_acquire_returned(struct zone *zone,
+ bool success)
+{
+}
+
+static inline void __zone_lock_trace_released(struct zone *zone)
+{
+}
+
+#endif /* CONFIG_TRACING */
static inline void zone_lock_init(struct zone *zone)
{
@@ -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); \
} 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);
spin_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);
}
static inline void zone_unlock_irq(struct zone *zone)
{
+ __zone_lock_trace_released(zone);
spin_unlock_irq(&zone->_lock);
}
diff --git a/include/trace/events/zone_lock.h b/include/trace/events/zone_lock.h
new file mode 100644
index 000000000000..3df82a8c0160
--- /dev/null
+++ b/include/trace/events/zone_lock.h
@@ -0,0 +1,64 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM zone_lock
+
+#if !defined(_TRACE_ZONE_LOCK_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_ZONE_LOCK_H
+
+#include <linux/tracepoint.h>
+#include <linux/types.h>
+
+struct zone;
+
+DECLARE_EVENT_CLASS(zone_lock,
+
+ TP_PROTO(struct zone *zone),
+
+ TP_ARGS(zone),
+
+ TP_STRUCT__entry(
+ __field(struct zone *, zone)
+ ),
+
+ TP_fast_assign(
+ __entry->zone = zone;
+ ),
+
+ TP_printk("zone=%p", __entry->zone)
+);
+
+#define DEFINE_ZONE_LOCK_EVENT(name) \
+ DEFINE_EVENT(zone_lock, name, \
+ TP_PROTO(struct zone *zone), \
+ TP_ARGS(zone))
+
+DEFINE_ZONE_LOCK_EVENT(zone_lock_start_locking);
+DEFINE_ZONE_LOCK_EVENT(zone_lock_released);
+
+TRACE_EVENT(zone_lock_acquire_returned,
+
+ TP_PROTO(struct zone *zone, bool success),
+
+ TP_ARGS(zone, success),
+
+ TP_STRUCT__entry(
+ __field(struct zone *, zone)
+ __field(bool, success)
+ ),
+
+ TP_fast_assign(
+ __entry->zone = zone;
+ __entry->success = success;
+ ),
+
+ TP_printk(
+ "zone=%p success=%s",
+ __entry->zone,
+ __entry->success ? "true" : "false"
+ )
+);
+
+#endif /* _TRACE_ZONE_LOCK_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/mm/Makefile b/mm/Makefile
index 8ad2ab08244e..ffd06cf7a04e 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -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
diff --git a/mm/zone_lock.c b/mm/zone_lock.c
new file mode 100644
index 000000000000..f647fd2aca48
--- /dev/null
+++ b/mm/zone_lock.c
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0
+#define CREATE_TRACE_POINTS
+#include <trace/events/zone_lock.h>
+
+#include <linux/zone_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);
+}
+EXPORT_SYMBOL(__zone_lock_do_trace_start_locking);
+
+void __zone_lock_do_trace_acquire_returned(struct zone *zone, bool success)
+{
+ trace_zone_lock_acquire_returned(zone, success);
+}
+EXPORT_SYMBOL(__zone_lock_do_trace_acquire_returned);
+
+void __zone_lock_do_trace_released(struct zone *zone)
+{
+ trace_zone_lock_released(zone);
+}
+EXPORT_SYMBOL(__zone_lock_do_trace_released);
+
+#endif /* CONFIG_TRACING */
--
2.47.3
On Thu, Feb 26, 2026 at 06:26:22PM +0000, Dmitry Ilvokhin wrote:
> Add 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.
>
> Signed-off-by: Dmitry Ilvokhin <d@ilvokhin.com>
One nit below other than that:
Acked-by: Shakeel Butt <shakeel.butt@linux.dev>
[...]
> --- /dev/null
> +++ b/mm/zone_lock.c
> @@ -0,0 +1,31 @@
> +// SPDX-License-Identifier: GPL-2.0
> +#define CREATE_TRACE_POINTS
> +#include <trace/events/zone_lock.h>
> +
> +#include <linux/zone_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);
> +}
> +EXPORT_SYMBOL(__zone_lock_do_trace_start_locking);
No reason to not have these as EXPORT_SYMBOL_GPL (& below)
> +
> +void __zone_lock_do_trace_acquire_returned(struct zone *zone, bool success)
> +{
> + trace_zone_lock_acquire_returned(zone, success);
> +}
> +EXPORT_SYMBOL(__zone_lock_do_trace_acquire_returned);
> +
> +void __zone_lock_do_trace_released(struct zone *zone)
> +{
> + trace_zone_lock_released(zone);
> +}
> +EXPORT_SYMBOL(__zone_lock_do_trace_released);
> +
> +#endif /* CONFIG_TRACING */
> --
> 2.47.3
>
On Thu, 26 Feb 2026 11:14:52 -0800 Shakeel Butt <shakeel.butt@linux.dev> wrote:
> On Thu, Feb 26, 2026 at 06:26:22PM +0000, Dmitry Ilvokhin wrote:
> > Add 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.
> >
> > Signed-off-by: Dmitry Ilvokhin <d@ilvokhin.com>
>
> ...
>
> > +void __zone_lock_do_trace_start_locking(struct zone *zone)
> > +{
> > + trace_zone_lock_start_locking(zone);
> > +}
> > +EXPORT_SYMBOL(__zone_lock_do_trace_start_locking);
>
> No reason to not have these as EXPORT_SYMBOL_GPL (& below)
Do we need the exports at all?
include/linux/mmzone.h
include/linux/zone_lock.h
include/trace/events/zone_lock.h
MAINTAINERS
mm/compaction.c
mm/internal.h
mm/Makefile
mm/memory_hotplug.c
mm/mm_init.c
mm/page_alloc.c
mm/page_isolation.c
mm/page_owner.c
mm/page_reporting.c
mm/show_mem.c
mm/vmscan.c
mm/vmstat.c
mm/zone_lock.c
On Thu, Feb 26, 2026 at 01:25:01PM -0800, Andrew Morton wrote:
> On Thu, 26 Feb 2026 11:14:52 -0800 Shakeel Butt <shakeel.butt@linux.dev> wrote:
>
> > On Thu, Feb 26, 2026 at 06:26:22PM +0000, Dmitry Ilvokhin wrote:
> > > Add 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.
> > >
> > > Signed-off-by: Dmitry Ilvokhin <d@ilvokhin.com>
> >
> > ...
> >
> > > +void __zone_lock_do_trace_start_locking(struct zone *zone)
> > > +{
> > > + trace_zone_lock_start_locking(zone);
> > > +}
> > > +EXPORT_SYMBOL(__zone_lock_do_trace_start_locking);
> >
> > No reason to not have these as EXPORT_SYMBOL_GPL (& below)
>
> Do we need the exports at all?
Very good point and we don't. I think this might just be copying the mmap_lock
tracepoint wrappers which might need the exports as some drivers might be taking
the mmap_lock.
Dmitry, please confirm (test) and let us know.
On Thu, Feb 26, 2026 at 01:31:48PM -0800, Shakeel Butt wrote:
> On Thu, Feb 26, 2026 at 01:25:01PM -0800, Andrew Morton wrote:
> > On Thu, 26 Feb 2026 11:14:52 -0800 Shakeel Butt <shakeel.butt@linux.dev> wrote:
> >
> > > On Thu, Feb 26, 2026 at 06:26:22PM +0000, Dmitry Ilvokhin wrote:
> > > > Add 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.
> > > >
> > > > Signed-off-by: Dmitry Ilvokhin <d@ilvokhin.com>
> > >
> > > ...
> > >
> > > > +void __zone_lock_do_trace_start_locking(struct zone *zone)
> > > > +{
> > > > + trace_zone_lock_start_locking(zone);
> > > > +}
> > > > +EXPORT_SYMBOL(__zone_lock_do_trace_start_locking);
> > >
> > > No reason to not have these as EXPORT_SYMBOL_GPL (& below)
> >
> > Do we need the exports at all?
>
> Very good point and we don't. I think this might just be copying the mmap_lock
> tracepoint wrappers which might need the exports as some drivers might be taking
> the mmap_lock.
>
> Dmitry, please confirm (test) and let us know.
This is a good catch, thank you. I don't think we need EXPORT_SYMBOL()
here. Just verified it locally. I'll remove it in v4.
© 2016 - 2026 Red Hat, Inc.