From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id A627DC54FB3 for ; Thu, 29 May 2025 17:00:41 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 298526B007B; Thu, 29 May 2025 13:00:41 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 2496E6B0082; Thu, 29 May 2025 13:00:41 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 111AC6B0083; Thu, 29 May 2025 13:00:41 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0017.hostedemail.com [216.40.44.17]) by kanga.kvack.org (Postfix) with ESMTP id D92ED6B007B for ; Thu, 29 May 2025 13:00:40 -0400 (EDT) Received: from smtpin19.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay01.hostedemail.com (Postfix) with ESMTP id 9B07B1D44F2 for ; Thu, 29 May 2025 17:00:40 +0000 (UTC) X-FDA: 83496559440.19.0DE2A9A Received: from tor.source.kernel.org (tor.source.kernel.org [172.105.4.254]) by imf22.hostedemail.com (Postfix) with ESMTP id D1D93C000A for ; Thu, 29 May 2025 17:00:38 +0000 (UTC) Authentication-Results: imf22.hostedemail.com; dkim=none; dmarc=none; spf=pass (imf22.hostedemail.com: domain of "SRS0=SoWH=YN=goodmis.org=rostedt@kernel.org" designates 172.105.4.254 as permitted sender) smtp.mailfrom="SRS0=SoWH=YN=goodmis.org=rostedt@kernel.org" ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1748538038; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding:in-reply-to: references; bh=gZHg8pmOzowUo7gi0tGz9nBAcS6EkKzYoU/W9jIgg8Y=; b=ZO80uhQiu8k5SdlRcqvExr5/2Dn1rqHUJKpSkZsuX/4tH8FKLPOiuEjnrdrfNr7wUDhlui TbjxgKbLjwHBXiSh1PFn7CHCaduQn0RWkfcGKvgoNk5pvAqAwL3qmpYgO/NOhixmfuqVsm j76KO9ARznm+ILhXZq/E2dq28C/GH+A= ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1748538038; a=rsa-sha256; cv=none; b=025Z1vxfMMWrvtACfcmy1rKoqQwKwN79afgeFqG0lOCt8XxSsVoZHj2Jkrx81M14ksOTP7 ZC3qrBhJvv7TGHcH5ruci08IN32au164Lq8w6U7UEgNsjlvbxZBVzWlSbW1dA6Os/7TS66 HrNUN7vxf4wYsnx6rtG9C2ewOgM+g3I= ARC-Authentication-Results: i=1; imf22.hostedemail.com; dkim=none; dmarc=none; spf=pass (imf22.hostedemail.com: domain of "SRS0=SoWH=YN=goodmis.org=rostedt@kernel.org" designates 172.105.4.254 as permitted sender) smtp.mailfrom="SRS0=SoWH=YN=goodmis.org=rostedt@kernel.org" Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by tor.source.kernel.org (Postfix) with ESMTP id 1FFB460010; Thu, 29 May 2025 17:00:38 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6CC55C4CEEA; Thu, 29 May 2025 17:00:36 +0000 (UTC) Date: Thu, 29 May 2025 13:01:38 -0400 From: Steven Rostedt To: LKML , Linux Trace Kernel Cc: Mathieu Desnoyers , Masami Hiramatsu , Mark Rutland , Andrew Morton , Lorenzo Stoakes , Caleb Sander Mateos , Peter Zijlstra , Ingo Molnar , Borislav Petkov , Thomas Gleixner , linux-mm@kvack.org Subject: [RFC][PATCH] tracepoints: Add verifier that makes sure all defined tracepoints are used Message-ID: <20250529130138.544ffec4@gandalf.local.home> X-Mailer: Claws Mail 3.20.0git84 (GTK+ 2.24.33; x86_64-pc-linux-gnu) MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit X-Rspamd-Server: rspam10 X-Rspamd-Queue-Id: D1D93C000A X-Stat-Signature: ma7tgw5gbzweo48eqh6x1n646mingxgi X-Rspam-User: X-HE-Tag: 1748538038-372120 X-HE-Meta: U2FsdGVkX187UAYYTd6hCWWDAeoed49U67dfJyMZyzoUPrF2Lz79zIfYKkd+t47IDGfCYneSSqO1DbZPA1/VSOeKv+tSyyjuRGpOa2H+GUR2qxQFcokXb17XkXZrvwgZVsGO8FVjhelwayJZA94PmCOjZF83ArN0QABne+qVoOJ8lXIUAtOOWjTKtB1LIvvIC6AwJ3HCwAhelptTNnnbNsIEW0jzD6qfgo2DdNMLMD8/vm2oJjNVil4apQa8/XPazzP15iD192tCmzYjxMKCiymvdAkWIrXMzmD5aebo9CwX+ZW+i3foa9YQLOi5YH9Ko/18Yb8/W8IxpMj6E/vPaVp56uNO+ukH/a70qLGFPyg3vIKFsCfiuke4nvT8NhX6loCp4sQPLnRkKfFWsArTcncpQ6jX478kgEwzkeRDFuhebjPh94U3O0JVzEFar2ZBmSLL9wQ1P4ZEgbHxhPQNcuC5qG96xRUVVTzfvjCONgV6cHs4l1Xidk+R8appFT/nNJSo7VhCqAq35as+58M0FU5FabhJWYRmQPvHwSoCZV4E8rcv3fyrpRlBA0TPaRPllIWblmcmNv6k4qBCVFy+Ap+lzHt60RlG5XfgxQ0czBl++HJoHfZeL3syh8o2T8TrpBiyOdcB4DC8w8yGd7wMwq83qjqIKqrdfAxY+gMGT+jW7SF3lxTfpiY/lxmmRvWuY17Vn+/8h4LXMaHTg7O7HlBrvkGrLqmGwRtAAMoV+3vPQCp4YD9SQjBiny0gody+Z64J3+Vs53yQVvgGcOzIcoSmJbF2PX7nzylPoTC9X3jv3ritSAENIPjT8b+JpxaTlgllKbnlWKHYZCoBNeVgmGL1x7Wg9iYm7Lkw9RPmHpuAjapo0pTcAwQHSrqBEMdKJCWEex+auR3bUh6z5QjVau/jfqun3EQ53XqE2Alk61C8wlDfB6PnFjh3fhkfBngG/atwH6j9efWg3vI2nLh xb0RP1vt yO+KM07pCDfRUX6lucQFyq41GW+axVZ4sQDcXh436aQmU/202GpOZaPdd0dkYBQHag77sVyD6tkzIOw6xL0GH6byw6ClaWo5LkDz0bkoYqWtEKaRlgB0h6a7JRfpPGsNDfhj+joC0CVX8uqY4nU1D2FWnnm0wqdkEEzvZiK2/xhd2HeMERi79+fRhC5zfgxr58CTeYtYjnooPU83We/cHZOTjQCtEXYkGrxtaXaJwxOouXVI/o0XaJDMOypQwijxKgsFKRohwoIvEs/pYqeBiMnn4wSt1dIpXx5GS64xGxE8OKemih1nq2UPcJASoJgoYxd4Y3AZZj7b5cFQ= X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: From: Steven Rostedt If a tracepoint is defined via DECLARE_TRACE() or TRACE_EVENT() but never called (via the trace_() function), its meta data is still around in memory and not discarded. When created via TRACE_EVENT() the situation is worse because the TRACE_EVENT() creates meta data that can be around 5k per trace event. Having unused trace events causes several thousand of wasted bytes. Add a verifier that injects a pointer to the tracepoint structure in the functions that are used and added to a section called __tracepoint_check. Then on boot up, iterate over this section and for every tracepoint descriptor that is pointed to, update its ".funcs" field to (void *)1, as the .funcs field is only set when a tracepoint is registered. At this time, no tracepoints should be registered. Then iterate all tracepoints and if any tracepoints doesn't have its .funcs field set to (void*)1, trigger a warning, and list all tracepoints that are not found. Enabling this currently with a given config produces: Tracepoint x86_fpu_before_restore unused Tracepoint x86_fpu_after_restore unused Tracepoint x86_fpu_init_state unused Tracepoint pelt_hw_tp unused Tracepoint pelt_irq_tp unused Tracepoint ipi_raise unused Tracepoint ipi_entry unused Tracepoint ipi_exit unused Tracepoint irq_matrix_alloc_reserved unused Tracepoint psci_domain_idle_enter unused Tracepoint psci_domain_idle_exit unused Tracepoint powernv_throttle unused Tracepoint clock_enable unused Tracepoint clock_disable unused Tracepoint clock_set_rate unused Tracepoint power_domain_target unused Tracepoint xdp_bulk_tx unused Tracepoint xdp_redirect_map unused Tracepoint xdp_redirect_map_err unused Tracepoint mem_return_failed unused Tracepoint vma_mas_szero unused Tracepoint vma_store unused Tracepoint hugepage_set_pmd unused Tracepoint hugepage_set_pud unused Tracepoint hugepage_update_pmd unused Tracepoint hugepage_update_pud unused Tracepoint dax_pmd_insert_mapping unused Tracepoint dax_insert_mapping unused Tracepoint block_rq_remap unused Tracepoint xhci_dbc_handle_event unused Tracepoint xhci_dbc_handle_transfer unused Tracepoint xhci_dbc_gadget_ep_queue unused Tracepoint xhci_dbc_alloc_request unused Tracepoint xhci_dbc_free_request unused Tracepoint xhci_dbc_queue_request unused Tracepoint xhci_dbc_giveback_request unused Tracepoint tcp_ao_wrong_maclen unused Tracepoint tcp_ao_mismatch unused Tracepoint tcp_ao_key_not_found unused Tracepoint tcp_ao_rnext_request unused Tracepoint tcp_ao_synack_no_key unused Tracepoint tcp_ao_snd_sne_update unused Tracepoint tcp_ao_rcv_sne_update unused Some of the above is totally unused but others are not used due to their "trace_" functions being inside configs, in which case, the defined tracepoints should also be inside those same configs. Others are architecture specific but defined in generic code, where they should either be moved to the architecture or be surrounded by #ifdef for the architectures they are for. Note, currently this only handles tracepoints that are builtin. This can easily be extended to verify tracepoints used by modules, but it requires a slightly different approach as it needs updates to the module code. Link: https://lore.kernel.org/all/20250528114549.4d8a5e03@gandalf.local.home/ Signed-off-by: Steven Rostedt (Google) --- include/asm-generic/vmlinux.lds.h | 1 + include/linux/tracepoint.h | 10 ++++++++++ kernel/trace/Kconfig | 8 ++++++++ kernel/tracepoint.c | 26 ++++++++++++++++++++++++++ 4 files changed, 45 insertions(+) diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index fa5f19b8d53a..600d8b51e315 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -708,6 +708,7 @@ defined(CONFIG_AUTOFDO_CLANG) || defined(CONFIG_PROPELLER_CLANG) MCOUNT_REC() \ *(.init.rodata .init.rodata.*) \ FTRACE_EVENTS() \ + BOUNDED_SECTION_BY(__tracepoint_check, ___tracepoint_check) \ TRACE_SYSCALLS() \ KPROBE_BLACKLIST() \ ERROR_INJECT_WHITELIST() \ diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h index a351763e6965..c9c03ec8e552 100644 --- a/include/linux/tracepoint.h +++ b/include/linux/tracepoint.h @@ -221,6 +221,14 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p) __do_trace_##name(args); \ } +#ifdef CONFIG_TRACEPOINT_VERIFY_USED +# define TRACEPOINT_CHECK(name) \ + static void __used __section("__tracepoint_check") *__trace_check = \ + &__tracepoint_##name; +#else +# define TRACEPOINT_CHECK(name) +#endif + /* * Make sure the alignment of the structure in the __tracepoints section will * not add unwanted padding between the beginning of the section and the @@ -270,6 +278,7 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p) __DECLARE_TRACE_COMMON(name, PARAMS(proto), PARAMS(args), PARAMS(data_proto)) \ static inline void __do_trace_##name(proto) \ { \ + TRACEPOINT_CHECK(name) \ if (cond) { \ guard(preempt_notrace)(); \ __DO_TRACE_CALL(name, TP_ARGS(args)); \ @@ -289,6 +298,7 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p) __DECLARE_TRACE_COMMON(name, PARAMS(proto), PARAMS(args), PARAMS(data_proto)) \ static inline void __do_trace_##name(proto) \ { \ + TRACEPOINT_CHECK(name) \ guard(rcu_tasks_trace)(); \ __DO_TRACE_CALL(name, TP_ARGS(args)); \ } \ diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig index a3f35c7d83b6..8867eee5b58f 100644 --- a/kernel/trace/Kconfig +++ b/kernel/trace/Kconfig @@ -1044,6 +1044,14 @@ config GCOV_PROFILE_FTRACE Note that on a kernel compiled with this config, ftrace will run significantly slower. +config TRACEPOINT_VERIFY_USED + bool "Verify that all defined tracepoints are used" + depends on TRACEPOINTS + help + This option checks if every builtin defined tracepoint is + used in the code. If a tracepoint is defined but not used, + it will waste memory as its meta data is still created. + config FTRACE_SELFTEST bool diff --git a/kernel/tracepoint.c b/kernel/tracepoint.c index 62719d2941c9..f354d3850a04 100644 --- a/kernel/tracepoint.c +++ b/kernel/tracepoint.c @@ -677,10 +677,36 @@ static struct notifier_block tracepoint_module_nb = { .priority = 0, }; +#ifdef CONFIG_TRACEPOINT_VERIFY_USED +extern void * __start___tracepoint_check[]; +extern void * __stop___tracepoint_check[]; + +#define VERIFIED_TRACEPOINT ((void *)1) + +static void check_tracepoint(struct tracepoint *tp, void *priv) +{ + if (WARN_ONCE(tp->funcs != VERIFIED_TRACEPOINT, "Unused tracepoints found")) + pr_warn("Tracepoint %s unused\n", tp->name); + + tp->funcs = NULL; +} +#endif + static __init int init_tracepoints(void) { int ret; +#ifdef CONFIG_TRACEPOINT_VERIFY_USED + for (void **ptr = __start___tracepoint_check; + ptr < __stop___tracepoint_check; ptr++) { + struct tracepoint *tp = *ptr; + + tp->funcs = VERIFIED_TRACEPOINT; + } + + for_each_kernel_tracepoint(check_tracepoint, NULL); +#endif + ret = register_module_notifier(&tracepoint_module_nb); if (ret) pr_warn("Failed to register tracepoint module enter notifier\n"); -- 2.47.2