From nobody Thu Sep 24 18:39:27 2026 Received: from mail-pg1-f197.google.com (mail-pg1-f197.google.com [209.85.215.197]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8A10F51354A for ; Mon, 21 Sep 2026 21:26:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.197 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790026019; cv=none; b=C+dpg1yQIL229CBXn6aniJKPU2Ee9BNirhl7jolstPsOS2nvamJ3xRMrZE1Rv6qeF5g9bTInnKLAsOZBzC8P5vftOIUBK3R+6P92czlQHvYtUMpRmQP7hsS3n62y9lebto6wnPSuJyWgb+DQ6LlCP/pW/1q6aPT+WrnBAOabl8E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790026019; c=relaxed/simple; bh=zfsKN+CQz7AB5uzYL/r5PpWfcFcVfhImN1CP/mNFBa0=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=D1cADpVSI6yF8/aKyZooXLJ1PCSrSVR69DKKM939jqc41hBCgU8dpDXRia06j9aN5N8qdqK8r+Uu70ixu5gm8Fg9+kkTLp859B8t9vTft5OyE2daJb188TBbGjt7VRalkgVuBj5T8CL240+kwRBtREaPbP/h6NrQ6T/n0Vro08k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--abhishekbapat.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=fgC6QJ4e; arc=none smtp.client-ip=209.85.215.197 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--abhishekbapat.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="fgC6QJ4e" Received: by mail-pg1-f197.google.com with SMTP id 41be03b00d2f7-cc4216aee8fso4575316a12.1 for ; Mon, 21 Sep 2026 14:26:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1790026017; x=1790630817; darn=vger.kernel.org; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:from:to:cc:subject:date:message-id:reply-to :content-type; bh=dObMqg9/Qyt4/t/40pZAxqs94G9neMmesRffkXIevgI=; b=fgC6QJ4evluQP2wfTpt64tqBUkzmODRCdRS9XmFaTjwEE/+Qy/2LG/zIFDqj+IeIfO XqdDzCyhc4r5MX4gAtwq9Oy2i2iR8duzVWfZgGi0prH5B8DfLdB1Hkb962RNBOSEVfuP sXNviqWa3VGx3Nv8/+kuD0Rxn53s2TipS4neo1ErCleN+3agzJD5iHH+ckaVE1XBP5yG 8KqfyYCsX8rLEYTB/7nLt7Uc/COjzsgFxp8wYc+d0OKSBbjOXO893xLTHrzXjFZo6WnF KSAtEt418jLboCDYuLM9Z7XBMjUFREX2k9xCayOEvSoTWw8rFuRbZ5fzf3OIVhPTsVtV TZRA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790026017; x=1790630817; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=dObMqg9/Qyt4/t/40pZAxqs94G9neMmesRffkXIevgI=; b=jgkQh0ougZt9BVraNeFIIVUNQf0MW0WIUGKTJrjppotmhswkqlod2aqGaY0s2r7LpG 7+BZsjA1vaFKMuII1TSF1plakVNNmk5NRTkPsYhUp6Ydbem0PPxDQrJ5dwnPxQloBxac gRk0E+aaq/3sFNJxpQPyQKlDGFKLf/WrA6HtZqKmruTvsiWeFHyTxre1SX7ra3eMXIuQ tegPV9nnzZzD05CyzECVGnQiCNJxdOMaapxdB4b3meTJZ+rWCWZE+D9UqMPdouVLs6F/ 3XAM4tfHE1g+ZO5n7qh14vjlzKl9P+b7cyU+/pAceICEEGne+SfXDRuUIIc1pWj2w/Lc dtzg== X-Forwarded-Encrypted: i=1; AKwUvBwjIFxWE9yZZz/J/38ccovhns1oPIp7m/t6HAg8y6h/GVIKozQ4P8p1mG/oeTS3Sw9YmDVSchKwGEhBuH8=@vger.kernel.org X-Gm-Message-State: AFuF++kRNrllLLu9TrmZOOsIZRcUDkvxn7DWniUt9OyrE8ASWsFUtRmg rFwZfBuuxVe2PFzO0VhlOPDbVN7IKVvBVSO6lga0KzFzKtaVRdg4qI3w/S/UdQbyZmuC5R90Sv9 l1dV+Z+YucBV+4LEhjU+dAKEOsJFBiKRavQ== X-Received: from dyaz4-n2.prod.google.com ([2002:a05:693c:6384:20b0:33c:4c1f:ace6]) (user=abhishekbapat job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:224c:b0:39b:61f1:8032 with SMTP id 98e67ed59e1d1-39e54e7c18emr16859882a91.16.1790026016572; Mon, 21 Sep 2026 14:26:56 -0700 (PDT) Date: Mon, 21 Sep 2026 21:26:38 +0000 In-Reply-To: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: X-Mailer: git-send-email 2.55.0.1082.g2b9226bbc0-goog Message-ID: <06c3a9b52785e6968ea15709a55365b2342c7a15.1790025465.git.abhishekbapat@google.com> Subject: [PATCH 1/4] alloc_tag: Add trace events for tracing allocations From: Abhishek Bapat To: Suren Baghdasaryan , Hao Ge , Andrew Morton Cc: Steven Rostedt , Masami Hiramatsu , Mathieu Desnoyers , linux-kernel@vger.kernel.org, linux-mm@kvack.org, linux-trace-kernel@vger.kernel.org, Shuah Khan , Abhishek Bapat Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The memory allocation profiling framework intercepts allocations across the core subsystems, but currently lacks runtime tracing hooks for standard observability tools to dynamically track the context (stack traces and lifecycles of the individual memory chunks) of the allocations made. Introduce three standard trace events to allow this tracking: 1. `alloc_tag_hit`: Fired at the exact call site. This allows userspace tools to trigger and capture a call stack. 2. `alloc_tag_mem_alloced`: Fired in alloc_tag_add upon successful allocation. It records the allocated size, the tag, and the uniquely generated codetag_ref metadata pointer. 3. `alloc_tag_mem_freed`: Fired in alloc_tag_sub right before memory is freed, yielding the same codetag_ref to allow tracing tools to find the corresponding allocation. Because the introduced trace events occur at different stages in the call stack, userspace tracing tools must stitch them together to form a complete picture of a buffer's lifetime. Here's an example of how userspace correlates these three events: 1. On `alloc_tag_hit`: The tool captures the stack trace and caches it, keyed by the combination of the current thread's PID and the `tag`. 2. On `alloc_tag_mem_alloced`: The tool extracts the PID and `tag` from the event and looks up the stack trace cached in step 1. It creates a new active allocation record, mapping the new provided `codetag_ref` to this cached stack trace and the newly returned allocation size. 3. On `alloc_tag_mem_freed`: When the memory is freed, the event yields the same `codetag_ref`. The tool uses this reference to look up the original allocation record, correlates the free, and safely retires the tracking entry. Also, introduce `alloc_tag_trace_key` static key to minimize the overhead when no tags are being traced (the usual case). Once tracing for any tag is requested, the key is set, opening the path to check whether tracing is enabled for the current tag. Nore that the mechanism to enabl tag tracing is implemented in the next patch, therefore for now, `alloc_tag_trace_key` stays always unset. Signed-off-by: Abhishek Bapat --- MAINTAINERS | 1 + include/linux/alloc_tag.h | 57 ++++++++++++--- include/trace/events/alloc_tag.h | 122 +++++++++++++++++++++++++++++++ mm/alloc_tag.c | 28 +++++++ 4 files changed, 196 insertions(+), 12 deletions(-) create mode 100644 include/trace/events/alloc_tag.h diff --git a/MAINTAINERS b/MAINTAINERS index 24420a8c06d0..29e1f7915cb9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -17096,6 +17096,7 @@ S: Maintained F: Documentation/mm/allocation-profiling.rst F: include/linux/alloc_tag.h F: include/linux/pgalloc_tag.h +F: include/trace/events/alloc_tag.h F: include/uapi/linux/alloc_tag.h F: mm/alloc_tag.c F: tools/testing/selftests/alloc_tag/ diff --git a/include/linux/alloc_tag.h b/include/linux/alloc_tag.h index 7f2d80a59792..2994934cf44a 100644 --- a/include/linux/alloc_tag.h +++ b/include/linux/alloc_tag.h @@ -128,12 +128,33 @@ DECLARE_PER_CPU(struct alloc_tag_counters, _shared_al= loc_tag); DECLARE_STATIC_KEY_MAYBE(CONFIG_MEM_ALLOC_PROFILING_ENABLED_BY_DEFAULT, mem_alloc_profiling_key); =20 +DECLARE_STATIC_KEY_FALSE(alloc_tag_trace_key); + static inline bool mem_alloc_profiling_enabled(void) { return static_branch_maybe(CONFIG_MEM_ALLOC_PROFILING_ENABLED_BY_DEFAULT, &mem_alloc_profiling_key); } =20 +static inline bool alloc_tag_trace_enabled(const struct alloc_tag *tag) +{ + return static_branch_unlikely(&alloc_tag_trace_key); +} + +void alloc_tag_trace_mem_alloc(union codetag_ref *ref, struct alloc_tag *t= ag, + size_t bytes); + +void alloc_tag_trace_mem_free(union codetag_ref *ref, struct alloc_tag *ta= g, + size_t bytes); + +void __alloc_tag_trace_hit(struct alloc_tag *tag); + +static inline void alloc_tag_trace_hit(struct alloc_tag *tag) +{ + if (alloc_tag_trace_enabled(tag)) + __alloc_tag_trace_hit(tag); +} + bool mem_alloc_profiling_permanently_disabled(void); =20 static inline struct alloc_tag_counters alloc_tag_read(struct alloc_tag *t= ag) @@ -200,8 +221,13 @@ static inline bool alloc_tag_ref_set(union codetag_ref= *ref, struct alloc_tag *t =20 static inline void alloc_tag_add(union codetag_ref *ref, struct alloc_tag = *tag, size_t bytes) { - if (likely(alloc_tag_ref_set(ref, tag))) + if (likely(alloc_tag_ref_set(ref, tag))) { this_cpu_add(tag->counters->bytes, bytes); + + if (alloc_tag_trace_enabled(tag)) + /* Trace successful allocs with their unique ref */ + alloc_tag_trace_mem_alloc(ref, tag, bytes); + } } =20 static inline void alloc_tag_sub(union codetag_ref *ref, size_t bytes) @@ -222,6 +248,10 @@ static inline void alloc_tag_sub(union codetag_ref *re= f, size_t bytes) this_cpu_sub(tag->counters->bytes, bytes); this_cpu_dec(tag->counters->calls); =20 + if (alloc_tag_trace_enabled(tag)) + /* Trace frees with their unique ref */ + alloc_tag_trace_mem_free(ref, tag, bytes); + ref->ct =3D NULL; } =20 @@ -247,21 +277,24 @@ static inline void alloc_tag_add(union codetag_ref *r= ef, struct alloc_tag *tag, static inline void alloc_tag_sub(union codetag_ref *ref, size_t bytes) {} static inline void alloc_tag_set_inaccurate(struct alloc_tag *tag) {} static inline bool alloc_tag_is_inaccurate(struct alloc_tag *tag) { return= false; } +#define alloc_tag_trace_hit(_tag) /* NOOP */ #define alloc_tag_record(p) do {} while (0) =20 #endif /* CONFIG_MEM_ALLOC_PROFILING */ =20 -#define alloc_hooks_tag(_tag, _do_alloc) \ -({ \ - typeof(_do_alloc) _res; \ - if (mem_alloc_profiling_enabled()) { \ - struct alloc_tag * __maybe_unused _old; \ - _old =3D alloc_tag_save(_tag); \ - _res =3D _do_alloc; \ - alloc_tag_restore(_tag, _old); \ - } else \ - _res =3D _do_alloc; \ - _res; \ +#define alloc_hooks_tag(_tag, _do_alloc) \ +({ \ + typeof(_do_alloc) _res; \ + if (mem_alloc_profiling_enabled()) { \ + struct alloc_tag * __maybe_unused _old; \ + /* Fired here to cleanly capture the caller's stack trace */ \ + alloc_tag_trace_hit(_tag); \ + _old =3D alloc_tag_save(_tag); \ + _res =3D _do_alloc; \ + alloc_tag_restore(_tag, _old); \ + } else \ + _res =3D _do_alloc; \ + _res; \ }) =20 #define alloc_hooks(_do_alloc) \ diff --git a/include/trace/events/alloc_tag.h b/include/trace/events/alloc_= tag.h new file mode 100644 index 000000000000..af2182501864 --- /dev/null +++ b/include/trace/events/alloc_tag.h @@ -0,0 +1,122 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM alloc_tag + +#if !defined(_TRACE_ALLOC_TAG_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_ALLOC_TAG_H + +#include + +/* + * alloc_tag_hit is generated at the exact allocation call site and can be + * used to capture a clean stack trace. + * + * To link this stack trace to the actual allocated memory chunk, tools mu= st + * correlate this event with the resulting alloc_tag_mem_alloced event. Si= nce + * multiple threads can hit the same tag simultaneously, tools must match = BOTH + * the `tag` field and the implicitly recorded PID provided by the core + * tracing subsystem. + */ +TRACE_EVENT(alloc_tag_hit, + + TP_PROTO(struct alloc_tag *tag), + + TP_ARGS(tag), + + TP_STRUCT__entry( + __field(struct alloc_tag *, tag) + __string(modname, tag->ct.modname ? tag->ct.modname : "NONE") + __string(filename, tag->ct.filename) + __string(function, tag->ct.function) + __field(unsigned int, lineno) + ), + + TP_fast_assign( + __entry->tag =3D tag; + __assign_str(modname); + __assign_str(filename); + __assign_str(function); + __entry->lineno =3D tag->ct.lineno; + ), + + TP_printk("tag %p, module: %s, filename: %s, function %s, lineno %u", + __entry->tag, + __get_str(modname), + __get_str(filename), + __get_str(function), + __entry->lineno + ) +); + +/* + * alloc_tag_mem_alloced is generated after memory is successfully allocat= ed. + * It captures the exact byte size. + * + * The `ref` pointer identifies the memory chunk for tracking its lifecycle + * (e.g., matching it with alloc_tag_mem_freed). + * + * Because the kernel isolates active allocations within the task struct + * (current->alloc_tag), this even will always share the same implicit PID= as + * its corresponding alloc_tag_hit event. Tools should use the combination + * PID + `tag` to correlate them. + */ +TRACE_EVENT(alloc_tag_mem_alloced, + + TP_PROTO(union codetag_ref *ref, struct alloc_tag *tag, size_t bytes), + + TP_ARGS(ref, tag, bytes), + + TP_STRUCT__entry( + __field(union codetag_ref *, ref) + __field(struct alloc_tag *, tag) + __field(size_t, bytes) + ), + + TP_fast_assign( + __entry->ref =3D ref; + __entry->tag =3D tag; + __entry->bytes =3D bytes; + ), + + TP_printk("reference %p, tag %p, bytes %zu", + __entry->ref, + __entry->tag, + __entry->bytes + ) +); + +/* + * alloc_tag_mem_freed event is generated immediately before memory is + * freed. The `ref` pointer matches the one emitted during allocation, + * allowing tools to match it to it's corresponding allocation and + * call stack. + */ +TRACE_EVENT(alloc_tag_mem_freed, + + TP_PROTO(union codetag_ref *ref, struct alloc_tag *tag, size_t bytes), + + TP_ARGS(ref, tag, bytes), + + TP_STRUCT__entry( + __field(union codetag_ref *, ref) + __field(struct alloc_tag *, tag) + __field(size_t, bytes) + ), + + TP_fast_assign( + __entry->ref =3D ref; + __entry->tag =3D tag; + __entry->bytes =3D bytes; + ), + + TP_printk("reference %p, tag %p, bytes %zu", + __entry->ref, + __entry->tag, + __entry->bytes + ) +); + +#endif /* _TRACE_ALLOC_TAG_H */ + +/* This part must be outside protection */ +#include diff --git a/mm/alloc_tag.c b/mm/alloc_tag.c index f30ef8dd24c7..a5339767efd5 100644 --- a/mm/alloc_tag.c +++ b/mm/alloc_tag.c @@ -19,6 +19,9 @@ #include #include =20 +#define CREATE_TRACE_POINTS +#include + #include "internal.h" #include "page_alloc.h" =20 @@ -55,6 +58,9 @@ EXPORT_SYMBOL(mem_alloc_profiling_key); =20 DEFINE_STATIC_KEY_FALSE(mem_profiling_compressed); =20 +DEFINE_STATIC_KEY_FALSE(alloc_tag_trace_key); +EXPORT_SYMBOL(alloc_tag_trace_key); + struct alloc_tag_kernel_section kernel_tags =3D { NULL, 0 }; unsigned long alloc_tag_ref_mask; int alloc_tag_ref_offs; @@ -485,6 +491,28 @@ static const struct proc_ops allocinfo_proc_ops =3D { #endif }; =20 +void __alloc_tag_trace_hit(struct alloc_tag *tag) +{ + if (unlikely(!tag)) + return; + trace_alloc_tag_hit(tag); +} +EXPORT_SYMBOL(__alloc_tag_trace_hit); + +void alloc_tag_trace_mem_alloc(union codetag_ref *ref, struct alloc_tag *t= ag, + size_t bytes) +{ + trace_alloc_tag_mem_alloced(ref, tag, bytes); +} +EXPORT_SYMBOL(alloc_tag_trace_mem_alloc); + +void alloc_tag_trace_mem_free(union codetag_ref *ref, struct alloc_tag *ta= g, + size_t bytes) +{ + trace_alloc_tag_mem_freed(ref, tag, bytes); +} +EXPORT_SYMBOL(alloc_tag_trace_mem_free); + size_t alloc_tag_top_users(struct codetag_bytes *tags, size_t count, bool = can_sleep) { struct codetag_iterator iter; --=20 2.55.0.1082.g2b9226bbc0-goog From nobody Thu Sep 24 18:39:27 2026 Received: from mail-pj1-f72.google.com (mail-pj1-f72.google.com [209.85.216.72]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2BF93514742 for ; Mon, 21 Sep 2026 21:26:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.72 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790026019; cv=none; b=a0fgYaAM2NAX5+82LH52bZq2JKjHlfNpzMeR8jJ+HJ5kq0nvx21CnsLM3ggYVIszuPn6igC+NeiRHTcI4ZlviQeTpOEHMOUPlnlOdpF8RDrFns0tbAb+1sOKu0zolZBc4xiayqq284bH0Vnpmt4UK1+nOs+WuUHh+S2LtLZjRAo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790026019; c=relaxed/simple; bh=mQl9uRFTjOhtAf8RnezROyeHtTJ0aF74n3XpBmZ0br0=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=jYr8n3SPq0rvXjCdXuMcfInsKVc79Zq0bmzX62nYgqsbjsPFzVrRSItTY7+6lTNbSZhRuccCfoc3rC1n3qZEpFNjpBlI0ney7aCwId3cFmDlYgVVE32B44Blx7TdU+wF91eJpqsKFDsl/MzBxoqPNFKUrJnSfxUJBhWlku8+NTY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--abhishekbapat.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=Nlz/P2jO; arc=none smtp.client-ip=209.85.216.72 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--abhishekbapat.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="Nlz/P2jO" Received: by mail-pj1-f72.google.com with SMTP id 98e67ed59e1d1-39e087a17dfso5978603a91.3 for ; Mon, 21 Sep 2026 14:26:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1790026017; x=1790630817; darn=vger.kernel.org; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:from:to:cc:subject:date:message-id:reply-to :content-type; bh=JRTedVM7nBxor9V1RQ1SMJHuSnIvSIlR7gJ4JHxEE28=; b=Nlz/P2jOFDhTQKlOEQur1sro78eqWIpSXzMqnTzLb22IxXYuz9HBfcVgHXq7Xw0s53 /sIy/843imVfmw4/ccbuST833IuhnQ3PiArv6VstzOvvge+ep5p64LNnDtliGfayQfNT M0ltWDSwCFFifEB2ubRmITloTyAXRLjUZDOSLLV1xAqHQkzT4svCvbVTBGzKjuO0v8NP in7yVcaKB65aiD5rmAjQAdYh6AL9QjX4j1InH9LS0+4qsSUYSr4nGsJ9HnYk3WzHGGoe zp31eDbkZaLWn4hEQoMHhHDlqVfd9MXi68lmeho4uRd5f+bURkA82PU0qclGi/EqDnkI ktbw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790026017; x=1790630817; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=JRTedVM7nBxor9V1RQ1SMJHuSnIvSIlR7gJ4JHxEE28=; b=rrEZwFWZyanx7JtYl1W+NuilydAN2cui6VloMDEMzvfnqJXOVlTIERjziiFUyWgBU1 0MhsF0A/lzaMDeqHjynejXWUTqySqs+XbkjyEUbJk7RTiYt0Qo56TwpSwD9RsBdMlGuP WF9J14iIwCGF98U+LEXA1aBR2J43as6EEx7G0cL57dsbri2dcor0lBmzcsA9Mw0O0Rt4 CQOL6DpboUmGNZNbQqb+ujiHbAxBaeReX40ofY6m0AWgkjj6HT8h3liBjTf4bF9gMaNX HEITRRd86yzrOH3me82mz2m9Vv/EygnKYR1GeiuI6xhcLA2S5SltTjW/cfsJrtKbOEeb AVnQ== X-Forwarded-Encrypted: i=1; AKwUvByaXXf6sv1R67IHF6XSyjVypRMR4+HEetVrIisORWv+IO9Ns9oAKv7suSv9BOE+VIlUmqW9CJOZGiwPgrk=@vger.kernel.org X-Gm-Message-State: AFuF++lep0giEJq7QuDK1USL4O0A8AqK9JLFwikzkwzba2REdCsHAFge G0UjnV0VA0sN6BMCNeLV5piB54pNFWcDnkCMYp0d5UolDCBT3vR0Ipz6KwEIrEUTrvgfZyY1OkN EbJ15CgXGvnK9Lr8vPhYjbTFsXXr5umbAbg== X-Received: from dlzz29.prod.google.com ([2002:a05:7022:49d:b0:144:d6d2:5015]) (user=abhishekbapat job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:5287:b0:39e:3285:b776 with SMTP id 98e67ed59e1d1-39e54cb9c71mr17703289a91.7.1790026017349; Mon, 21 Sep 2026 14:26:57 -0700 (PDT) Date: Mon, 21 Sep 2026 21:26:39 +0000 In-Reply-To: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: X-Mailer: git-send-email 2.55.0.1082.g2b9226bbc0-goog Message-ID: <95bf63d2b9ef14f6610d6543b6892d266e4dc5c6.1790025465.git.abhishekbapat@google.com> Subject: [PATCH 2/4] alloc_tag: Introduce IOCTLs to toggle allocation tracepoints From: Abhishek Bapat To: Suren Baghdasaryan , Hao Ge , Andrew Morton Cc: Steven Rostedt , Masami Hiramatsu , Mathieu Desnoyers , linux-kernel@vger.kernel.org, linux-mm@kvack.org, linux-trace-kernel@vger.kernel.org, Shuah Khan , Abhishek Bapat Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Introduce a new IOCTL (`ALLOCINFO_IOC_TOGGLE_TRACE`) to selectively toggle tracing on exact allocation call sites. Userspace tools can use the existing filtering mechanism to specify the set of tags to toggle tracing for. To facilitate low overhead execution for non-targeted call sites, add a new `CODETAG_FLAG_TRACE_ON` flag to `struct codetag` to track per-site activation. Protect these conditional branch evaluations using a global `alloc_tag_trace_key` static branch and an inline static key check pattern in the allocator hooks (`alloc_tag_add`, `alloc_tag_sub`, etc). This ensures that the trace events are entirely skipped when no allocation call sites are being actively traced, leaving only a NOP on the allocation fast path. Signed-off-by: Abhishek Bapat --- include/linux/alloc_tag.h | 39 ++++++++---- include/linux/codetag.h | 5 +- include/uapi/linux/alloc_tag.h | 9 +++ mm/alloc_tag.c | 110 ++++++++++++++++++++++++++++++++- 4 files changed, 147 insertions(+), 16 deletions(-) diff --git a/include/linux/alloc_tag.h b/include/linux/alloc_tag.h index 2994934cf44a..dc86f8997476 100644 --- a/include/linux/alloc_tag.h +++ b/include/linux/alloc_tag.h @@ -136,9 +136,36 @@ static inline bool mem_alloc_profiling_enabled(void) &mem_alloc_profiling_key); } =20 +static inline void alloc_tag_set_inaccurate(struct alloc_tag *tag) +{ + atomic_or(CODETAG_FLAG_INACCURATE, &tag->ct.flags); +} + +static inline bool alloc_tag_is_inaccurate(struct alloc_tag *tag) +{ + return !!(atomic_read(&tag->ct.flags) & CODETAG_FLAG_INACCURATE); +} + +static inline void alloc_tag_set_traced(struct alloc_tag *tag) +{ + atomic_or(CODETAG_FLAG_TRACE_ON, &tag->ct.flags); +} + +static inline void alloc_tag_clear_traced(struct alloc_tag *tag) +{ + atomic_andnot(CODETAG_FLAG_TRACE_ON, &tag->ct.flags); +} + +static inline bool alloc_tag_is_traced(const struct alloc_tag *tag) +{ + return !!(atomic_read(&tag->ct.flags) & CODETAG_FLAG_TRACE_ON); +} + static inline bool alloc_tag_trace_enabled(const struct alloc_tag *tag) { - return static_branch_unlikely(&alloc_tag_trace_key); + if (static_branch_unlikely(&alloc_tag_trace_key)) + return tag && alloc_tag_is_traced(tag); + return false; } =20 void alloc_tag_trace_mem_alloc(union codetag_ref *ref, struct alloc_tag *t= ag, @@ -255,16 +282,6 @@ static inline void alloc_tag_sub(union codetag_ref *re= f, size_t bytes) ref->ct =3D NULL; } =20 -static inline void alloc_tag_set_inaccurate(struct alloc_tag *tag) -{ - tag->ct.flags |=3D CODETAG_FLAG_INACCURATE; -} - -static inline bool alloc_tag_is_inaccurate(struct alloc_tag *tag) -{ - return !!(tag->ct.flags & CODETAG_FLAG_INACCURATE); -} - #define alloc_tag_record(p) ((p) =3D current->alloc_tag) =20 #else /* CONFIG_MEM_ALLOC_PROFILING */ diff --git a/include/linux/codetag.h b/include/linux/codetag.h index a25a085c2df1..f728295d50c0 100644 --- a/include/linux/codetag.h +++ b/include/linux/codetag.h @@ -18,6 +18,7 @@ struct module; =20 /* codetag flags */ #define CODETAG_FLAG_INACCURATE (1 << 0) +#define CODETAG_FLAG_TRACE_ON (1 << 1) =20 /* * An instance of this structure is created in a special ELF section at ev= ery @@ -25,7 +26,7 @@ struct module; * an array of these. */ struct codetag { - unsigned int flags; + atomic_t flags; unsigned int lineno; const char *modname; const char *function; @@ -71,7 +72,7 @@ struct codetag_iterator { .function =3D __func__, \ .filename =3D __FILE__, \ .lineno =3D __LINE__, \ - .flags =3D 0, \ + .flags =3D ATOMIC_INIT(0), \ } =20 void codetag_lock_module_list(struct codetag_type *cttype); diff --git a/include/uapi/linux/alloc_tag.h b/include/uapi/linux/alloc_tag.h index 7d4618bea043..069ab8341e87 100644 --- a/include/uapi/linux/alloc_tag.h +++ b/include/uapi/linux/alloc_tag.h @@ -85,9 +85,16 @@ struct allocinfo_get_at { struct allocinfo_tag_data data; }; =20 +struct allocinfo_toggle_traces { + /* inputs */ + struct allocinfo_tag fields; + __u64 enable; +}; + #define _ALLOCINFO_IOC_CONTENT_ID 0 #define _ALLOCINFO_IOC_GET_AT 1 #define _ALLOCINFO_IOC_GET_NEXT 2 +#define _ALLOCINFO_IOC_TOGGLE_TRACE 3 =20 #define ALLOCINFO_IOC_BASE 0xA6 #define ALLOCINFO_IOC_CONTENT_ID _IOR(ALLOCINFO_IOC_BASE, _ALLOCINFO_IOC_C= ONTENT_ID, \ @@ -96,5 +103,7 @@ struct allocinfo_get_at { struct allocinfo_get_at) #define ALLOCINFO_IOC_GET_NEXT _IOR(ALLOCINFO_IOC_BASE, _ALLOCINFO_IOC_GE= T_NEXT, \ struct allocinfo_tag_data) +#define ALLOCINFO_IOC_TOGGLE_TRACE _IOW(ALLOCINFO_IOC_BASE, _ALLOCINFO_IOC= _TOGGLE_TRACE, \ + struct allocinfo_toggle_traces) =20 #endif /* _UAPI_ALLOC_TAG_H */ diff --git a/mm/alloc_tag.c b/mm/alloc_tag.c index a5339767efd5..fb179321a2a1 100644 --- a/mm/alloc_tag.c +++ b/mm/alloc_tag.c @@ -61,6 +61,15 @@ DEFINE_STATIC_KEY_FALSE(mem_profiling_compressed); DEFINE_STATIC_KEY_FALSE(alloc_tag_trace_key); EXPORT_SYMBOL(alloc_tag_trace_key); =20 +static atomic_t alloc_tag_trace_cnt =3D ATOMIC_INIT(0); + +/* + * As `codetag_lock_module_list` is a read lock, we need an additional mut= ex + * to protect against the race conditions involved in the alloc tag trace + * toggle path. + */ +static DEFINE_MUTEX(alloc_tag_trace_mutex); + struct alloc_tag_kernel_section kernel_tags =3D { NULL, 0 }; unsigned long alloc_tag_ref_mask; int alloc_tag_ref_offs; @@ -297,7 +306,7 @@ static bool matches_filter(struct codetag *ct, struct a= llocinfo_filter *filter, return false; =20 if (filter->mask & ALLOCINFO_FILTER_MASK_INACCURATE) { - inaccurate =3D !!(ct->flags & CODETAG_FLAG_INACCURATE); + inaccurate =3D alloc_tag_is_inaccurate(ct_to_alloc_tag(ct)); if (inaccurate !=3D !!(filter->inaccurate)) return false; } @@ -444,6 +453,81 @@ static int allocinfo_ioctl_get_next(struct seq_file *m= , void __user *arg) return ret; } =20 +static bool alloc_tag_trace_toggle(struct alloc_tag *tag, bool enable) +{ + if (enable) { + if (alloc_tag_is_traced(tag)) + return false; + + alloc_tag_set_traced(tag); + if (atomic_fetch_inc(&alloc_tag_trace_cnt) =3D=3D 0) + static_branch_enable(&alloc_tag_trace_key); + } else { + if (!alloc_tag_is_traced(tag)) + return false; + + alloc_tag_clear_traced(tag); + if (atomic_dec_and_test(&alloc_tag_trace_cnt)) + static_branch_disable(&alloc_tag_trace_key); + } + + return true; +} + +/* + * Toggles context capture for a specified allocation. + */ +static int allocinfo_ioctl_toggle_trace(struct seq_file *m, void __user *a= rg) +{ + struct allocinfo_toggle_traces params; + struct codetag_iterator iter; + struct codetag *ct; + int matches =3D 0, successes =3D 0, ret; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + if (copy_from_user(¶ms, arg, sizeof(params))) + return -EFAULT; + + codetag_lock_module_list(alloc_tag_cttype); + + struct allocinfo_filter filter =3D { + .mask =3D ALLOCINFO_FILTER_MASK_MODNAME | + ALLOCINFO_FILTER_MASK_FUNCTION | + ALLOCINFO_FILTER_MASK_FILENAME | + ALLOCINFO_FILTER_MASK_LINENO, + .fields =3D params.fields, + }; + + iter =3D codetag_get_ct_iter(alloc_tag_cttype); + + /* Toggle tracing on all codetags that match */ + while ((ct =3D codetag_next_ct(&iter))) { + if (matches_filter(ct, &filter, NULL, NULL)) { + matches++; + + mutex_lock(&alloc_tag_trace_mutex); + if (alloc_tag_trace_toggle(ct_to_alloc_tag(ct), !!params.enable)) + successes++; + mutex_unlock(&alloc_tag_trace_mutex); + } + } + + if (matches =3D=3D 0) + /* Nothing matched the filter */ + ret =3D -ENOENT; + else if (successes =3D=3D 0) + /* Items matched, but were already in the requested state */ + ret =3D -EINVAL; + else + ret =3D 0; + + codetag_unlock_module_list(alloc_tag_cttype); + + return ret; +} + /* * Entry point ioctl function for /proc/allocinfo routing requests to fetc= h the * layout content ID, seek to a specific tag, or read sequential tags. @@ -464,6 +548,9 @@ static long allocinfo_ioctl(struct file *file, unsigned= int cmd, case ALLOCINFO_IOC_GET_NEXT: ret =3D allocinfo_ioctl_get_next(file->private_data, arg); break; + case ALLOCINFO_IOC_TOGGLE_TRACE: + ret =3D allocinfo_ioctl_toggle_trace(file->private_data, arg); + break; default: ret =3D -ENOIOCTLCMD; break; @@ -493,8 +580,6 @@ static const struct proc_ops allocinfo_proc_ops =3D { =20 void __alloc_tag_trace_hit(struct alloc_tag *tag) { - if (unlikely(!tag)) - return; trace_alloc_tag_hit(tag); } EXPORT_SYMBOL(__alloc_tag_trace_hit); @@ -1043,6 +1128,24 @@ static int load_module(struct module *mod, struct co= detag *start, struct codetag return 0; } =20 +static void unload_module(struct module *mod, struct codetag *start, struc= t codetag *stop) +{ + struct alloc_tag *start_tag =3D ct_to_alloc_tag(start); + struct alloc_tag *stop_tag =3D ct_to_alloc_tag(stop); + struct alloc_tag *tag; + + /* + * Turn tracing off for the tags of the module being unloaded. Without + * this, `alloc_tag_trace_cnt` would never reach zero and tracing would + * stay enabled forever. + * + * `alloc_tag_trace_mutex` is not needed here as this code path is + * protected by a `down_write(&cttype->mod_lock)`. + */ + for (tag =3D start_tag; tag < stop_tag; tag++) + alloc_tag_trace_toggle(tag, false); +} + static void replace_module(struct module *mod, struct module *new_mod) { MA_STATE(mas, &mod_area_mt, 0, module_tags.size); @@ -1369,6 +1472,7 @@ static int __init alloc_tag_init(void) .alloc_section_mem =3D reserve_module_tags, .free_section_mem =3D release_module_tags, .module_load =3D load_module, + .module_unload =3D unload_module, .module_replaced =3D replace_module, #endif }; --=20 2.55.0.1082.g2b9226bbc0-goog From nobody Thu Sep 24 18:39:27 2026 Received: from mail-pl1-f200.google.com (mail-pl1-f200.google.com [209.85.214.200]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 05696514774 for ; Mon, 21 Sep 2026 21:26:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.200 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790026020; cv=none; b=UHzzYpBWRpBxjK/CWN9CgyEX6I2zQ2LbV+vfQzQtaMUB7nVY1uDYoja53pRcFXhSGyPfjFgPtCcvK6/FDm5EmhXoI2CkqarfJGBODRSLWaA4M2tnqFwwnyjUNf6ZMBWBloYIusgKr+jAKF8vxupYqXJLQypZTIkjopxQe5HlmTY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790026020; c=relaxed/simple; bh=JQ/lbKA9YQdgwnnkaFloU/3l/iRjfaxtxV1VWvxRrpk=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=H6WNM17nmAJ4H6zSztsfOEQcWavHuylLfqAYCxnJxNscw3nPHimEm391v3f7IX7tj+ttZsSelbjMctpBdGzVgW6DzwUCjpsZZKjPLjdlttkvWVAmAhlywfveZN6QRiIpXP2mpK4ADD3jcmCq+Q7wtzNHtKXrrEiK8JASBMJSGkA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--abhishekbapat.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=Xtf/iLOl; arc=none smtp.client-ip=209.85.214.200 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--abhishekbapat.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="Xtf/iLOl" Received: by mail-pl1-f200.google.com with SMTP id d9443c01a7336-2d94a158dc8so61115585ad.2 for ; Mon, 21 Sep 2026 14:26:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1790026018; x=1790630818; darn=vger.kernel.org; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:from:to:cc:subject:date:message-id:reply-to :content-type; bh=thyHfYtRbZkf/h8UY4YJlFOO7BMX5P6p7QG3tm7dEMQ=; b=Xtf/iLOlmeigqXAIsJx3Pb/dj9ZcwkdRVvJKJXrJ1wM6fol/vYXuXdAXSiNjagdZj7 3qvEPSPs8/mVDnjBIaGEQSuOoWHMlOIGkIgYPCsaUD5p9LLiMz77ALDus/27uJ8QdMtf grYd6NDo+a0icxOEUgmp38XhCcbjhNpoC8AraZlO+bwc0gpydFeety5iVPp/G9L84+zd EqyEryHyvLF4HSWF+1Rj/kkgjP01jYsyFrhJ9K820Abod3T0inouh2GSZqJJrJBfr1HB S7hiH9dPQ+fj7CI2d25BJ8TTndazGuUoF6exW2Vt+nzKsCKPYJSaufmrDQmp6Si2ec4n h23w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790026018; x=1790630818; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=thyHfYtRbZkf/h8UY4YJlFOO7BMX5P6p7QG3tm7dEMQ=; b=v1G86yiwmnwLZ1p5XrKc/jI+oq9zzK41caNJ1GGo7m1CYen9dAGA5pBgQxmjUBrGtH jQVX07f7GoDQzRlcKryt5MFi1xul0l3r+5W6AnKGcA+o6rn81lZmPCokKORxHAjRrgPt o73W/0aUsSByTHVGz2QJ/8sLdGkwGA2opyF2VjlIxDbP/MoDVTsKFKtWqNU4gGtce33d tknHIGS51uFhIDLIqpTIh4v3J1s6Mrav7b8E55POAutOVacJzFGlEgq1rAnHQpcq/8RC TVJ0ma6ONktX/74oq/D+VA/PNQZhGNEWWKOOZigCqn9WiXbS+T6iSoxSm+1Sos1PQh9L 6o5g== X-Forwarded-Encrypted: i=1; AKwUvBykI9r8jGdnOqgh6ew59xn4Idibtv7tbLtmF04oWVGqQIawRKyzUmM9pIQWHrwdQyvGDaXK3GBRaKfa1+o=@vger.kernel.org X-Gm-Message-State: AFuF++kYN8ffkhWvh0PHB9ZUOAlZSNNQ8G033CCtr6IFTxojhluB5aJf EMO1GAPVPkv5bzsFiviuya8TuOmJdLaXw7Gjrqqqp24wacFAjw4Jnaj6sr0hUxY7j+2ty0K62mw y3cRZzu0QitGfhJ8kO62JEz2LJU5JHt1zPg== X-Received: from dybsr41.prod.google.com ([2002:a05:7301:71a9:b0:339:7118:d1b6]) (user=abhishekbapat job=prod-delivery.src-stubby-dispatcher) by 2002:a17:903:234d:b0:2d6:e074:9cad with SMTP id d9443c01a7336-2ddb1acad2dmr184944625ad.6.1790026018153; Mon, 21 Sep 2026 14:26:58 -0700 (PDT) Date: Mon, 21 Sep 2026 21:26:40 +0000 In-Reply-To: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: X-Mailer: git-send-email 2.55.0.1082.g2b9226bbc0-goog Message-ID: Subject: [PATCH 3/4] alloc_tag: extend allocinfo_filter to support tracing queries From: Abhishek Bapat To: Suren Baghdasaryan , Hao Ge , Andrew Morton Cc: Steven Rostedt , Masami Hiramatsu , Mathieu Desnoyers , linux-kernel@vger.kernel.org, linux-mm@kvack.org, linux-trace-kernel@vger.kernel.org, Shuah Khan , Abhishek Bapat Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Extend the allocinfo filtering mechanism to allow users to filter tags based on their trace state. Signed-off-by: Abhishek Bapat --- include/uapi/linux/alloc_tag.h | 8 ++++++-- mm/alloc_tag.c | 8 ++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/include/uapi/linux/alloc_tag.h b/include/uapi/linux/alloc_tag.h index 069ab8341e87..e65c32afceee 100644 --- a/include/uapi/linux/alloc_tag.h +++ b/include/uapi/linux/alloc_tag.h @@ -38,7 +38,8 @@ struct allocinfo_counter { __u64 bytes; __u64 calls; __u8 accurate; - __u8 pad[7]; + __u8 trace_on; + __u8 pad[6]; } __attribute__((aligned(8))); =20 struct allocinfo_tag_data { @@ -54,7 +55,8 @@ enum { ALLOCINFO_FILTER_INACCURATE, ALLOCINFO_FILTER_MIN_SIZE, ALLOCINFO_FILTER_MAX_SIZE, - __ALLOCINFO_FILTER_LAST =3D ALLOCINFO_FILTER_MAX_SIZE + ALLOCINFO_FILTER_TRACE_ON, + __ALLOCINFO_FILTER_LAST =3D ALLOCINFO_FILTER_TRACE_ON }; =20 #define ALLOCINFO_FILTER_MASK_MODNAME (1 << ALLOCINFO_FILTER_MODNAME) @@ -64,6 +66,7 @@ enum { #define ALLOCINFO_FILTER_MASK_INACCURATE (1 << ALLOCINFO_FILTER_INACCURATE) #define ALLOCINFO_FILTER_MASK_MIN_SIZE (1 << ALLOCINFO_FILTER_MIN_SIZE) #define ALLOCINFO_FILTER_MASK_MAX_SIZE (1 << ALLOCINFO_FILTER_MAX_SIZE) +#define ALLOCINFO_FILTER_MASK_TRACE_ON (1 << ALLOCINFO_FILTER_TRACE_ON) =20 #define ALLOCINFO_FILTER_MASKS \ ((1 << (__ALLOCINFO_FILTER_LAST + 1)) - 1) @@ -75,6 +78,7 @@ struct allocinfo_filter { __u64 max_size; /* filter criteria only; see allocinfo_counter.accurate for actual accura= cy */ __u64 inaccurate; + __u64 tracing; }; =20 struct allocinfo_get_at { diff --git a/mm/alloc_tag.c b/mm/alloc_tag.c index fb179321a2a1..50632b627d92 100644 --- a/mm/alloc_tag.c +++ b/mm/alloc_tag.c @@ -251,6 +251,7 @@ static void allocinfo_to_params(struct codetag *ct, data->counter.bytes =3D counters->bytes; data->counter.calls =3D counters->calls; data->counter.accurate =3D !alloc_tag_is_inaccurate(ct_to_alloc_tag(ct)); + data->counter.trace_on =3D alloc_tag_is_traced(ct_to_alloc_tag(ct)); } =20 /* @@ -324,6 +325,13 @@ static bool matches_filter(struct codetag *ct, struct = allocinfo_filter *filter, return false; } =20 + if (filter->mask & ALLOCINFO_FILTER_MASK_TRACE_ON) { + bool tracing =3D alloc_tag_is_traced(ct_to_alloc_tag(ct)); + + if (tracing !=3D !!(filter->tracing)) + return false; + } + return true; } =20 --=20 2.55.0.1082.g2b9226bbc0-goog From nobody Thu Sep 24 18:39:27 2026 Received: from mail-pg1-f197.google.com (mail-pg1-f197.google.com [209.85.215.197]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C292951588B for ; Mon, 21 Sep 2026 21:26:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.197 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790026021; cv=none; b=SfpICtl9cXRe2f9eqIgqv81YJz2ZgcEV4p4fU4q9nNdkFFFsB23xM/JF0OFVjBJgiS76+Dbq7HrziI5khgcsNfUZivfK84O3coppebbWu5u/8Nna+4pk9SrFVo8rDlBb28yBBB1v7sNZF+55NR/TJCMHOxrBUUp0VYxKq286P/c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790026021; c=relaxed/simple; bh=rK6SJyn/YB5/uhpulKVt3Q8tkfBa+5FtGVb4YmpINQM=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=SWSzp5IJTKF5J7LYq3OdI02tGf1yf40gXuGvoHWgjpxacdVD73c8HoesDNpkV9O09C9JwuGQ7NfMdGYwUbicXOaL0jLc6Jh/CgiOsCI6y8kmPknCuqVoOfJIAvCciDf32NfKDfeas94s9zM5g3cjczBvk6usABMF9F8GNm8Jkxs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--abhishekbapat.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=ubio37gH; arc=none smtp.client-ip=209.85.215.197 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--abhishekbapat.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="ubio37gH" Received: by mail-pg1-f197.google.com with SMTP id 41be03b00d2f7-cb11535e6a1so2707372a12.0 for ; Mon, 21 Sep 2026 14:26:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1790026019; x=1790630819; darn=vger.kernel.org; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:from:to:cc:subject:date:message-id:reply-to :content-type; bh=4svBVXpzXDnEEaPp2iHW0GefZCmj3wqJ5HrNnYa0oV0=; b=ubio37gHhkwD6IGHCuB3yEkukouUOZQI13D4gcI+a17hw+yRSXks4hwn3EZ2pc7sRM sJKskkg3mLWjC8tn7wPecG/GPAK5sL/AhW8AOiQauU4uU7YOf7aVUwwdfIW3B3J16d+s SofUi0a8MGK6pYXslU3n1hYClRaxr6S+LFZ2TgWCC6RyZR2x1Znn0ItY/v7r6rkyWSR6 mbzqQSs8UR+dw6YglQEUwWZlOhrgdvaHIPygu4WdSL1w3pNjqSXaQGv9qeIcIAQTndOj 1DFsnJ5uvBekOWoRr143o4jUQXbnNTIYRNr1AcPOQuocTrqomCYf6b0S7T0AY/JVAx9h putQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790026019; x=1790630819; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=4svBVXpzXDnEEaPp2iHW0GefZCmj3wqJ5HrNnYa0oV0=; b=UKw6vjZxu/otF3GbxuqBh50hOBoxB07x8zy3pedBKqQJyANH9Tx4U5VcJcxBxC/FNa gW1xf2FHUCh4V8GaHCCc3EHFnMe17I1cF4mqlfOT3y8IgzWgpUK0tQzDL1pszPLKTNmU M9Mdv/YYv2LqlEMyE+LaogwqxZjVy9YjYr5uhXR5MTBTFeIVZka8f6POT7MaiC3h9iQT eQIOKWSuJhmPUitw3AQIA5W2pVWNLt5dCV9WP8/vA3KbCHrtHdSYzPsqAJ/c/6O6O2Sd E+sv/WffJ2nYzXU1vNoFE/skjZF5lQwoMnPtUyJhrV4gYB1OF95U8Jzsi+oG+jkR9BvI DEtA== X-Forwarded-Encrypted: i=1; AKwUvBwFXHQbu45J4V4R3OC7wmueeK3oxfU5DYCCZTXYSp9NJsL9EcgI7gD+/81pC1srCU4BA9H16VNd+W9MKeg=@vger.kernel.org X-Gm-Message-State: AFuF++lCeaiF4D05Jbm6RR7QvbP/3unZxqlGHmUXcpk+td7thJCrMa1X Jq858Bg3sSx5dqzmjoLst2hrwgRkmFq6IVgZJAL4B69lT7c7I0KYkhD93Zc2Pe4/xxriSDF/VMy m9usvIr/DfYDOTUpa5XDXKSnqI7jxJ+Vh0A== X-Received: from dyng28.prod.google.com ([2002:a05:7300:7f1c:b0:339:c3e:449b]) (user=abhishekbapat job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a21:1393:b0:3dd:a195:dd61 with SMTP id adf61e73a8af0-3dda195e47amr11865501637.67.1790026018871; Mon, 21 Sep 2026 14:26:58 -0700 (PDT) Date: Mon, 21 Sep 2026 21:26:41 +0000 In-Reply-To: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: X-Mailer: git-send-email 2.55.0.1082.g2b9226bbc0-goog Message-ID: <988dddb203416668a10bc9c5e6157a78615d2ed2.1790025465.git.abhishekbapat@google.com> Subject: [PATCH 4/4] alloc_tag: add a test for trace state toggle and filtering From: Abhishek Bapat To: Suren Baghdasaryan , Hao Ge , Andrew Morton Cc: Steven Rostedt , Masami Hiramatsu , Mathieu Desnoyers , linux-kernel@vger.kernel.org, linux-mm@kvack.org, linux-trace-kernel@vger.kernel.org, Shuah Khan , Abhishek Bapat Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Following the introduction of the ALLOCINFO_IOC_TOGGLE_TRACE IOCTL and ALLOCINFO_FILTER_MASK_TRACE_ON filters for selective memory allocation tracing, update the kselftests to validate this behaviour. Introduce `test_tracing_toggle_and_filter`, which validates the architecture by: 1. Dynamically toggling trace execution ON for a designated allocation. 2. Evaluating that the TRACE_ON filter precisely isolates the active target across the IOCTL API. 3. Verifying that the targeted allocation correctly reports its `trace_on` metadata state as 1. 4. Toggling trace execution OFF for the same allocation. Signed-off-by: Abhishek Bapat --- .../alloc_tag/allocinfo_ioctl_test.c | 111 +++++++++++++++++- 1 file changed, 108 insertions(+), 3 deletions(-) diff --git a/tools/testing/selftests/alloc_tag/allocinfo_ioctl_test.c b/too= ls/testing/selftests/alloc_tag/allocinfo_ioctl_test.c index 74fd64b2370c..3ef7a12fe35b 100644 --- a/tools/testing/selftests/alloc_tag/allocinfo_ioctl_test.c +++ b/tools/testing/selftests/alloc_tag/allocinfo_ioctl_test.c @@ -48,6 +48,11 @@ static inline int __allocinfo_get_next(int dev_fd, struc= t allocinfo_tag_data *pa return ioctl(dev_fd, ALLOCINFO_IOC_GET_NEXT, params); } =20 +static inline int __allocinfo_toggle_trace(int dev_fd, struct allocinfo_to= ggle_traces *params) +{ + return ioctl(dev_fd, ALLOCINFO_IOC_TOGGLE_TRACE, params); +} + static bool match_entry(const struct allocinfo_tag_data *procfs_entry, const struct allocinfo_tag_data *tag_data, bool match_bytes, bool match_calls, bool match_lineno, @@ -289,6 +294,8 @@ static int run_filter_test(const struct allocinfo_filte= r *filter) return ret; } =20 +static const char *target_test_function =3D "dup_mm"; + static int test_filename_filter(void) { struct allocinfo_filter filter; @@ -304,11 +311,10 @@ static int test_filename_filter(void) static int test_function_filter(void) { struct allocinfo_filter filter; - const char *target_function =3D "dup_mm"; =20 memset(&filter, 0, sizeof(filter)); filter.mask |=3D ALLOCINFO_FILTER_MASK_FUNCTION; - strncpy(filter.fields.function, target_function, ALLOCINFO_STR_SIZE); + strncpy(filter.fields.function, target_test_function, ALLOCINFO_STR_SIZE); =20 return run_filter_test(&filter); } @@ -514,11 +520,104 @@ static int test_lineno_filter(void) return ret; } =20 +static enum ioctl_ret toggle_trace(struct allocinfo_tag *target_tag, + bool enable) +{ + int fd; + struct allocinfo_toggle_traces toggle_params; + + fd =3D open(ALLOCINFO_PROC, O_RDONLY); + if (fd < 0) { + ksft_print_msg("Failed to open " ALLOCINFO_PROC ": %s\n", strerror(errno= )); + return IOCTL_FAILURE; + } + + memset(&toggle_params, 0, sizeof(toggle_params)); + toggle_params.fields =3D *target_tag; + toggle_params.enable =3D enable; + + if (__allocinfo_toggle_trace(fd, &toggle_params)) { + close(fd); + return IOCTL_FAILURE; + } + + close(fd); + return IOCTL_SUCCESS; +} + +static int test_tracing_toggle_and_filter(void) +{ + struct allocinfo_filter filter =3D { 0 }; + enum ioctl_ret ioctl_status; + int ret =3D KSFT_PASS; + bool initial_state, target_state; + struct allocinfo_tag target_tag; + struct allocinfo_tag_data_vec *tags =3D calloc(1, sizeof(*tags)); + + if (!tags) { + ksft_print_msg("Memory allocation failed.\n"); + return KSFT_FAIL; + } + + filter.mask |=3D ALLOCINFO_FILTER_MASK_FUNCTION; + strncpy(filter.fields.function, target_test_function, ALLOCINFO_STR_SIZE); + + ioctl_status =3D get_filtered_ioctl_entries(tags, &filter, 0); + if (ioctl_status !=3D IOCTL_SUCCESS || tags->count =3D=3D 0) { + ksft_print_msg("Could not retrieve IOCTL entries for %s\n", target_test_= function); + ret =3D KSFT_SKIP; + goto exit; + } + + target_tag =3D tags->tag[0].tag; + initial_state =3D tags->tag[0].counter.trace_on; + target_state =3D !initial_state; + + ioctl_status =3D toggle_trace(&target_tag, target_state); + if (ioctl_status !=3D IOCTL_SUCCESS) { + ksft_print_msg("Failed to toggle tracing\n"); + ret =3D KSFT_FAIL; + goto exit; + } + + filter.mask |=3D ALLOCINFO_FILTER_MASK_TRACE_ON; + filter.tracing =3D target_state; + + ioctl_status =3D get_filtered_ioctl_entries(tags, &filter, 0); + if (ioctl_status !=3D IOCTL_SUCCESS) { + ksft_print_msg("Error retrieving IOCTL entries with trace filter.\n"); + ret =3D KSFT_FAIL; + goto exit_revert; + } + + if (tags->count !=3D 1) { + ksft_print_msg("Expected exactly 1 entry, but got %llu\n", tags->count); + ret =3D KSFT_FAIL; + goto exit_revert; + } + + if (tags->tag[0].counter.trace_on !=3D target_state) { + ksft_print_msg("Entry returned by trace filter does not match target sta= te\n"); + ret =3D KSFT_FAIL; + } + +exit_revert: + ioctl_status =3D toggle_trace(&target_tag, initial_state); + if (ioctl_status !=3D IOCTL_SUCCESS) { + ksft_print_msg("Failed to revert tracing to initial state\n"); + ret =3D KSFT_FAIL; + } + +exit: + free(tags); + return ret; +} + int main(int argc, char *argv[]) { int ret; =20 - ksft_set_plan(4); + ksft_set_plan(5); =20 ret =3D test_filename_filter(); if (ret =3D=3D KSFT_SKIP) @@ -526,6 +625,12 @@ int main(int argc, char *argv[]) else ksft_test_result(ret =3D=3D KSFT_PASS, "test_filename_filter\n"); =20 + ret =3D test_tracing_toggle_and_filter(); + if (ret =3D=3D KSFT_SKIP) + ksft_test_result_skip("Skipping test_tracing_toggle_and_filter\n"); + else + ksft_test_result(ret =3D=3D KSFT_PASS, "test_tracing_toggle_and_filter\n= "); + ret =3D test_function_filter(); if (ret =3D=3D KSFT_SKIP) ksft_test_result_skip("Skipping test_function_filter\n"); --=20 2.55.0.1082.g2b9226bbc0-goog