From nobody Thu Apr 2 20:28:06 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CEEC9389115 for ; Thu, 26 Mar 2026 14:26:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774535189; cv=none; b=WRp/ySY1RClHbwAi4VC5V+7N54u9accRc/JrtWwahHfR35Px/CoxyruB4lg4qWaQliic04Ep0l9yrfdDlWj/KFUAxpoCJM6VL336ln/Kj+NQvez/UssJMUaKe0A9kW+cwRdYJkGpp74g3o6nIwPCFeTdsXH1TUmVuZ2nZuf33tY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774535189; c=relaxed/simple; bh=9WBcVw9Mn5JnV5u0u1fcUdkgNqAM6vpU1uJiOvoVRNg=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=W3ucmESJ8Ewe0vCOInnRaeXsK64Lb5+O2g+m6SEi+Ak37VOI4Qkv5/Fq1BTy4LG3Mj8/8bA26rk5yBnGtGMuWVL5M/UrvF1wd7RBFkMgu98wGxNyYZpavSDjEwzhPHGmyi9fQ31xK7eO43P9Bl2OxqQejJxZP8A9+CWf2yRsmL8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=bTMQAqnc; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="bTMQAqnc" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 92D32C19424; Thu, 26 Mar 2026 14:26:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774535189; bh=9WBcVw9Mn5JnV5u0u1fcUdkgNqAM6vpU1uJiOvoVRNg=; h=Date:From:To:Cc:Subject:References:From; b=bTMQAqncGl4tf04+jiEKAOmjouRyFA6igVBi0YljAaydusdDK91xx6NieC0VjEQdh tb0JzmhARVP+YbgdRCzN817B2MQQzAedkMOALbTl9VnQSA4vMdta/3p+HAFwmnYe4k sa7qsd3qbqIDBjDG1djlhIgZj1N3lec4BAMJmPLYgNYQjRBZg/TYdcTBzUcXQ96w2s n25zWH8/7nChJmI4l+cGce03qPVqBWjUx+fqP7cu/ydXN7H+NG+hALdEearsKjDUHh JCl1JyB3cU0UNXqIVmoJwGKxOX+QhSp0RwyXvhInORaGPfCyxx7FB6mf1HvdRTPEf6 bHgXL0rLJY4fQ== Received: from rostedt by gandalf with local (Exim 4.99.1) (envelope-from ) id 1w5lg4-0000000Du9y-1HhZ; Thu, 26 Mar 2026 10:27:16 -0400 Message-ID: <20260326142716.158410157@kernel.org> User-Agent: quilt/0.69 Date: Thu, 26 Mar 2026 10:26:57 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org Cc: Masami Hiramatsu , Mark Rutland , Mathieu Desnoyers , Andrew Morton , Anna Schumaker , Chuck Lever , Simon Horman , Yury Norov , Randy Dunlap , Jeff Layton , Arnd Bergmann , Andy Shevchenko Subject: [for-next][PATCH 01/13] tracing: move __printf() attribute on __ftrace_vbprintk() References: <20260326142656.794462952@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Arnd Bergmann The sunrpc change to use trace_printk() for debugging caused a new warning for every instance of dprintk() in some configurations, when -Wformat-security is enabled: fs/nfs/getroot.c: In function 'nfs_get_root': fs/nfs/getroot.c:90:17: error: format not a string literal and no format ar= guments [-Werror=3Dformat-security] 90 | nfs_errorf(fc, "NFS: Couldn't getattr on root"); I've been slowly chipping away at those warnings over time with the intention of enabling them by default in the future. While I could not figure out why this only happens for this one instance, I see that the __trace_bprintk() function is always called with a local variable as the format string, rather than a literal. Move the __printf(2,3) annotation on this function from the declaration to the caller. As this is can only be validated for literals, the attribute on the declaration causes the warnings every time, but removing it entirely introduces a new warning on the __ftrace_vbprintk() definition. The format strings still get checked because the underlying literal keeps getting passed into __trace_printk() in the "else" branch, which is not taken but still evaluated for compile-time warnings. Cc: Masami Hiramatsu Cc: Anna Schumaker Cc: Chuck Lever Cc: Simon Horman Cc: Mathieu Desnoyers Cc: Andrew Morton Cc: Yury Norov Cc: Randy Dunlap Link: https://patch.msgid.link/20260203164545.3174910-1-arnd@kernel.org Fixes: ec7d8e68ef0e ("sunrpc: add a Kconfig option to redirect dfprintk() o= utput to trace buffer") Acked-by: Jeff Layton Acked-by: Steven Rostedt (Google) Signed-off-by: Arnd Bergmann Acked-by: Andy Shevchenko Signed-off-by: Steven Rostedt (Google) --- include/linux/trace_printk.h | 1 - kernel/trace/trace_printk.c | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/trace_printk.h b/include/linux/trace_printk.h index bb5874097f24..2670ec7f4262 100644 --- a/include/linux/trace_printk.h +++ b/include/linux/trace_printk.h @@ -107,7 +107,6 @@ do { \ __trace_printk(_THIS_IP_, fmt, ##args); \ } while (0) =20 -extern __printf(2, 3) int __trace_bprintk(unsigned long ip, const char *fmt, ...); =20 extern __printf(2, 3) diff --git a/kernel/trace/trace_printk.c b/kernel/trace/trace_printk.c index 5ea5e0d76f00..3ea17af60169 100644 --- a/kernel/trace/trace_printk.c +++ b/kernel/trace/trace_printk.c @@ -197,6 +197,7 @@ struct notifier_block module_trace_bprintk_format_nb = =3D { .notifier_call =3D module_trace_bprintk_format_notify, }; =20 +__printf(2, 3) int __trace_bprintk(unsigned long ip, const char *fmt, ...) { int ret; --=20 2.51.0 From nobody Thu Apr 2 20:28:06 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CF76D3F99EA for ; Thu, 26 Mar 2026 14:26:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774535189; cv=none; b=Dc56iuk/26L8uegxnSOf7OrRAdPdRjW0c6NfPZ1NLVoR49jzyO/S4mdjyv1dx9tFaFwGxyx7PMD3joVI77fm+goNc2b3Ty4CG8hNPtMSSaRPyBNVgcLA/7IG7OrtCaqFzazUr+TUVkVX61+4pV0aMo3ZmXaiWAb0BheUw4rS46E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774535189; c=relaxed/simple; bh=fH18RRJLVtt2AkQHsFTHXn4+EvWyOFsLmcuEKxKsC0Q=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=HPXDzJaa2ug/y62L2X7Dkv5MrMg7hGi49BXwI1CYCzCKUOB5SwgpfMYdozl0xC07PAube5kkzchqBmVo2/be+hTqZDBpbc9DN3Q0S8rBO/ItXGFnf2p10UZZMHAD0OpwE/uyIKTT2Gj/LtR05SlYiTXRrSHz6T6q0m+v56T+ngk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=bny7jicS; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="bny7jicS" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A7CE6C2BCB3; Thu, 26 Mar 2026 14:26:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774535189; bh=fH18RRJLVtt2AkQHsFTHXn4+EvWyOFsLmcuEKxKsC0Q=; h=Date:From:To:Cc:Subject:References:From; b=bny7jicS2kothtKOArpaDsmoM31eQ+QtHcQT7kk9isbXdLCAsUn980rVYpSP7cNqT zF+akBOEYSEX8qDm2kzNkFGGEq08JjSceYcHhwJ/eDHEBSqv6sjSJ/FujPZVi4E5YY fnDR8zfj94baCF9+5q7DZpIMqs5gUAXXatukojyuG0ZeHj+6Dlm3AQcmicLTjzHoC4 eBxrJMKDZqf5yc9/I252iRgjwoHbHz34tjwIPVVy9p22mkqq7Vj5/iFpHLv3SUnaar CmhyVFwl+nRqLBB3YINNKe6K4uRalRFU+AWmhUMBq3+/TfzoQyEGyU0/IwGRL693hV HtfmTN/RJiL3w== Received: from rostedt by gandalf with local (Exim 4.99.1) (envelope-from ) id 1w5lg4-0000000DuAT-1vzi; Thu, 26 Mar 2026 10:27:16 -0400 Message-ID: <20260326142716.325097418@kernel.org> User-Agent: quilt/0.69 Date: Thu, 26 Mar 2026 10:26:58 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org Cc: Masami Hiramatsu , Mark Rutland , Mathieu Desnoyers , Andrew Morton , Tom Zanussi , Petr Pavlu Subject: [for-next][PATCH 02/13] tracing: Remove unnecessary check for EVENT_FILE_FL_FREED References: <20260326142656.794462952@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Petr Pavlu The event_filter_write() function calls event_file_file() to retrieve a trace_event_file associated with a given file struct. If a non-NULL pointer is returned, the function then checks whether the trace_event_file instance has the EVENT_FILE_FL_FREED flag set. This check is redundant because event_file_file() already performs this validation and returns NULL if the flag is set. The err value is also already initialized to -ENODEV. Remove the unnecessary check for EVENT_FILE_FL_FREED in event_filter_write(). Cc: Masami Hiramatsu Cc: Mathieu Desnoyers Cc: Tom Zanussi Link: https://patch.msgid.link/20260219162737.314231-4-petr.pavlu@suse.com Signed-off-by: Petr Pavlu Signed-off-by: Steven Rostedt (Google) --- kernel/trace/trace_events.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 249d1cba72c0..26d1e95a55d1 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -2247,12 +2247,8 @@ event_filter_write(struct file *filp, const char __u= ser *ubuf, size_t cnt, =20 mutex_lock(&event_mutex); file =3D event_file_file(filp); - if (file) { - if (file->flags & EVENT_FILE_FL_FREED) - err =3D -ENODEV; - else - err =3D apply_event_filter(file, buf); - } + if (file) + err =3D apply_event_filter(file, buf); mutex_unlock(&event_mutex); =20 kfree(buf); --=20 2.51.0 From nobody Thu Apr 2 20:28:06 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E6AFF3FB04F for ; Thu, 26 Mar 2026 14:26:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774535190; cv=none; b=OPB1zo3luzzQuwBZUsiEhm7uUVhsNF6TH/mcffV6t1THhl22XEOHysYVErvef5iTgtuI7Zt7YZ6WvmcaR0YHKjnk3k6EVpxFwkjuKy8VnfYp8jZNKhJtihJVuSm5vtMS712/3dSDbJxUT63V00XD9dFbOOMr+6u8SGHSQYFNNss= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774535190; c=relaxed/simple; bh=zcAw5f43I5Vmc+VHblcCKwXlEacEGDMa1mFfbQf9cpk=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=VdBk/Q0Uq3SLW5qbBEiAm4aD1yemb/Asi7EkKqjmN0fIa1owhxqMmHpgCpVKABMqfUFoOfR90L59odk1neKUrmYmFFJNpDA/En8fxuLiMBek0hIHeEsHWJmh1uWLL/rSl404BqIQipnSknt9zYfzQgKuW+zmp5+Rj7gtosQ8fCg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=FffrcZPd; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="FffrcZPd" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C5832C2BCB5; Thu, 26 Mar 2026 14:26:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774535189; bh=zcAw5f43I5Vmc+VHblcCKwXlEacEGDMa1mFfbQf9cpk=; h=Date:From:To:Cc:Subject:References:From; b=FffrcZPdK2jcl6+B1jL6Hv1kAiTlBpl3QvsaRRRqsrHSg3orPyyjPnb/oeinEh4Ye xBd62IryazFBOv24qiDdTtq4P5VYpTHiAXiDWCqEc/kfZT9IjyCRrwXU9nXF6XqC69 FL7MwjzurPRiEdTYoUWttsBZHMhnAs/txmqXZvDZh77adqzYvV/71F7MPjKowX4Nx6 KRiYV9NwJ5a7R5I4j0bo5/Bwz1Ikh3LPb8GxgLA7i0brqVHOHDfXGf2Wi+arL6IH9W oiaRxva0clknaa+saGN8cRIEdj1EvNQoVVml3wYtmfUfUrM4ODRiEqXPNog4i6ydNs YPZbBCDDI+Nqg== Received: from rostedt by gandalf with local (Exim 4.99.1) (envelope-from ) id 1w5lg4-0000000DuAy-2d9O; Thu, 26 Mar 2026 10:27:16 -0400 Message-ID: <20260326142716.479635119@kernel.org> User-Agent: quilt/0.69 Date: Thu, 26 Mar 2026 10:26:59 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org Cc: Masami Hiramatsu , Mark Rutland , Mathieu Desnoyers , Andrew Morton , Tom Zanussi , Petr Pavlu Subject: [for-next][PATCH 03/13] tracing: Clean up access to trace_event_file from a file pointer References: <20260326142656.794462952@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Petr Pavlu The tracing code provides two functions event_file_file() and event_file_data() to obtain a trace_event_file pointer from a file struct. The primary method to use is event_file_file(), as it checks for the EVENT_FILE_FL_FREED flag to determine whether the event is being removed. The second function event_file_data() is an optimization for retrieving the same data when the event_mutex is still held. In the past, when removing an event directory in remove_event_file_dir(), the code set i_private to NULL for all event files and readers were expected to check for this state to recognize that the event is being removed. In the case of event_id_read(), the value was read using event_file_data() without acquiring the event_mutex. This required event_file_data() to use READ_ONCE() when retrieving the i_private data. With the introduction of eventfs, i_private is assigned when an eventfs inode is allocated and remains set throughout its lifetime. Remove the now unnecessary READ_ONCE() access to i_private in both event_file_file() and event_file_data(). Inline the access to i_private in remove_event_file_dir(), which allows event_file_data() to handle i_private solely as a trace_event_file pointer. Add a check in event_file_data() to ensure that the event_mutex is held and that file->flags doesn't have the EVENT_FILE_FL_FREED flag set. Finally, move event_file_data() immediately after event_file_code() since the latter provides a comment explaining how both functions should be used together. Cc: Masami Hiramatsu Cc: Mathieu Desnoyers Cc: Tom Zanussi Link: https://patch.msgid.link/20260219162737.314231-5-petr.pavlu@suse.com Signed-off-by: Petr Pavlu Signed-off-by: Steven Rostedt (Google) --- kernel/trace/trace.h | 17 +++++++++++------ kernel/trace/trace_events.c | 6 +++--- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index b8f3804586a0..7db78a62f786 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -1802,11 +1802,6 @@ extern struct trace_event_file *find_event_file(stru= ct trace_array *tr, const char *system, const char *event); =20 -static inline void *event_file_data(struct file *filp) -{ - return READ_ONCE(file_inode(filp)->i_private); -} - extern struct mutex event_mutex; extern struct list_head ftrace_events; =20 @@ -1827,12 +1822,22 @@ static inline struct trace_event_file *event_file_f= ile(struct file *filp) struct trace_event_file *file; =20 lockdep_assert_held(&event_mutex); - file =3D READ_ONCE(file_inode(filp)->i_private); + file =3D file_inode(filp)->i_private; if (!file || file->flags & EVENT_FILE_FL_FREED) return NULL; return file; } =20 +static inline void *event_file_data(struct file *filp) +{ + struct trace_event_file *file; + + lockdep_assert_held(&event_mutex); + file =3D file_inode(filp)->i_private; + WARN_ON(!file || file->flags & EVENT_FILE_FL_FREED); + return file; +} + extern const struct file_operations event_trigger_fops; extern const struct file_operations event_hist_fops; extern const struct file_operations event_hist_debug_fops; diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 26d1e95a55d1..6523c873689a 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -2184,12 +2184,12 @@ static int trace_format_open(struct inode *inode, s= truct file *file) static ssize_t event_id_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *pp= os) { - int id =3D (long)event_file_data(filp); + /* id is directly in i_private and available for inode's lifetime. */ + int id =3D (long)file_inode(filp)->i_private; char buf[32]; int len; =20 - if (unlikely(!id)) - return -ENODEV; + WARN_ON(!id); =20 len =3D sprintf(buf, "%d\n", id); =20 --=20 2.51.0 From nobody Thu Apr 2 20:28:06 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 29ACD3FB044 for ; Thu, 26 Mar 2026 14:26:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774535190; cv=none; b=JDIfmRpBEEuf2tCmYMUqAPuUG9zNUCyWYVQ3giQu7gkEIe3K93PffR7HLtj8QCqxQJYVO5BmisakMkMCB02oRKraAI47y368NP6XIoigg51qee5CMCRc8P+MIYfmrKFeOcfKMuy5MEZl3El3YQNIrTddg2mR4r7hgEGnq7DUxIc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774535190; c=relaxed/simple; bh=emVsdbxH1gETPmcQ4E7Fjci/kpiDTa+ULuaDf/TIRfI=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=g/13BlxVft50vhhgo+dFjpKAlbd+i4SghXmmM+kiVa8CYPJFjQS9BQtG3bNPvI2kt0aMtcpShvTfz+kNJSbsY2wjSOi8VH/3lV0bVvBosa89AOSpaKCuX2PodqilXmChgZStPcQztrgvWatUqCDCf+u9nmbVbBqn2+rvCYMJ0og= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Hx7ZYPaf; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Hx7ZYPaf" Received: by smtp.kernel.org (Postfix) with ESMTPSA id EBA31C2BCB0; Thu, 26 Mar 2026 14:26:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774535190; bh=emVsdbxH1gETPmcQ4E7Fjci/kpiDTa+ULuaDf/TIRfI=; h=Date:From:To:Cc:Subject:References:From; b=Hx7ZYPafnnwaXFRkxhai8829zmP4JTo82NEWUXvtF/LZqssW5ZyJXQdQJc00lfDpo WpmSxWDeQ54gqPxcbhaqlFkto1sIVQcAqNM9oF0mpOUuL7r1Ev2VMKkVHw+XBfiI74 LULQ1A3GFe/wN40/WUNhBLuirIjPZ//aewn1NKUpcanLEJvC+AA/3ayiIzbtWnlOYI fc7n++oEBv8qxU6U8OOUWJVg/QZf95EYhS4oZpXY59w+Nfsj5hb9Us1dkF6NnjoNxT 8XanQZc3sitegLvbskbUz6b0RjvHsp1km6SKPO498799jYoOFHXmeU+nESKP2+k/Ef QNj6NHReGR0fA== Received: from rostedt by gandalf with local (Exim 4.99.1) (envelope-from ) id 1w5lg4-0000000DuBT-3Ega; Thu, 26 Mar 2026 10:27:16 -0400 Message-ID: <20260326142716.644352953@kernel.org> User-Agent: quilt/0.69 Date: Thu, 26 Mar 2026 10:27:00 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org Cc: Masami Hiramatsu , Mark Rutland , Mathieu Desnoyers , Andrew Morton , Tom Zanussi , Petr Pavlu Subject: [for-next][PATCH 04/13] tracing: Free up file->private_data for use by individual events References: <20260326142656.794462952@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Petr Pavlu The tracing_open_file_tr() function currently copies the trace_event_file pointer from inode->i_private to file->private_data when the file is successfully opened. This duplication is not particularly useful, as all event code should utilize event_file_file() or event_file_data() to retrieve a trace_event_file pointer from a file struct and these access functions read file->f_inode->i_private. Moreover, this setup requires the code for opening hist files to explicitly clear file->private_data before calling single_open(), since this function expects the private_data member to be set to NULL and uses it to store a pointer to a seq_file. Remove the unnecessary setting of file->private_data in tracing_open_file_tr() and simplify the hist code. Cc: Masami Hiramatsu Cc: Mathieu Desnoyers Cc: Tom Zanussi Link: https://patch.msgid.link/20260219162737.314231-6-petr.pavlu@suse.com Signed-off-by: Petr Pavlu Signed-off-by: Steven Rostedt (Google) --- kernel/trace/trace.c | 2 -- kernel/trace/trace_events_hist.c | 4 ---- 2 files changed, 6 deletions(-) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index a626211ceb9a..cf48fe23e71f 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -4050,8 +4050,6 @@ int tracing_open_file_tr(struct inode *inode, struct = file *filp) event_file_get(file); } =20 - filp->private_data =3D inode->i_private; - return 0; } =20 diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_h= ist.c index 73ea180cad55..67cb92310864 100644 --- a/kernel/trace/trace_events_hist.c +++ b/kernel/trace/trace_events_hist.c @@ -5836,8 +5836,6 @@ static int event_hist_open(struct inode *inode, struc= t file *file) hist_file->file =3D file; hist_file->last_act =3D get_hist_hit_count(event_file); =20 - /* Clear private_data to avoid warning in single_open() */ - file->private_data =3D NULL; ret =3D single_open(file, hist_show, hist_file); if (ret) { kfree(hist_file); @@ -6126,8 +6124,6 @@ static int event_hist_debug_open(struct inode *inode,= struct file *file) if (ret) return ret; =20 - /* Clear private_data to avoid warning in single_open() */ - file->private_data =3D NULL; ret =3D single_open(file, hist_debug_show, file); if (ret) tracing_release_file_tr(inode, file); --=20 2.51.0 From nobody Thu Apr 2 20:28:06 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4B5693FCB18 for ; Thu, 26 Mar 2026 14:26:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774535190; cv=none; b=IGE/typzJD2cH9PUbjmxGskeckMfR9ensHgGvSmITlbtE7lg3gLvyzA419J8HAEJNCL5UyhVrgig9Jt2l3ndTx3OqBKPGfUOVTztM/DaRhzJ+08Q9gM1vjUkm2EMfh0Wf/VdHYR6rfDhkVGemwzg09X6ORL5a95Krj9+sLg+Piw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774535190; c=relaxed/simple; bh=MUgVeWs0HVVRJ2A2+99r4QuA6JCEuXiaxwag2K8Berw=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=UO9j5jbJEuQ8+4t8T4HfhbDkjfnwuX0dKOJpGGCXBTYS4ABTTDi8lZYOqJcN5oEXvlZ7IelzIYoSOZKqtqgP2sr/6ZjbDyH1Nre78XtUQK+Sd0M5b038/gN5KQk1wP8ev1PQKsfXHUSV/e8iot1h8jT7LkbEiiD4i4RcftHUDMI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=NaKAJVH0; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="NaKAJVH0" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 14141C2BCB3; Thu, 26 Mar 2026 14:26:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774535190; bh=MUgVeWs0HVVRJ2A2+99r4QuA6JCEuXiaxwag2K8Berw=; h=Date:From:To:Cc:Subject:References:From; b=NaKAJVH0ODboKDQN0hEe4nr5Jxcc31ZIkL6X3riG+95IO87S/2pKWLlorjm+4+xyK CnB7SH95hAATdzsvvv8gTbJUGttMqM92QDWJbDp0zGGatpsoi0ry52gfJSHT2UpaUv ZCHh4iOADcPw2Ci0Zo5F9tOGN6H9D8hNgKkqcGtLaZzSho98DW3zVqX93VcRchmUCq dPJrL7UN+B24FNumuNXl2WWbdXoynmj546MYVFAIR59CbUMuEj1SoK76So/I4p3ZeM CEOLThYySiXYKTbI/rqfzFrikMj2oZ19M1n6KBohPd473tZ7KXSGkhCZpNZdVyeTDg I9d2RMyvdd4eA== Received: from rostedt by gandalf with local (Exim 4.99.1) (envelope-from ) id 1w5lg4-0000000DuBx-3rra; Thu, 26 Mar 2026 10:27:16 -0400 Message-ID: <20260326142716.787543618@kernel.org> User-Agent: quilt/0.69 Date: Thu, 26 Mar 2026 10:27:01 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org Cc: Masami Hiramatsu , Mark Rutland , Mathieu Desnoyers , Andrew Morton , Donglin Peng Subject: [for-next][PATCH 05/13] tracing: Pretty-print enum parameters in function arguments References: <20260326142656.794462952@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Donglin Peng Currently, print_function_args() prints enum parameter values in decimal format, reducing trace log readability. Use BTF information to resolve enum parameters and print their symbolic names (where available). This improves readability by showing meaningful identifiers instead of raw numbers. Before: mod_memcg_lruvec_state(lruvec=3D0xffff..., idx=3D5, val=3D320) After: mod_memcg_lruvec_state(lruvec=3D0xffff..., idx=3D5 [NR_SLAB_RECLAIMABLE_B= ], val=3D320) Cc: Steven Rostedt Cc: Masami Hiramatsu Link: https://patch.msgid.link/20260209071949.4040193-1-dolinux.peng@gmail.= com Signed-off-by: Donglin Peng Signed-off-by: Steven Rostedt (Google) --- kernel/trace/trace_output.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/kernel/trace/trace_output.c b/kernel/trace/trace_output.c index 1996d7aba038..be0755400f9b 100644 --- a/kernel/trace/trace_output.c +++ b/kernel/trace/trace_output.c @@ -719,12 +719,13 @@ void print_function_args(struct trace_seq *s, unsigne= d long *args, { const struct btf_param *param; const struct btf_type *t; + const struct btf_enum *enums; const char *param_name; char name[KSYM_NAME_LEN]; unsigned long arg; struct btf *btf; s32 tid, nr =3D 0; - int a, p, x; + int a, p, x, i; u16 encode; =20 trace_seq_printf(s, "("); @@ -778,6 +779,15 @@ void print_function_args(struct trace_seq *s, unsigned= long *args, break; case BTF_KIND_ENUM: trace_seq_printf(s, "%ld", arg); + enums =3D btf_enum(t); + for (i =3D 0; i < btf_vlen(t); i++) { + if (arg =3D=3D enums[i].val) { + trace_seq_printf(s, " [%s]", + btf_name_by_offset(btf, + enums[i].name_off)); + break; + } + } break; default: /* This does not handle complex arguments */ --=20 2.51.0 From nobody Thu Apr 2 20:28:06 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5A9243FCB1B for ; Thu, 26 Mar 2026 14:26:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774535190; cv=none; b=AhHNFSpHyuPhtk9aon6XKD2afWjQ819xIHdqwVNqC/OzA0N8EuXdgrS2zvzBTdSew8nCKKIVXH4pnn5J6J7dHlEMjikMqAWLPmNbYdutJn1Xp95Fz1dbDbig+rYS9J5WIExXkad4IeRRN74S8acYp5mLBfKvnPDE44m18dWnIoM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774535190; c=relaxed/simple; bh=CCaf7Z2zeejiFpnaQdTg+kyJHvswat6Nu2ucqg1V0nU=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=L4cl+BQhNl3HSGbgbNKh9ycbv4Xx2sAdAqIvPrL+rK2mu4lGxzUp4LAja+Mo94E9vxQ3FCAe74VTbB2GrSjYyL34GpBf3aV+Qme6RgCUYJxQL2fU06PB0J7XUZ1OXzuLtOxSRTxjhik2T49XatL1D6PDwL2T3muX+ZhmtfWVeK4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=dXBf9fX2; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="dXBf9fX2" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3DAF1C2BCB4; Thu, 26 Mar 2026 14:26:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774535190; bh=CCaf7Z2zeejiFpnaQdTg+kyJHvswat6Nu2ucqg1V0nU=; h=Date:From:To:Cc:Subject:References:From; b=dXBf9fX2RrkYllOSZnFTJ/mJUd8Ek06HuoZQN+m/Nn1/Zy7afz1brJXnVhZHZtFei 5Gb3YEr6iOiWnO26Y+vFXYFqQVcFxZRFF5ByjCss37d1r5qDyGQukQiuDBgRJU8Fda qScC5T7ngqzMh9atxhn4maoHB8EmKo+mmQZT/PVQ2Cq+XZ5MH0rimRUHm3uQgLNxw8 DyD4vMr7JJvBJ6seIucRjCgP4cVskUDxe1J9v3vMsKp0atwcRBM0QePoUwW+f8qDt7 VzBqwQCySvcXZGpM0SWC71GSwNh+GqH34XiJFX9TbPdnCaO3RRalGBDYS2UvwYoaj5 7SbseBmOYkLMw== Received: from rostedt by gandalf with local (Exim 4.99.1) (envelope-from ) id 1w5lg5-0000000DuCR-0IoD; Thu, 26 Mar 2026 10:27:17 -0400 Message-ID: <20260326142716.940055400@kernel.org> User-Agent: quilt/0.69 Date: Thu, 26 Mar 2026 10:27:02 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org Cc: Masami Hiramatsu , Mark Rutland , Mathieu Desnoyers , Andrew Morton , Randy Dunlap Subject: [for-next][PATCH 06/13] tracing: trace_mmap.h: fix a kernel-doc warning References: <20260326142656.794462952@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Randy Dunlap Add a description of struct reader to resolve a kernel-doc warning: Warning: include/uapi/linux/trace_mmap.h:43 struct member 'reader' not desc= ribed in 'trace_buffer_meta' Signed-off-by: Randy Dunlap Acked-by: Masami Hiramatsu (Google) Signed-off-by: Steven Rostedt (Google) --- include/uapi/linux/trace_mmap.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/uapi/linux/trace_mmap.h b/include/uapi/linux/trace_mma= p.h index c102ef35d11e..99653f259a7a 100644 --- a/include/uapi/linux/trace_mmap.h +++ b/include/uapi/linux/trace_mmap.h @@ -10,6 +10,7 @@ * @meta_struct_len: Size of this structure. * @subbuf_size: Size of each sub-buffer. * @nr_subbufs: Number of subbfs in the ring-buffer, including the reader. + * @reader: The reader composite info structure * @reader.lost_events: Number of events lost at the time of the reader sw= ap. * @reader.id: subbuf ID of the current reader. ID range [0 : @nr_subbufs= - 1] * @reader.read: Number of bytes read on the reader subbuf. --=20 2.51.0 From nobody Thu Apr 2 20:28:06 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E529F3FD15F for ; Thu, 26 Mar 2026 14:26:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774535191; cv=none; b=hba8wYspFyADHKMLm6TMX8ciOvCz7ddN7wdF4JfawHT3/S7+UaJaVwWyc67Dog7WEXcxhsoBJHQSQfb0zStaLcrmnNp1AY5SiCWuyhpVTiEuZZw+t/qxaZu2mmpnunvquFkOxhQ8WwdUqmldGgJl72pkThWMBPA6ZWMF9okpLnQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774535191; c=relaxed/simple; bh=ZuX51W2Lsk9HrZx4hd75KNLceSH/hg0E/KRi2LT43dI=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=m/4fKkW2C+h9CJ16IZEZcor5R/aqhUcVU2u9787jBkEkcCzv+TLiVSZRvjGPY2LUb40MAaVJiVdgwnWCKTOzmHxNTPLUrMzpWqEoSJKE4EjhgcASOnA3ysE7E7AwwdhxkjTUGiuCb2KZeI1P0Njx4S1RTQdUMIfQG6UqAZgA/tM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=uoNlxjDC; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="uoNlxjDC" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7A2A5C19423; Thu, 26 Mar 2026 14:26:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774535190; bh=ZuX51W2Lsk9HrZx4hd75KNLceSH/hg0E/KRi2LT43dI=; h=Date:From:To:Cc:Subject:References:From; b=uoNlxjDCvVRx+rhwCzNXCzx7yCgJFzFAZQ2PZ3Lo7+7irpmNIBeR0N6DeajIWQh4O EKF4YyNnFCpA/YOwTm5UVGHklKhwZbEh1CFHI6cPv6bHsIfYR1ikowDgz6bKUgavw7 gJ9BtBYIsjttkQvWO6Z3q3EOLcLXoc1JM8DX78z3ovIGsQVEciXDc+KSoNbway0PN2 hsTwAoUbgWWmtyteGgRx8j6sgLcZV1pMjWRZg7PmvFLfrMr4fNaIKyGscPodztuCG+ r/BAKRCTiCjphmDq3suqKFMFHTTWiGcwPUWeQ5y5iqNngeCuopIWQGDnPVgOHsf7ij UTr/zgSKhsWGw== Received: from rostedt by gandalf with local (Exim 4.99.1) (envelope-from ) id 1w5lg5-0000000DuCv-0wuX; Thu, 26 Mar 2026 10:27:17 -0400 Message-ID: <20260326142717.093894148@kernel.org> User-Agent: quilt/0.69 Date: Thu, 26 Mar 2026 10:27:03 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org Cc: Masami Hiramatsu , Mark Rutland , Mathieu Desnoyers , Andrew Morton , Dmitry Ilvokhin , Ingo Molnar , Jens Axboe , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Alexei Starovoitov , Daniel Borkmann , Marcelo Ricardo Leitner , Xin Long , Jon Maloy , Aaron Conole , Eelco Chaudron , Ilya Maximets , Jiri Pirko , Oded Gabbay , Koby Elbaz , "Rafael J. Wysocki" , Viresh Kumar , "Gautham R. Shenoy" , Huang Rui , Mario Limonciello , Len Brown , Srinivas Pandruvada , MyungJoo Ham , Kyungmin Park , Chanwoo Choi , =?UTF-8?q?Christian=20K=C3=B6nig?= , Sumit Semwal , Eddie James , Andrew Jeffery , Joel Stanley , David Airlie , Simona Vetter , Alex Deucher , Danilo Krummrich , Matthew Brost , Philipp Stanner , Harry Wentland , Leo Li , Jiri Kosina , Benjamin Tissoires , Wolfram Sang , Mark Brown , Michael Hennerich , =?UTF-8?q?Nuno=20S=C3=A1?= , "James E.J. Bottomley" , "Martin K. Petersen" , Chris Mason , David Sterba , Thomas Gleixner , SeongJae Park , Borislav Petkov , Dave Hansen , Peter Zijlstra , "Vineeth Pillai (Google)" Subject: [for-next][PATCH 07/13] tracepoint: Add trace_call__##name() API References: <20260326142656.794462952@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable From: "Vineeth Pillai (Google)" Add trace_call__##name() as a companion to trace_##name(). When a caller already guards a tracepoint with an explicit enabled check: if (trace_foo_enabled() && cond) trace_foo(args); trace_foo() internally repeats the static_branch_unlikely() test, which the compiler cannot fold since static branches are patched binary instructions. This results in two static-branch evaluations for every guarded call site. trace_call__##name() calls __do_trace_##name() directly, skipping the redundant static-branch re-check. This avoids leaking the internal __do_trace_##name() symbol into call sites while still eliminating the double evaluation: if (trace_foo_enabled() && cond) trace_invoke_foo(args); /* calls __do_trace_foo() directly */ Three locations are updated: - __DECLARE_TRACE: invoke form omits static_branch_unlikely, retains the LOCKDEP RCU-watching assertion. - __DECLARE_TRACE_SYSCALL: same, plus retains might_fault(). - !TRACEPOINTS_ENABLED stub: empty no-op so callers compile cleanly when tracepoints are compiled out. Cc: Dmitry Ilvokhin Cc: Mathieu Desnoyers Cc: Ingo Molnar Cc: Jens Axboe Cc: "David S. Miller" Cc: Eric Dumazet Cc: Jakub Kicinski Cc: Paolo Abeni Cc: Alexei Starovoitov Cc: Daniel Borkmann Cc: Marcelo Ricardo Leitner Cc: Xin Long Cc: Jon Maloy Cc: Aaron Conole Cc: Eelco Chaudron Cc: Ilya Maximets Cc: Jiri Pirko Cc: Oded Gabbay Cc: Koby Elbaz Cc: "Rafael J. Wysocki" Cc: Viresh Kumar Cc: "Gautham R. Shenoy" Cc: Huang Rui Cc: Mario Limonciello Cc: Len Brown Cc: Srinivas Pandruvada Cc: MyungJoo Ham Cc: Kyungmin Park Cc: Chanwoo Choi Cc: Christian K=C3=B6nig Cc: Sumit Semwal Cc: Eddie James Cc: Andrew Jeffery Cc: Joel Stanley Cc: David Airlie Cc: Simona Vetter Cc: Alex Deucher Cc: Danilo Krummrich Cc: Matthew Brost Cc: Philipp Stanner Cc: Harry Wentland Cc: Leo Li Cc: Jiri Kosina Cc: Benjamin Tissoires Cc: Wolfram Sang Cc: Mark Brown Cc: Michael Hennerich Cc: Nuno S=C3=A1 Cc: "James E.J. Bottomley" Cc: "Martin K. Petersen" Cc: Chris Mason Cc: David Sterba Cc: Thomas Gleixner Cc: Andrew Morton Cc: SeongJae Park Cc: Borislav Petkov Cc: Dave Hansen Link: https://patch.msgid.link/20260323160052.17528-2-vineeth@bitbyteword.o= rg Suggested-by: Steven Rostedt Suggested-by: Peter Zijlstra Acked-by: Masami Hiramatsu (Google) Signed-off-by: Vineeth Pillai (Google) Assisted-by: Claude:claude-sonnet-4-6 Signed-off-by: Steven Rostedt (Google) --- include/linux/tracepoint.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h index 22ca1c8b54f3..ed969705341f 100644 --- a/include/linux/tracepoint.h +++ b/include/linux/tracepoint.h @@ -294,6 +294,10 @@ static inline struct tracepoint *tracepoint_ptr_deref(= tracepoint_ptr_t *p) WARN_ONCE(!rcu_is_watching(), \ "RCU not watching for tracepoint"); \ } \ + } \ + static inline void trace_call__##name(proto) \ + { \ + __do_trace_##name(args); \ } =20 #define __DECLARE_TRACE_SYSCALL(name, proto, args, data_proto) \ @@ -313,6 +317,11 @@ static inline struct tracepoint *tracepoint_ptr_deref(= tracepoint_ptr_t *p) WARN_ONCE(!rcu_is_watching(), \ "RCU not watching for tracepoint"); \ } \ + } \ + static inline void trace_call__##name(proto) \ + { \ + might_fault(); \ + __do_trace_##name(args); \ } =20 /* @@ -398,6 +407,8 @@ static inline struct tracepoint *tracepoint_ptr_deref(t= racepoint_ptr_t *p) #define __DECLARE_TRACE_COMMON(name, proto, args, data_proto) \ static inline void trace_##name(proto) \ { } \ + static inline void trace_call__##name(proto) \ + { } \ static inline int \ register_trace_##name(void (*probe)(data_proto), \ void *data) \ --=20 2.51.0 From nobody Thu Apr 2 20:28:06 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A77223FD140 for ; Thu, 26 Mar 2026 14:26:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774535190; cv=none; b=QgOXd4PIvlu8xcvxgKEwB5fNMfS8fjNjn01bDHXnbT/Ywr11aDN0EEFOLRPpKczKFRplNtToN5FJieucZbfxwjghQVQJAnqx6wybrJlZkErtsqdqVT6NP14i+ZchXQYdt8rRERNGOR+Cr6nXRQFEjistRoTWa4oPOcl+lc8ZtnM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774535190; c=relaxed/simple; bh=GwEQoPZxPaH8/kFLl0DeQs94N1yCBHxSlWsEkNf87UU=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=D91jLFVGACSq24CH4lIhXNV9yAJwuyW6b4t3OGREbCetF0gH0wZ0p8mXFpyuvtvq7LdUj95BmnCGeuHRnhNnvKE5/UyWxqwoqC7i6MjslXE327coAGoVsPLFZzya/TovUGgV1nxb5O/LxsyY0vdPdF3+O8M5OUs/Tyf9WDj4wQg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=fEq9IwSJ; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="fEq9IwSJ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7A763C19424; Thu, 26 Mar 2026 14:26:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774535190; bh=GwEQoPZxPaH8/kFLl0DeQs94N1yCBHxSlWsEkNf87UU=; h=Date:From:To:Cc:Subject:References:From; b=fEq9IwSJai1G+re7AHQ0a0aVbnSlC2CmW4YHApgUvtXJkbfWk4nwD/lGacIE0Uf89 RixcSUM46C+05SYVtP3d1rKHaOG79N1ODrieAf1liFMMXpDeVnf998Uv7GGtRK/V1d zBTxsmS35ME+w1/0gs5MIKmwEigaH7PoTjFoA16ONjpaajER55XyYIrEoZ+ICA7AQu bB1gtLWiMZVKCBMMPdMqb6wgl/uDBRejZzazbOLNtv1nF6RxnKIJLX0+g25wyUkgvU uMKVbvSbOn1JMxbisYFgdZmtbOgyzvAV3AQt+GI223NGQmNtWF3qrm/pIiK3mWEEB7 GMKOxeF+uPvAw== Received: from rostedt by gandalf with local (Exim 4.99.1) (envelope-from ) id 1w5lg5-0000000DuDP-1ZjK; Thu, 26 Mar 2026 10:27:17 -0400 Message-ID: <20260326142717.242926364@kernel.org> User-Agent: quilt/0.69 Date: Thu, 26 Mar 2026 10:27:04 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org Cc: Masami Hiramatsu , Mark Rutland , Mathieu Desnoyers , Andrew Morton , David Vernet , Andrea Righi , Changwoo Min , Ingo Molnar , Juri Lelli , Vincent Guittot , Dietmar Eggemann , Ben Segall , Mel Gorman , Valentin Schneider , Thomas Gleixner , "Yury Norov [NVIDIA]" , "Paul E. McKenney" , Rik van Riel , Roman Kisel , Joel Fernandes , "Rafael J. Wysocki" , Ulf Hansson , Peter Zijlstra , "Vineeth Pillai (Google)" , Tejun Heo Subject: [for-next][PATCH 08/13] kernel: Use trace_call__##name() at guarded tracepoint call sites References: <20260326142656.794462952@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: "Vineeth Pillai (Google)" Replace trace_foo() with the new trace_call__foo() at sites already guarded by trace_foo_enabled(), avoiding a redundant static_branch_unlikely() re-evaluation inside the tracepoint. trace_call__foo() calls the tracepoint callbacks directly without utilizing the static branch again. Cc: David Vernet Cc: Andrea Righi Cc: Changwoo Min Cc: Ingo Molnar Cc: Juri Lelli Cc: Vincent Guittot Cc: Dietmar Eggemann Cc: Ben Segall Cc: Mel Gorman Cc: Valentin Schneider Cc: Thomas Gleixner Cc: "Yury Norov [NVIDIA]" Cc: "Paul E. McKenney" Cc: Rik van Riel Cc: Roman Kisel Cc: Joel Fernandes Cc: "Rafael J. Wysocki" Cc: Ulf Hansson Link: https://patch.msgid.link/20260323160052.17528-3-vineeth@bitbyteword.o= rg Suggested-by: Steven Rostedt Suggested-by: Peter Zijlstra Signed-off-by: Vineeth Pillai (Google) Assisted-by: Claude:claude-sonnet-4-6 Acked-by: Tejun Heo Acked-by: Thomas Gleixner Acked-by: Masami Hiramatsu (Google) Signed-off-by: Steven Rostedt (Google) --- kernel/irq_work.c | 2 +- kernel/sched/ext.c | 2 +- kernel/smp.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel/irq_work.c b/kernel/irq_work.c index 73f7e1fd4ab4..120fd7365fbe 100644 --- a/kernel/irq_work.c +++ b/kernel/irq_work.c @@ -79,7 +79,7 @@ void __weak arch_irq_work_raise(void) static __always_inline void irq_work_raise(struct irq_work *work) { if (trace_ipi_send_cpu_enabled() && arch_irq_work_has_interrupt()) - trace_ipi_send_cpu(smp_processor_id(), _RET_IP_, work->func); + trace_call__ipi_send_cpu(smp_processor_id(), _RET_IP_, work->func); =20 arch_irq_work_raise(); } diff --git a/kernel/sched/ext.c b/kernel/sched/ext.c index 26a6ac2f8826..7da8be1b0f26 100644 --- a/kernel/sched/ext.c +++ b/kernel/sched/ext.c @@ -4493,7 +4493,7 @@ static __printf(2, 3) void dump_line(struct seq_buf *= s, const char *fmt, ...) vscnprintf(line_buf, sizeof(line_buf), fmt, args); va_end(args); =20 - trace_sched_ext_dump(line_buf); + trace_call__sched_ext_dump(line_buf); } #endif /* @s may be zero sized and seq_buf triggers WARN if so */ diff --git a/kernel/smp.c b/kernel/smp.c index f349960f79ca..537cf1f461d7 100644 --- a/kernel/smp.c +++ b/kernel/smp.c @@ -394,7 +394,7 @@ void __smp_call_single_queue(int cpu, struct llist_node= *node) func =3D CSD_TYPE(csd) =3D=3D CSD_TYPE_TTWU ? sched_ttwu_pending : csd->func; =20 - trace_csd_queue_cpu(cpu, _RET_IP_, func, csd); + trace_call__csd_queue_cpu(cpu, _RET_IP_, func, csd); } =20 /* --=20 2.51.0 From nobody Thu Apr 2 20:28:06 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id ED0DB3FE348 for ; Thu, 26 Mar 2026 14:26:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774535191; cv=none; b=adQR6dQ7avgwirMiW5ZSjmZauazEk+ScUTkbdfZghM8tTn3Ras9BKOc58XFbJ2pEUKJoHQ1qXTuX64U8PtQxCjkNSlYUZUMUkL2Wx8RlOUYMBONt9IUNcO5nmEDkxFA226xuIpRlIy2GTwi5mTcp0rw6xWyNRTn4TSZ649UfYac= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774535191; c=relaxed/simple; bh=jov5e7jlVudlYB2gcxiyiPam4xfciFU+ds7ErRDdJuw=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=GhtueV3wcs/WmmVzlN0kStWiz8L1m6uc+KOj5Gp+et1cSIG+Ai2Sc/hSnTZVn7wjcLeSEor0Yw6DyuWd3RmBfGPyGpZxyDj6FmJ5LX8UuVy1cL+UlDb7ZQKB97vTNCgJiYd5ceFHNNDcOO7+8o27t9X1sY4il+ARl+SxSXQO+DA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=hSPkFobb; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="hSPkFobb" Received: by smtp.kernel.org (Postfix) with ESMTPSA id BD93EC2BCB3; Thu, 26 Mar 2026 14:26:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774535190; bh=jov5e7jlVudlYB2gcxiyiPam4xfciFU+ds7ErRDdJuw=; h=Date:From:To:Cc:Subject:References:From; b=hSPkFobbowYQjpZQPw+tus3RE4xnF8jRvri2dfa/uBqVnuQcdPDmfCeCPYpR6jIU1 ueSKsTUmpeWyZIFWRNmRBWtDzs3P0ROyphe446tXuJn8CHe3zyGylQ9rH2AHfu57Jx wM57qn1qSQXpxXYju2OpfC5FTytYMjMp/i+LUvwPzLOyqTl4he+/urPRrt7sZa/eR0 Cnuv2aq/fzWY5vlK/veBCuyH7ltSpxckEmgQ4wTlfZ9bNFmec8qW82d6hu090r23Tv zcSgfrJCkc89351CZPZ9tzjkpm6IQdoZMeyTXkI8pFMEahs01O8dxBC2e+n9d2u73M TJhUKRc6Bki/Q== Received: from rostedt by gandalf with local (Exim 4.99.1) (envelope-from ) id 1w5lg5-0000000DuDv-2CP6; Thu, 26 Mar 2026 10:27:17 -0400 Message-ID: <20260326142717.391191738@kernel.org> User-Agent: quilt/0.69 Date: Thu, 26 Mar 2026 10:27:05 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org Cc: Masami Hiramatsu , Mark Rutland , Mathieu Desnoyers , Andrew Morton , Peter Zijlstra , "Vineeth Pillai (Google)" , Wolfram Sang Subject: [for-next][PATCH 09/13] i2c: Use trace_call__##name() at guarded tracepoint call sites References: <20260326142656.794462952@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: "Vineeth Pillai (Google)" Replace trace_foo() with the new trace_call__foo() at sites already guarded by trace_foo_enabled(), avoiding a redundant static_branch_unlikely() re-evaluation inside the tracepoint. trace_call__foo() calls the tracepoint callbacks directly without utilizing the static branch again. Link: https://patch.msgid.link/20260323160052.17528-13-vineeth@bitbyteword.= org Suggested-by: Steven Rostedt Suggested-by: Peter Zijlstra Signed-off-by: Vineeth Pillai (Google) Assisted-by: Claude:claude-sonnet-4-6 Acked-by: Wolfram Sang Signed-off-by: Steven Rostedt (Google) --- drivers/i2c/i2c-core-slave.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/i2c-core-slave.c b/drivers/i2c/i2c-core-slave.c index 02ca55c2246b..bebb7ba67e30 100644 --- a/drivers/i2c/i2c-core-slave.c +++ b/drivers/i2c/i2c-core-slave.c @@ -89,7 +89,7 @@ int i2c_slave_event(struct i2c_client *client, int ret =3D client->slave_cb(client, event, val); =20 if (trace_i2c_slave_enabled()) - trace_i2c_slave(client, event, val, ret); + trace_call__i2c_slave(client, event, val, ret); =20 return ret; } --=20 2.51.0 From nobody Thu Apr 2 20:28:06 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E9B8A3FE346 for ; Thu, 26 Mar 2026 14:26:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774535191; cv=none; b=aew/IIWcdYbmEhwN6Vk5HG2WfAu4InDucWAvr4eGgmHIfrywT2pl+Jj+fqk4mMshfYhNSU4OKhmAmnbVIFciGwqoXjxo+PiiawjBXCMamuQblOaPEOUWF3w7thNLE1IEeXI690xLcJMq29WlKW09I4PbqPEAQo7fFlg/imPZyvE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774535191; c=relaxed/simple; bh=ub6vsJaN2ba6oYLcAub1SvoScM/NMrZy7VIW1LN561c=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=e2b48ZuUcY4nRT6fNjRSCppzaOuUKIm7QP16B/WvHhZWnOs6zU9nM4wz8ar/MYS7Z2cqQiRGR48N5PNvb5vc+/IddmWYzNPRpUqRNV7wf8Y7ArsG4IT4kfrIuuHuYCGyMP1MpId+LjBYALQgOukVH216pPIZ76cs5lep2FdcLVs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ZGf0JDwO; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="ZGf0JDwO" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B2F88C2BCB1; Thu, 26 Mar 2026 14:26:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774535190; bh=ub6vsJaN2ba6oYLcAub1SvoScM/NMrZy7VIW1LN561c=; h=Date:From:To:Cc:Subject:References:From; b=ZGf0JDwOrsVViVD69VwPG7GFbwtrQINWgEW4EMbEnGKBS78NYHDf3XZumLqKoOML5 UJrt7q8BLx0pOE+J9SyTUaNk/QrqAQuebmHZQ8S9yO1JlsCmBeBtha7pWBWOaPnpdS 2ztT+R2Y+BvGNfS38Tssn4ondcCqZSP+ocjoiinRsV2I4zjos1kV9uS1W/0JjbkwyT gPvsyDhkFw+Rhf8SpUya/pjCAfiDtN+0mD5ONZzhm3IjHUucxQQhZfWwPCVvaZj2fC k8gicz8k7tJSmhXo0FPOOLPgTSN7SQexUSwefqIR5J7CeDVUPbEV8iIxWgrZ4k/1XX ysg4fODFr+TFQ== Received: from rostedt by gandalf with local (Exim 4.99.1) (envelope-from ) id 1w5lg5-0000000DuEQ-2o7e; Thu, 26 Mar 2026 10:27:17 -0400 Message-ID: <20260326142717.541601648@kernel.org> User-Agent: quilt/0.69 Date: Thu, 26 Mar 2026 10:27:06 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org Cc: Masami Hiramatsu , Mark Rutland , Mathieu Desnoyers , Andrew Morton , Michael Hennerich , =?UTF-8?q?Nuno=20S=C3=A1?= , David Lechner , Peter Zijlstra , "Vineeth Pillai (Google)" , Mark Brown Subject: [for-next][PATCH 10/13] spi: Use trace_call__##name() at guarded tracepoint call sites References: <20260326142656.794462952@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable From: "Vineeth Pillai (Google)" Replace trace_foo() with the new trace_call__foo() at sites already guarded by trace_foo_enabled(), avoiding a redundant static_branch_unlikely() re-evaluation inside the tracepoint. trace_call__foo() calls the tracepoint callbacks directly without utilizing the static branch again. Cc: Michael Hennerich Cc: Nuno S=C3=A1 Cc: David Lechner Link: https://patch.msgid.link/20260323160052.17528-14-vineeth@bitbyteword.= org Suggested-by: Steven Rostedt Suggested-by: Peter Zijlstra Signed-off-by: Vineeth Pillai (Google) Assisted-by: Claude:claude-sonnet-4-6 Acked-by: Mark Brown Signed-off-by: Steven Rostedt (Google) --- drivers/spi/spi-axi-spi-engine.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-axi-spi-engine.c b/drivers/spi/spi-axi-spi-eng= ine.c index 48ee5bf48173..02bbc5d0cfc5 100644 --- a/drivers/spi/spi-axi-spi-engine.c +++ b/drivers/spi/spi-axi-spi-engine.c @@ -953,7 +953,7 @@ static int spi_engine_transfer_one_message(struct spi_c= ontroller *host, struct spi_transfer *xfer; =20 list_for_each_entry(xfer, &msg->transfers, transfer_list) - trace_spi_transfer_start(msg, xfer); + trace_call__spi_transfer_start(msg, xfer); } =20 spin_lock_irqsave(&spi_engine->lock, flags); @@ -987,7 +987,7 @@ static int spi_engine_transfer_one_message(struct spi_c= ontroller *host, struct spi_transfer *xfer; =20 list_for_each_entry(xfer, &msg->transfers, transfer_list) - trace_spi_transfer_stop(msg, xfer); + trace_call__spi_transfer_stop(msg, xfer); } =20 out: --=20 2.51.0 From nobody Thu Apr 2 20:28:06 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 34F573FE374 for ; Thu, 26 Mar 2026 14:26:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774535191; cv=none; b=sCwFix4tMxLjfHHojVbQeBqtrRZEC034+ovnRWhCk8tsaX9Whe3lV2TNGQbYrC9fV22w9LZluuSD1lnwYMDKhScY0i3zzGZugOMhXSHzgpjgO/QNqQpI4mgTqpMKe/RurJTd+5xyzsgxNx52BYV/TtVCdsSJlSqXPp5jffRasoY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774535191; c=relaxed/simple; bh=51ZFW3EL396EmBawd122kWtJK4L3EBSrL6KdxmmRnao=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=Pidpw7MLjEniY7oSv6xAjgr5Hggfn2he5ZnebVvT3xiWSEIivoFfN661jFbjczwkzjlq/B48jcU0Yc+AMo/JYEOAh7XP1nnly72aAVKqprm2N834SecWaHejK0Biy7JkY+64lUvTwdMQDf1UbJkbLEin2RTIfN57g/5MdJSMaNI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=hmQPYSFB; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="hmQPYSFB" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 02640C2BCB6; Thu, 26 Mar 2026 14:26:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774535191; bh=51ZFW3EL396EmBawd122kWtJK4L3EBSrL6KdxmmRnao=; h=Date:From:To:Cc:Subject:References:From; b=hmQPYSFBzcJAMrassl9HyW9NVWaP/i9Z05/vow7eIx+FTG2KtKyOkXeIA4JcpyANm MmOaJl/HPg4FYpC/BczA+gzvgQ66MrgcoNpMQIyUZBSQji/mOHEVnh4sd1aQUs6Vvk QYnvztIePY8AofZuuIlrh4p9RFHLqhPcSsQh0reFTnTXL820/ra0f6ODm244UqTXl5 trMCqwev1MRl9hrAQotJNWGxMDktf4QImN2q9WIYkcF1bJTd43F6zgyHl69E62mhvE HhDkwMtsbwwQ0Cb3MrqhgB1LOnUUBMDu/plHhblTs+cSCIyAcUk7TDnkuS+XAHFXa0 3hRtm28SnAMCw== Received: from rostedt by gandalf with local (Exim 4.99.1) (envelope-from ) id 1w5lg5-0000000DuEv-3OJI; Thu, 26 Mar 2026 10:27:17 -0400 Message-ID: <20260326142717.686260889@kernel.org> User-Agent: quilt/0.69 Date: Thu, 26 Mar 2026 10:27:07 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org Cc: Masami Hiramatsu , Mark Rutland , Mathieu Desnoyers , Andrew Morton , Chris Mason , Peter Zijlstra , "Vineeth Pillai (Google)" , David Sterba Subject: [for-next][PATCH 11/13] btrfs: Use trace_call__##name() at guarded tracepoint call sites References: <20260326142656.794462952@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: "Vineeth Pillai (Google)" Replace trace_foo() with the new trace_call__foo() at sites already guarded by trace_foo_enabled(), avoiding a redundant static_branch_unlikely() re-evaluation inside the tracepoint. trace_call__foo() calls the tracepoint callbacks directly without utilizing the static branch again. Cc: Chris Mason Link: https://patch.msgid.link/20260323160052.17528-16-vineeth@bitbyteword.= org Suggested-by: Steven Rostedt Suggested-by: Peter Zijlstra Signed-off-by: Vineeth Pillai (Google) Assisted-by: Claude:claude-sonnet-4-6 Acked-by: David Sterba Signed-off-by: Steven Rostedt (Google) --- fs/btrfs/extent_map.c | 4 ++-- fs/btrfs/raid56.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c index 095a561d733f..9284c0a81bef 100644 --- a/fs/btrfs/extent_map.c +++ b/fs/btrfs/extent_map.c @@ -1318,7 +1318,7 @@ static void btrfs_extent_map_shrinker_worker(struct w= ork_struct *work) if (trace_btrfs_extent_map_shrinker_scan_enter_enabled()) { s64 nr =3D percpu_counter_sum_positive(&fs_info->evictable_extent_maps); =20 - trace_btrfs_extent_map_shrinker_scan_enter(fs_info, nr); + trace_call__btrfs_extent_map_shrinker_scan_enter(fs_info, nr); } =20 while (ctx.scanned < ctx.nr_to_scan && !btrfs_fs_closing(fs_info)) { @@ -1358,7 +1358,7 @@ static void btrfs_extent_map_shrinker_worker(struct w= ork_struct *work) if (trace_btrfs_extent_map_shrinker_scan_exit_enabled()) { s64 nr =3D percpu_counter_sum_positive(&fs_info->evictable_extent_maps); =20 - trace_btrfs_extent_map_shrinker_scan_exit(fs_info, nr_dropped, nr); + trace_call__btrfs_extent_map_shrinker_scan_exit(fs_info, nr_dropped, nr); } =20 atomic64_set(&fs_info->em_shrinker_nr_to_scan, 0); diff --git a/fs/btrfs/raid56.c b/fs/btrfs/raid56.c index 02105d68accb..30bd6c0fdd1f 100644 --- a/fs/btrfs/raid56.c +++ b/fs/btrfs/raid56.c @@ -1743,7 +1743,7 @@ static void submit_read_wait_bio_list(struct btrfs_ra= id_bio *rbio, struct raid56_bio_trace_info trace_info =3D { 0 }; =20 bio_get_trace_info(rbio, bio, &trace_info); - trace_raid56_read(rbio, bio, &trace_info); + trace_call__raid56_read(rbio, bio, &trace_info); } submit_bio(bio); } @@ -2428,7 +2428,7 @@ static void submit_write_bios(struct btrfs_raid_bio *= rbio, struct raid56_bio_trace_info trace_info =3D { 0 }; =20 bio_get_trace_info(rbio, bio, &trace_info); - trace_raid56_write(rbio, bio, &trace_info); + trace_call__raid56_write(rbio, bio, &trace_info); } submit_bio(bio); } --=20 2.51.0 From nobody Thu Apr 2 20:28:06 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5CCC53FE653 for ; Thu, 26 Mar 2026 14:26:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774535191; cv=none; b=mD+1izVgehd97RpttitUE8X12GvpPZfDjnRIM0837zblnIHoUPWe9/QuCWp5TH8Uizw8cHoVfLhMjmUKFpJflHKYyPLlPFTchN6QBOMSIyyeBFK05laHcvta3k2eQ0n+Xx2UVY4jFVFTaBtV0ib45dasdJ4sqJ9UAlMrhpyXDIs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774535191; c=relaxed/simple; bh=4eXygR8x57wvI/bE+wE8kElZatnu935aYK3c0nT/3mU=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=H0bwALvH+exfntJadGSFAgMqb1mMR6640RaYYBv6ZwQpTcpE3nJ6FX0xGdUqks/7KlVTzkWWND6Djs38+W/03IIzAl0f3kfJlI+wKbaKrHW7ifjd1G2td4WHqjWYxnrNg+1XT2imM3vH9wH+VbaWy0jFpKJQ9IQ2qheHEe9I0i4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=FXnVXUWS; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="FXnVXUWS" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2199FC19423; Thu, 26 Mar 2026 14:26:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774535191; bh=4eXygR8x57wvI/bE+wE8kElZatnu935aYK3c0nT/3mU=; h=Date:From:To:Cc:Subject:References:From; b=FXnVXUWSkUDoFtNRPnC/ungreGpSPZJg2mRR4DGA+Ds4wsFovRTAyabCdZ3yMED/u +ErHpzZqIm69eUmeWyWk+/tDHys3TuKTNb5pjugLcX3ryg64yIy0o1xxFi0/sV8hdX T6+BT7wDagP2NhAfI+t2EFYKfnkVEkpdB7vsPNJxNLbDDQzG15AnMNwpVrskwwYa+J i7oDuuuLYQTsasCtvBxhOxG8VhkEelf4XqiU/5NfuML4Nvatwbdif3hPRdFbMnXVNM HX6YDhIyUyDhKZuwJPm6coK4Qt5wMQ20+GNXddV1lHqzGyHmo9hzHAIikRU0nEtlyW 3pPoZlOHSko5A== Received: from rostedt by gandalf with local (Exim 4.99.1) (envelope-from ) id 1w5lg5-0000000DuFQ-3yZl; Thu, 26 Mar 2026 10:27:17 -0400 Message-ID: <20260326142717.825025945@kernel.org> User-Agent: quilt/0.69 Date: Thu, 26 Mar 2026 10:27:08 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org Cc: Masami Hiramatsu , Mark Rutland , Mathieu Desnoyers , Andrew Morton , Peter Zijlstra , "Vineeth Pillai (Google)" , SeongJae Park Subject: [for-next][PATCH 12/13] mm: damon: Use trace_call__##name() at guarded tracepoint call sites References: <20260326142656.794462952@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: "Vineeth Pillai (Google)" Replace trace_damos_stat_after_apply_interval() with trace_call__damos_stat_after_apply_interval() at a site already guarded by an early return when !trace_damos_stat_after_apply_interval_enabled(), avoiding a redundant static_branch_unlikely() re-evaluation inside the tracepoint. Cc: Andrew Morton Link: https://patch.msgid.link/20260323160052.17528-19-vineeth@bitbyteword.= org Suggested-by: Steven Rostedt Suggested-by: Peter Zijlstra Signed-off-by: Vineeth Pillai (Google) Reviewed-by: SeongJae Park Signed-off-by: Steven Rostedt (Google) --- mm/damon/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/damon/core.c b/mm/damon/core.c index c1d1091d307e..6ed6ad240ed9 100644 --- a/mm/damon/core.c +++ b/mm/damon/core.c @@ -2347,7 +2347,7 @@ static void damos_trace_stat(struct damon_ctx *c, str= uct damos *s) break; sidx++; } - trace_damos_stat_after_apply_interval(cidx, sidx, &s->stat); + trace_call__damos_stat_after_apply_interval(cidx, sidx, &s->stat); } =20 static void kdamond_apply_schemes(struct damon_ctx *c) --=20 2.51.0 From nobody Thu Apr 2 20:28:06 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9D49E3FEB07 for ; Thu, 26 Mar 2026 14:26:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774535191; cv=none; b=Mbq/VpTJq7GkPl9ZH/XLnmjfF/HzGPwIZ/J5a5wNU+dCB+V6V3L6zH1Dr2IZtnd2SX3rgBR8JDOkv3CIvHpHZuWiQgy4xkCvyfgVLognP3prOIR+0pwPtOl9XjuCbJP/tKqn43ny7CaZ3OugnZdtsu/awGGOtAMVJw7vZ801zGc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774535191; c=relaxed/simple; bh=ZA8feoSDYtDJaAXiXA9TnDZANmrigTyGgHNeIvap3bs=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=coex9E9CXyxqcZNrypV/sABtuYR7v6aWyRo+8Ph5z5MaElqiuLl4sBea3D/3Hs36RHa+F+//G6M7WRaqOyTGmF7wqPjSXThPWHNb/N8DdQfq8MZn/OJjlgKgvf94SrEA2E4T3wkXfIaA8WdijPeRIf2+e7Bbj2V/AFGvedacg8I= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Nejr1w4Y; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Nejr1w4Y" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 37D00C2BCB0; Thu, 26 Mar 2026 14:26:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774535191; bh=ZA8feoSDYtDJaAXiXA9TnDZANmrigTyGgHNeIvap3bs=; h=Date:From:To:Cc:Subject:References:From; b=Nejr1w4YsrFjreUVlKci1Ta8ps1ZZdCgXieBE5qEZFhK7T83LnIF5M1NooYcjDvWp AreeAiHnr7yklgO9KHQqlzwODyrIQM0W+e2RhPpj1Cjm65nMzhNW4LdzQJf+JNR45t lCk01P17gyAB+DvxaRqOV9vA5iy+PvhAo6E6XBhYVnenYzA9W+IZ2xOmxbej3ZT7eD cMOzHTgSfZcIlYuO3Iv8G3NwQs39TzHSwROzEraUmGiQplBvuFoNNIybjZgM+VLWK1 cUkwgsThthVqLbWFo6uyaVxaXog+jE7r2zB/wPAk63/fgwSsUkCyoq+WRpuVXcOVqz 1Lxs196uYUCHw== Received: from rostedt by gandalf with local (Exim 4.99.1) (envelope-from ) id 1w5lg6-0000000DuFv-0Mlx; Thu, 26 Mar 2026 10:27:18 -0400 Message-ID: <20260326142717.965465310@kernel.org> User-Agent: quilt/0.69 Date: Thu, 26 Mar 2026 10:27:09 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org Cc: Masami Hiramatsu , Mark Rutland , Mathieu Desnoyers , Andrew Morton Subject: [for-next][PATCH 13/13] tracing: Move snapshot code out of trace.c and into trace_snapshot.c References: <20260326142656.794462952@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Steven Rostedt The trace.c file was a dumping ground for most tracing code. Start organizing it better by moving various functions out into their own files. Move all the snapshot code, including the max trace code into its own trace_snapshot.c file. Cc: Masami Hiramatsu Cc: Mathieu Desnoyers Link: https://patch.msgid.link/20260324140145.36352d6a@gandalf.local.home Signed-off-by: Steven Rostedt (Google) --- include/linux/ftrace.h | 2 +- kernel/trace/Makefile | 1 + kernel/trace/trace.c | 1274 ++------------------------------- kernel/trace/trace.h | 105 ++- kernel/trace/trace_snapshot.c | 1067 +++++++++++++++++++++++++++ 5 files changed, 1230 insertions(+), 1219 deletions(-) create mode 100644 kernel/trace/trace_snapshot.c diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h index c242fe49af4c..28b30c6f1031 100644 --- a/include/linux/ftrace.h +++ b/include/linux/ftrace.h @@ -31,7 +31,7 @@ #define ARCH_SUPPORTS_FTRACE_OPS 0 #endif =20 -#ifdef CONFIG_TRACING +#ifdef CONFIG_TRACER_SNAPSHOT extern void ftrace_boot_snapshot(void); #else static inline void ftrace_boot_snapshot(void) { } diff --git a/kernel/trace/Makefile b/kernel/trace/Makefile index 04096c21d06b..83aeb5c77008 100644 --- a/kernel/trace/Makefile +++ b/kernel/trace/Makefile @@ -69,6 +69,7 @@ obj-$(CONFIG_TRACING) +=3D trace_seq.o obj-$(CONFIG_TRACING) +=3D trace_stat.o obj-$(CONFIG_TRACING) +=3D trace_printk.o obj-$(CONFIG_TRACING) +=3D trace_pid.o +obj-$(CONFIG_TRACER_SNAPSHOT) +=3D trace_snapshot.o obj-$(CONFIG_TRACING) +=3D pid_list.o obj-$(CONFIG_TRACING_MAP) +=3D tracing_map.o obj-$(CONFIG_PREEMPTIRQ_DELAY_TEST) +=3D preemptirq_delay_test.o diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index cf48fe23e71f..850f62032fd2 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -47,7 +47,6 @@ #include #include #include -#include #include #include #include @@ -219,15 +218,9 @@ static void ftrace_trace_userstack(struct trace_array = *tr, static char bootup_tracer_buf[MAX_TRACER_SIZE] __initdata; static char *default_bootup_tracer; =20 -static bool allocate_snapshot; -static bool snapshot_at_boot; - static char boot_instance_info[COMMAND_LINE_SIZE] __initdata; static int boot_instance_index; =20 -static char boot_snapshot_info[COMMAND_LINE_SIZE] __initdata; -static int boot_snapshot_index; - static int __init set_cmdline_ftrace(char *str) { strscpy(bootup_tracer_buf, str, MAX_TRACER_SIZE); @@ -276,38 +269,6 @@ static int __init stop_trace_on_warning(char *str) } __setup("traceoff_on_warning", stop_trace_on_warning); =20 -static int __init boot_alloc_snapshot(char *str) -{ - char *slot =3D boot_snapshot_info + boot_snapshot_index; - int left =3D sizeof(boot_snapshot_info) - boot_snapshot_index; - int ret; - - if (str[0] =3D=3D '=3D') { - str++; - if (strlen(str) >=3D left) - return -1; - - ret =3D snprintf(slot, left, "%s\t", str); - boot_snapshot_index +=3D ret; - } else { - allocate_snapshot =3D true; - /* We also need the main ring buffer expanded */ - trace_set_ring_buffer_expanded(NULL); - } - return 1; -} -__setup("alloc_snapshot", boot_alloc_snapshot); - - -static int __init boot_snapshot(char *str) -{ - snapshot_at_boot =3D true; - boot_alloc_snapshot(str); - return 1; -} -__setup("ftrace_boot_snapshot", boot_snapshot); - - static int __init boot_instance(char *str) { char *slot =3D boot_instance_info + boot_instance_index; @@ -807,47 +768,6 @@ void tracing_on(void) EXPORT_SYMBOL_GPL(tracing_on); =20 #ifdef CONFIG_TRACER_SNAPSHOT -static void tracing_snapshot_instance_cond(struct trace_array *tr, - void *cond_data) -{ - unsigned long flags; - - if (in_nmi()) { - trace_array_puts(tr, "*** SNAPSHOT CALLED FROM NMI CONTEXT ***\n"); - trace_array_puts(tr, "*** snapshot is being ignored ***\n"); - return; - } - - if (!tr->allocated_snapshot) { - trace_array_puts(tr, "*** SNAPSHOT NOT ALLOCATED ***\n"); - trace_array_puts(tr, "*** stopping trace here! ***\n"); - tracer_tracing_off(tr); - return; - } - - if (tr->mapped) { - trace_array_puts(tr, "*** BUFFER MEMORY MAPPED ***\n"); - trace_array_puts(tr, "*** Can not use snapshot (sorry) ***\n"); - return; - } - - /* Note, snapshot can not be used when the tracer uses it */ - if (tracer_uses_snapshot(tr->current_trace)) { - trace_array_puts(tr, "*** LATENCY TRACER ACTIVE ***\n"); - trace_array_puts(tr, "*** Can not use snapshot (sorry) ***\n"); - return; - } - - local_irq_save(flags); - update_max_tr(tr, current, smp_processor_id(), cond_data); - local_irq_restore(flags); -} - -void tracing_snapshot_instance(struct trace_array *tr) -{ - tracing_snapshot_instance_cond(tr, NULL); -} - /** * tracing_snapshot - take a snapshot of the current buffer. * @@ -870,138 +790,6 @@ void tracing_snapshot(void) } EXPORT_SYMBOL_GPL(tracing_snapshot); =20 -/** - * tracing_snapshot_cond - conditionally take a snapshot of the current bu= ffer. - * @tr: The tracing instance to snapshot - * @cond_data: The data to be tested conditionally, and possibly saved - * - * This is the same as tracing_snapshot() except that the snapshot is - * conditional - the snapshot will only happen if the - * cond_snapshot.update() implementation receiving the cond_data - * returns true, which means that the trace array's cond_snapshot - * update() operation used the cond_data to determine whether the - * snapshot should be taken, and if it was, presumably saved it along - * with the snapshot. - */ -void tracing_snapshot_cond(struct trace_array *tr, void *cond_data) -{ - tracing_snapshot_instance_cond(tr, cond_data); -} -EXPORT_SYMBOL_GPL(tracing_snapshot_cond); - -/** - * tracing_cond_snapshot_data - get the user data associated with a snapsh= ot - * @tr: The tracing instance - * - * When the user enables a conditional snapshot using - * tracing_snapshot_cond_enable(), the user-defined cond_data is saved - * with the snapshot. This accessor is used to retrieve it. - * - * Should not be called from cond_snapshot.update(), since it takes - * the tr->max_lock lock, which the code calling - * cond_snapshot.update() has already done. - * - * Returns the cond_data associated with the trace array's snapshot. - */ -void *tracing_cond_snapshot_data(struct trace_array *tr) -{ - void *cond_data =3D NULL; - - local_irq_disable(); - arch_spin_lock(&tr->max_lock); - - if (tr->cond_snapshot) - cond_data =3D tr->cond_snapshot->cond_data; - - arch_spin_unlock(&tr->max_lock); - local_irq_enable(); - - return cond_data; -} -EXPORT_SYMBOL_GPL(tracing_cond_snapshot_data); - -static int resize_buffer_duplicate_size(struct array_buffer *trace_buf, - struct array_buffer *size_buf, int cpu_id); -static void set_buffer_entries(struct array_buffer *buf, unsigned long val= ); - -int tracing_alloc_snapshot_instance(struct trace_array *tr) -{ - int order; - int ret; - - if (!tr->allocated_snapshot) { - - /* Make the snapshot buffer have the same order as main buffer */ - order =3D ring_buffer_subbuf_order_get(tr->array_buffer.buffer); - ret =3D ring_buffer_subbuf_order_set(tr->snapshot_buffer.buffer, order); - if (ret < 0) - return ret; - - /* allocate spare buffer */ - ret =3D resize_buffer_duplicate_size(&tr->snapshot_buffer, - &tr->array_buffer, RING_BUFFER_ALL_CPUS); - if (ret < 0) - return ret; - - tr->allocated_snapshot =3D true; - } - - return 0; -} - -static void free_snapshot(struct trace_array *tr) -{ - /* - * We don't free the ring buffer. instead, resize it because - * The max_tr ring buffer has some state (e.g. ring->clock) and - * we want preserve it. - */ - ring_buffer_subbuf_order_set(tr->snapshot_buffer.buffer, 0); - ring_buffer_resize(tr->snapshot_buffer.buffer, 1, RING_BUFFER_ALL_CPUS); - set_buffer_entries(&tr->snapshot_buffer, 1); - tracing_reset_online_cpus(&tr->snapshot_buffer); - tr->allocated_snapshot =3D false; -} - -static int tracing_arm_snapshot_locked(struct trace_array *tr) -{ - int ret; - - lockdep_assert_held(&trace_types_lock); - - spin_lock(&tr->snapshot_trigger_lock); - if (tr->snapshot =3D=3D UINT_MAX || tr->mapped) { - spin_unlock(&tr->snapshot_trigger_lock); - return -EBUSY; - } - - tr->snapshot++; - spin_unlock(&tr->snapshot_trigger_lock); - - ret =3D tracing_alloc_snapshot_instance(tr); - if (ret) { - spin_lock(&tr->snapshot_trigger_lock); - tr->snapshot--; - spin_unlock(&tr->snapshot_trigger_lock); - } - - return ret; -} - -int tracing_arm_snapshot(struct trace_array *tr) -{ - guard(mutex)(&trace_types_lock); - return tracing_arm_snapshot_locked(tr); -} - -void tracing_disarm_snapshot(struct trace_array *tr) -{ - spin_lock(&tr->snapshot_trigger_lock); - if (!WARN_ON(!tr->snapshot)) - tr->snapshot--; - spin_unlock(&tr->snapshot_trigger_lock); -} - /** * tracing_alloc_snapshot - allocate snapshot buffer. * @@ -1023,129 +811,12 @@ int tracing_alloc_snapshot(void) return ret; } EXPORT_SYMBOL_GPL(tracing_alloc_snapshot); - -/** - * tracing_snapshot_alloc - allocate and take a snapshot of the current bu= ffer. - * - * This is similar to tracing_snapshot(), but it will allocate the - * snapshot buffer if it isn't already allocated. Use this only - * where it is safe to sleep, as the allocation may sleep. - * - * This causes a swap between the snapshot buffer and the current live - * tracing buffer. You can use this to take snapshots of the live - * trace when some condition is triggered, but continue to trace. - */ -void tracing_snapshot_alloc(void) -{ - int ret; - - ret =3D tracing_alloc_snapshot(); - if (ret < 0) - return; - - tracing_snapshot(); -} -EXPORT_SYMBOL_GPL(tracing_snapshot_alloc); - -/** - * tracing_snapshot_cond_enable - enable conditional snapshot for an insta= nce - * @tr: The tracing instance - * @cond_data: User data to associate with the snapshot - * @update: Implementation of the cond_snapshot update function - * - * Check whether the conditional snapshot for the given instance has - * already been enabled, or if the current tracer is already using a - * snapshot; if so, return -EBUSY, else create a cond_snapshot and - * save the cond_data and update function inside. - * - * Returns 0 if successful, error otherwise. - */ -int tracing_snapshot_cond_enable(struct trace_array *tr, void *cond_data, - cond_update_fn_t update) -{ - struct cond_snapshot *cond_snapshot __free(kfree) =3D - kzalloc_obj(*cond_snapshot); - int ret; - - if (!cond_snapshot) - return -ENOMEM; - - cond_snapshot->cond_data =3D cond_data; - cond_snapshot->update =3D update; - - guard(mutex)(&trace_types_lock); - - if (tracer_uses_snapshot(tr->current_trace)) - return -EBUSY; - - /* - * The cond_snapshot can only change to NULL without the - * trace_types_lock. We don't care if we race with it going - * to NULL, but we want to make sure that it's not set to - * something other than NULL when we get here, which we can - * do safely with only holding the trace_types_lock and not - * having to take the max_lock. - */ - if (tr->cond_snapshot) - return -EBUSY; - - ret =3D tracing_arm_snapshot_locked(tr); - if (ret) - return ret; - - local_irq_disable(); - arch_spin_lock(&tr->max_lock); - tr->cond_snapshot =3D no_free_ptr(cond_snapshot); - arch_spin_unlock(&tr->max_lock); - local_irq_enable(); - - return 0; -} -EXPORT_SYMBOL_GPL(tracing_snapshot_cond_enable); - -/** - * tracing_snapshot_cond_disable - disable conditional snapshot for an ins= tance - * @tr: The tracing instance - * - * Check whether the conditional snapshot for the given instance is - * enabled; if so, free the cond_snapshot associated with it, - * otherwise return -EINVAL. - * - * Returns 0 if successful, error otherwise. - */ -int tracing_snapshot_cond_disable(struct trace_array *tr) -{ - int ret =3D 0; - - local_irq_disable(); - arch_spin_lock(&tr->max_lock); - - if (!tr->cond_snapshot) - ret =3D -EINVAL; - else { - kfree(tr->cond_snapshot); - tr->cond_snapshot =3D NULL; - } - - arch_spin_unlock(&tr->max_lock); - local_irq_enable(); - - tracing_disarm_snapshot(tr); - - return ret; -} -EXPORT_SYMBOL_GPL(tracing_snapshot_cond_disable); #else void tracing_snapshot(void) { WARN_ONCE(1, "Snapshot feature not enabled, but internal snapshot used"); } EXPORT_SYMBOL_GPL(tracing_snapshot); -void tracing_snapshot_cond(struct trace_array *tr, void *cond_data) -{ - WARN_ONCE(1, "Snapshot feature not enabled, but internal conditional snap= shot used"); -} -EXPORT_SYMBOL_GPL(tracing_snapshot_cond); int tracing_alloc_snapshot(void) { WARN_ONCE(1, "Snapshot feature not enabled, but snapshot allocation used"= ); @@ -1158,23 +829,6 @@ void tracing_snapshot_alloc(void) tracing_snapshot(); } EXPORT_SYMBOL_GPL(tracing_snapshot_alloc); -void *tracing_cond_snapshot_data(struct trace_array *tr) -{ - return NULL; -} -EXPORT_SYMBOL_GPL(tracing_cond_snapshot_data); -int tracing_snapshot_cond_enable(struct trace_array *tr, void *cond_data, = cond_update_fn_t update) -{ - return -ENODEV; -} -EXPORT_SYMBOL_GPL(tracing_snapshot_cond_enable); -int tracing_snapshot_cond_disable(struct trace_array *tr) -{ - return false; -} -EXPORT_SYMBOL_GPL(tracing_snapshot_cond_disable); -#define free_snapshot(tr) do { } while (0) -#define tracing_arm_snapshot_locked(tr) ({ -EBUSY; }) #endif /* CONFIG_TRACER_SNAPSHOT */ =20 void tracer_tracing_off(struct trace_array *tr) @@ -1487,206 +1141,6 @@ static ssize_t trace_seq_to_buffer(struct trace_seq= *s, void *buf, size_t cnt) =20 unsigned long __read_mostly tracing_thresh; =20 -#ifdef CONFIG_TRACER_MAX_TRACE -#ifdef LATENCY_FS_NOTIFY -static struct workqueue_struct *fsnotify_wq; - -static void latency_fsnotify_workfn(struct work_struct *work) -{ - struct trace_array *tr =3D container_of(work, struct trace_array, - fsnotify_work); - fsnotify_inode(tr->d_max_latency->d_inode, FS_MODIFY); -} - -static void latency_fsnotify_workfn_irq(struct irq_work *iwork) -{ - struct trace_array *tr =3D container_of(iwork, struct trace_array, - fsnotify_irqwork); - queue_work(fsnotify_wq, &tr->fsnotify_work); -} - -__init static int latency_fsnotify_init(void) -{ - fsnotify_wq =3D alloc_workqueue("tr_max_lat_wq", - WQ_UNBOUND | WQ_HIGHPRI, 0); - if (!fsnotify_wq) { - pr_err("Unable to allocate tr_max_lat_wq\n"); - return -ENOMEM; - } - return 0; -} - -late_initcall_sync(latency_fsnotify_init); - -void latency_fsnotify(struct trace_array *tr) -{ - if (!fsnotify_wq) - return; - /* - * We cannot call queue_work(&tr->fsnotify_work) from here because it's - * possible that we are called from __schedule() or do_idle(), which - * could cause a deadlock. - */ - irq_work_queue(&tr->fsnotify_irqwork); -} -#endif /* !LATENCY_FS_NOTIFY */ - -static const struct file_operations tracing_max_lat_fops; - -static void trace_create_maxlat_file(struct trace_array *tr, - struct dentry *d_tracer) -{ -#ifdef LATENCY_FS_NOTIFY - INIT_WORK(&tr->fsnotify_work, latency_fsnotify_workfn); - init_irq_work(&tr->fsnotify_irqwork, latency_fsnotify_workfn_irq); -#endif - tr->d_max_latency =3D trace_create_file("tracing_max_latency", - TRACE_MODE_WRITE, - d_tracer, tr, - &tracing_max_lat_fops); -} - -/* - * Copy the new maximum trace into the separate maximum-trace - * structure. (this way the maximum trace is permanently saved, - * for later retrieval via /sys/kernel/tracing/tracing_max_latency) - */ -static void -__update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu) -{ - struct array_buffer *trace_buf =3D &tr->array_buffer; - struct trace_array_cpu *data =3D per_cpu_ptr(trace_buf->data, cpu); - struct array_buffer *max_buf =3D &tr->snapshot_buffer; - struct trace_array_cpu *max_data =3D per_cpu_ptr(max_buf->data, cpu); - - max_buf->cpu =3D cpu; - max_buf->time_start =3D data->preempt_timestamp; - - max_data->saved_latency =3D tr->max_latency; - max_data->critical_start =3D data->critical_start; - max_data->critical_end =3D data->critical_end; - - strscpy(max_data->comm, tsk->comm); - max_data->pid =3D tsk->pid; - /* - * If tsk =3D=3D current, then use current_uid(), as that does not use - * RCU. The irq tracer can be called out of RCU scope. - */ - if (tsk =3D=3D current) - max_data->uid =3D current_uid(); - else - max_data->uid =3D task_uid(tsk); - - max_data->nice =3D tsk->static_prio - 20 - MAX_RT_PRIO; - max_data->policy =3D tsk->policy; - max_data->rt_priority =3D tsk->rt_priority; - - /* record this tasks comm */ - tracing_record_cmdline(tsk); - latency_fsnotify(tr); -} -#else -static inline void trace_create_maxlat_file(struct trace_array *tr, - struct dentry *d_tracer) { } -static inline void __update_max_tr(struct trace_array *tr, - struct task_struct *tsk, int cpu) { } -#endif /* CONFIG_TRACER_MAX_TRACE */ - -#ifdef CONFIG_TRACER_SNAPSHOT -/** - * update_max_tr - snapshot all trace buffers from global_trace to max_tr - * @tr: tracer - * @tsk: the task with the latency - * @cpu: The cpu that initiated the trace. - * @cond_data: User data associated with a conditional snapshot - * - * Flip the buffers between the @tr and the max_tr and record information - * about which task was the cause of this latency. - */ -void -update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu, - void *cond_data) -{ - if (tr->stop_count) - return; - - WARN_ON_ONCE(!irqs_disabled()); - - if (!tr->allocated_snapshot) { - /* Only the nop tracer should hit this when disabling */ - WARN_ON_ONCE(tr->current_trace !=3D &nop_trace); - return; - } - - arch_spin_lock(&tr->max_lock); - - /* Inherit the recordable setting from array_buffer */ - if (ring_buffer_record_is_set_on(tr->array_buffer.buffer)) - ring_buffer_record_on(tr->snapshot_buffer.buffer); - else - ring_buffer_record_off(tr->snapshot_buffer.buffer); - - if (tr->cond_snapshot && !tr->cond_snapshot->update(tr, cond_data)) { - arch_spin_unlock(&tr->max_lock); - return; - } - - swap(tr->array_buffer.buffer, tr->snapshot_buffer.buffer); - - __update_max_tr(tr, tsk, cpu); - - arch_spin_unlock(&tr->max_lock); - - /* Any waiters on the old snapshot buffer need to wake up */ - ring_buffer_wake_waiters(tr->array_buffer.buffer, RING_BUFFER_ALL_CPUS); -} - -/** - * update_max_tr_single - only copy one trace over, and reset the rest - * @tr: tracer - * @tsk: task with the latency - * @cpu: the cpu of the buffer to copy. - * - * Flip the trace of a single CPU buffer between the @tr and the max_tr. - */ -void -update_max_tr_single(struct trace_array *tr, struct task_struct *tsk, int = cpu) -{ - int ret; - - if (tr->stop_count) - return; - - WARN_ON_ONCE(!irqs_disabled()); - if (!tr->allocated_snapshot) { - /* Only the nop tracer should hit this when disabling */ - WARN_ON_ONCE(tr->current_trace !=3D &nop_trace); - return; - } - - arch_spin_lock(&tr->max_lock); - - ret =3D ring_buffer_swap_cpu(tr->snapshot_buffer.buffer, tr->array_buffer= .buffer, cpu); - - if (ret =3D=3D -EBUSY) { - /* - * We failed to swap the buffer due to a commit taking - * place on this CPU. We fail to record, but we reset - * the max trace buffer (no one writes directly to it) - * and flag that it failed. - * Another reason is resize is in progress. - */ - trace_array_printk_buf(tr->snapshot_buffer.buffer, _THIS_IP_, - "Failed to swap buffers due to commit or resize in progress\n"); - } - - WARN_ON_ONCE(ret && ret !=3D -EAGAIN && ret !=3D -EBUSY); - - __update_max_tr(tr, tsk, cpu); - arch_spin_unlock(&tr->max_lock); -} -#endif /* CONFIG_TRACER_SNAPSHOT */ - struct pipe_wait { struct trace_iterator *iter; int wait_index; @@ -1995,7 +1449,7 @@ int __init register_tracer(struct tracer *type) return 0; } =20 -static void tracing_reset_cpu(struct array_buffer *buf, int cpu) +void tracing_reset_cpu(struct array_buffer *buf, int cpu) { struct trace_buffer *buffer =3D buf->buffer; =20 @@ -3760,50 +3214,6 @@ static void test_ftrace_alive(struct seq_file *m) "# MAY BE MISSING FUNCTION EVENTS\n"); } =20 -#ifdef CONFIG_TRACER_SNAPSHOT -static void show_snapshot_main_help(struct seq_file *m) -{ - seq_puts(m, "# echo 0 > snapshot : Clears and frees snapshot buffer\n" - "# echo 1 > snapshot : Allocates snapshot buffer, if not already all= ocated.\n" - "# Takes a snapshot of the main buffer.\n" - "# echo 2 > snapshot : Clears snapshot buffer (but does not allocate= or free)\n" - "# (Doesn't have to be '2' works with any numbe= r that\n" - "# is not a '0' or '1')\n"); -} - -static void show_snapshot_percpu_help(struct seq_file *m) -{ - seq_puts(m, "# echo 0 > snapshot : Invalid for per_cpu snapshot file.\n"); -#ifdef CONFIG_RING_BUFFER_ALLOW_SWAP - seq_puts(m, "# echo 1 > snapshot : Allocates snapshot buffer, if not alre= ady allocated.\n" - "# Takes a snapshot of the main buffer for this= cpu.\n"); -#else - seq_puts(m, "# echo 1 > snapshot : Not supported with this kernel.\n" - "# Must use main snapshot file to allocate.\n"); -#endif - seq_puts(m, "# echo 2 > snapshot : Clears this cpu's snapshot buffer (but= does not allocate)\n" - "# (Doesn't have to be '2' works with any numbe= r that\n" - "# is not a '0' or '1')\n"); -} - -static void print_snapshot_help(struct seq_file *m, struct trace_iterator = *iter) -{ - if (iter->tr->allocated_snapshot) - seq_puts(m, "#\n# * Snapshot is allocated *\n#\n"); - else - seq_puts(m, "#\n# * Snapshot is freed *\n#\n"); - - seq_puts(m, "# Snapshot commands:\n"); - if (iter->cpu_file =3D=3D RING_BUFFER_ALL_CPUS) - show_snapshot_main_help(m); - else - show_snapshot_percpu_help(m); -} -#else -/* Should never be called */ -static inline void print_snapshot_help(struct seq_file *m, struct trace_it= erator *iter) { } -#endif - static int s_show(struct seq_file *m, void *v) { struct trace_iterator *iter =3D v; @@ -3852,17 +3262,6 @@ static int s_show(struct seq_file *m, void *v) return 0; } =20 -/* - * Should be used after trace_array_get(), trace_types_lock - * ensures that i_cdev was already initialized. - */ -static inline int tracing_get_cpu(struct inode *inode) -{ - if (inode->i_cdev) /* See trace_create_cpu_file() */ - return (long)inode->i_cdev - 1; - return RING_BUFFER_ALL_CPUS; -} - static const struct seq_operations tracer_seq_ops =3D { .start =3D s_start, .next =3D s_next, @@ -3889,7 +3288,7 @@ static void free_trace_iter_content(struct trace_iter= ator *iter) free_cpumask_var(iter->started); } =20 -static struct trace_iterator * +struct trace_iterator * __tracing_open(struct inode *inode, struct file *file, bool snapshot) { struct trace_array *tr =3D inode->i_private; @@ -4069,7 +3468,7 @@ int tracing_single_release_file_tr(struct inode *inod= e, struct file *filp) return single_release(inode, filp); } =20 -static int tracing_release(struct inode *inode, struct file *file) +int tracing_release(struct inode *inode, struct file *file) { struct trace_array *tr =3D inode->i_private; struct seq_file *m =3D file->private_data; @@ -5220,7 +4619,7 @@ int tracer_init(struct tracer *t, struct trace_array = *tr) return t->init(tr); } =20 -static void set_buffer_entries(struct array_buffer *buf, unsigned long val) +void trace_set_buffer_entries(struct array_buffer *buf, unsigned long val) { int cpu; =20 @@ -5231,40 +4630,12 @@ static void set_buffer_entries(struct array_buffer = *buf, unsigned long val) static void update_buffer_entries(struct array_buffer *buf, int cpu) { if (cpu =3D=3D RING_BUFFER_ALL_CPUS) { - set_buffer_entries(buf, ring_buffer_size(buf->buffer, 0)); + trace_set_buffer_entries(buf, ring_buffer_size(buf->buffer, 0)); } else { per_cpu_ptr(buf->data, cpu)->entries =3D ring_buffer_size(buf->buffer, c= pu); } } =20 -#ifdef CONFIG_TRACER_SNAPSHOT -/* resize @tr's buffer to the size of @size_tr's entries */ -static int resize_buffer_duplicate_size(struct array_buffer *trace_buf, - struct array_buffer *size_buf, int cpu_id) -{ - int cpu, ret =3D 0; - - if (cpu_id =3D=3D RING_BUFFER_ALL_CPUS) { - for_each_tracing_cpu(cpu) { - ret =3D ring_buffer_resize(trace_buf->buffer, - per_cpu_ptr(size_buf->data, cpu)->entries, cpu); - if (ret < 0) - break; - per_cpu_ptr(trace_buf->data, cpu)->entries =3D - per_cpu_ptr(size_buf->data, cpu)->entries; - } - } else { - ret =3D ring_buffer_resize(trace_buf->buffer, - per_cpu_ptr(size_buf->data, cpu_id)->entries, cpu_id); - if (ret =3D=3D 0) - per_cpu_ptr(trace_buf->data, cpu_id)->entries =3D - per_cpu_ptr(size_buf->data, cpu_id)->entries; - } - - return ret; -} -#endif /* CONFIG_TRACER_SNAPSHOT */ - static int __tracing_resize_ring_buffer(struct trace_array *tr, unsigned long size, int cpu) { @@ -5683,9 +5054,8 @@ tracing_set_trace_write(struct file *filp, const char= __user *ubuf, return ret; } =20 -static ssize_t -tracing_nsecs_read(unsigned long *ptr, char __user *ubuf, - size_t cnt, loff_t *ppos) +ssize_t tracing_nsecs_read(unsigned long *ptr, char __user *ubuf, + size_t cnt, loff_t *ppos) { char buf[64]; int r; @@ -5697,9 +5067,8 @@ tracing_nsecs_read(unsigned long *ptr, char __user *u= buf, return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); } =20 -static ssize_t -tracing_nsecs_write(unsigned long *ptr, const char __user *ubuf, - size_t cnt, loff_t *ppos) +ssize_t tracing_nsecs_write(unsigned long *ptr, const char __user *ubuf, + size_t cnt, loff_t *ppos) { unsigned long val; int ret; @@ -5741,28 +5110,6 @@ tracing_thresh_write(struct file *filp, const char _= _user *ubuf, return cnt; } =20 -#ifdef CONFIG_TRACER_MAX_TRACE - -static ssize_t -tracing_max_lat_read(struct file *filp, char __user *ubuf, - size_t cnt, loff_t *ppos) -{ - struct trace_array *tr =3D filp->private_data; - - return tracing_nsecs_read(&tr->max_latency, ubuf, cnt, ppos); -} - -static ssize_t -tracing_max_lat_write(struct file *filp, const char __user *ubuf, - size_t cnt, loff_t *ppos) -{ - struct trace_array *tr =3D filp->private_data; - - return tracing_nsecs_write(&tr->max_latency, ubuf, cnt, ppos); -} - -#endif - static int open_pipe_on_cpu(struct trace_array *tr, int cpu) { if (cpu =3D=3D RING_BUFFER_ALL_CPUS) { @@ -7067,266 +6414,78 @@ static ssize_t tracing_clock_write(struct file *fi= lp, const char __user *ubuf, const char *clockstr; int ret; =20 - if (cnt >=3D sizeof(buf)) - return -EINVAL; - - if (copy_from_user(buf, ubuf, cnt)) - return -EFAULT; - - buf[cnt] =3D 0; - - clockstr =3D strstrip(buf); - - ret =3D tracing_set_clock(tr, clockstr); - if (ret) - return ret; - - *fpos +=3D cnt; - - return cnt; -} - -static int tracing_clock_open(struct inode *inode, struct file *file) -{ - struct trace_array *tr =3D inode->i_private; - int ret; - - ret =3D tracing_check_open_get_tr(tr); - if (ret) - return ret; - - ret =3D single_open(file, tracing_clock_show, inode->i_private); - if (ret < 0) - trace_array_put(tr); - - return ret; -} - -static int tracing_time_stamp_mode_show(struct seq_file *m, void *v) -{ - struct trace_array *tr =3D m->private; - - guard(mutex)(&trace_types_lock); - - if (ring_buffer_time_stamp_abs(tr->array_buffer.buffer)) - seq_puts(m, "delta [absolute]\n"); - else - seq_puts(m, "[delta] absolute\n"); - - return 0; -} - -static int tracing_time_stamp_mode_open(struct inode *inode, struct file *= file) -{ - struct trace_array *tr =3D inode->i_private; - int ret; - - ret =3D tracing_check_open_get_tr(tr); - if (ret) - return ret; - - ret =3D single_open(file, tracing_time_stamp_mode_show, inode->i_private); - if (ret < 0) - trace_array_put(tr); - - return ret; -} - -u64 tracing_event_time_stamp(struct trace_buffer *buffer, struct ring_buff= er_event *rbe) -{ - if (rbe =3D=3D this_cpu_read(trace_buffered_event)) - return ring_buffer_time_stamp(buffer); - - return ring_buffer_event_time_stamp(buffer, rbe); -} - -struct ftrace_buffer_info { - struct trace_iterator iter; - void *spare; - unsigned int spare_cpu; - unsigned int spare_size; - unsigned int read; -}; - -#ifdef CONFIG_TRACER_SNAPSHOT -static int tracing_snapshot_open(struct inode *inode, struct file *file) -{ - struct trace_array *tr =3D inode->i_private; - struct trace_iterator *iter; - struct seq_file *m; - int ret; - - ret =3D tracing_check_open_get_tr(tr); - if (ret) - return ret; - - if (file->f_mode & FMODE_READ) { - iter =3D __tracing_open(inode, file, true); - if (IS_ERR(iter)) - ret =3D PTR_ERR(iter); - } else { - /* Writes still need the seq_file to hold the private data */ - ret =3D -ENOMEM; - m =3D kzalloc_obj(*m); - if (!m) - goto out; - iter =3D kzalloc_obj(*iter); - if (!iter) { - kfree(m); - goto out; - } - ret =3D 0; - - iter->tr =3D tr; - iter->array_buffer =3D &tr->snapshot_buffer; - iter->cpu_file =3D tracing_get_cpu(inode); - m->private =3D iter; - file->private_data =3D m; - } -out: - if (ret < 0) - trace_array_put(tr); - - return ret; -} - -static void tracing_swap_cpu_buffer(void *tr) -{ - update_max_tr_single((struct trace_array *)tr, current, smp_processor_id(= )); -} - -static ssize_t -tracing_snapshot_write(struct file *filp, const char __user *ubuf, size_t = cnt, - loff_t *ppos) -{ - struct seq_file *m =3D filp->private_data; - struct trace_iterator *iter =3D m->private; - struct trace_array *tr =3D iter->tr; - unsigned long val; - int ret; - - ret =3D tracing_update_buffers(tr); - if (ret < 0) - return ret; + if (cnt >=3D sizeof(buf)) + return -EINVAL; =20 - ret =3D kstrtoul_from_user(ubuf, cnt, 10, &val); - if (ret) - return ret; + if (copy_from_user(buf, ubuf, cnt)) + return -EFAULT; =20 - guard(mutex)(&trace_types_lock); + buf[cnt] =3D 0; =20 - if (tracer_uses_snapshot(tr->current_trace)) - return -EBUSY; + clockstr =3D strstrip(buf); =20 - local_irq_disable(); - arch_spin_lock(&tr->max_lock); - if (tr->cond_snapshot) - ret =3D -EBUSY; - arch_spin_unlock(&tr->max_lock); - local_irq_enable(); + ret =3D tracing_set_clock(tr, clockstr); if (ret) return ret; =20 - switch (val) { - case 0: - if (iter->cpu_file !=3D RING_BUFFER_ALL_CPUS) - return -EINVAL; - if (tr->allocated_snapshot) - free_snapshot(tr); - break; - case 1: -/* Only allow per-cpu swap if the ring buffer supports it */ -#ifndef CONFIG_RING_BUFFER_ALLOW_SWAP - if (iter->cpu_file !=3D RING_BUFFER_ALL_CPUS) - return -EINVAL; -#endif - if (tr->allocated_snapshot) - ret =3D resize_buffer_duplicate_size(&tr->snapshot_buffer, - &tr->array_buffer, iter->cpu_file); + *fpos +=3D cnt; =20 - ret =3D tracing_arm_snapshot_locked(tr); - if (ret) - return ret; + return cnt; +} =20 - /* Now, we're going to swap */ - if (iter->cpu_file =3D=3D RING_BUFFER_ALL_CPUS) { - local_irq_disable(); - update_max_tr(tr, current, smp_processor_id(), NULL); - local_irq_enable(); - } else { - smp_call_function_single(iter->cpu_file, tracing_swap_cpu_buffer, - (void *)tr, 1); - } - tracing_disarm_snapshot(tr); - break; - default: - if (tr->allocated_snapshot) { - if (iter->cpu_file =3D=3D RING_BUFFER_ALL_CPUS) - tracing_reset_online_cpus(&tr->snapshot_buffer); - else - tracing_reset_cpu(&tr->snapshot_buffer, iter->cpu_file); - } - break; - } +static int tracing_clock_open(struct inode *inode, struct file *file) +{ + struct trace_array *tr =3D inode->i_private; + int ret; =20 - if (ret >=3D 0) { - *ppos +=3D cnt; - ret =3D cnt; - } + ret =3D tracing_check_open_get_tr(tr); + if (ret) + return ret; + + ret =3D single_open(file, tracing_clock_show, inode->i_private); + if (ret < 0) + trace_array_put(tr); =20 return ret; } =20 -static int tracing_snapshot_release(struct inode *inode, struct file *file) +static int tracing_time_stamp_mode_show(struct seq_file *m, void *v) { - struct seq_file *m =3D file->private_data; - int ret; - - ret =3D tracing_release(inode, file); + struct trace_array *tr =3D m->private; =20 - if (file->f_mode & FMODE_READ) - return ret; + guard(mutex)(&trace_types_lock); =20 - /* If write only, the seq_file is just a stub */ - if (m) - kfree(m->private); - kfree(m); + if (ring_buffer_time_stamp_abs(tr->array_buffer.buffer)) + seq_puts(m, "delta [absolute]\n"); + else + seq_puts(m, "[delta] absolute\n"); =20 return 0; } =20 -static int tracing_buffers_open(struct inode *inode, struct file *filp); -static ssize_t tracing_buffers_read(struct file *filp, char __user *ubuf, - size_t count, loff_t *ppos); -static int tracing_buffers_release(struct inode *inode, struct file *file); -static ssize_t tracing_buffers_splice_read(struct file *file, loff_t *ppos, - struct pipe_inode_info *pipe, size_t len, unsigned int flags); - -static int snapshot_raw_open(struct inode *inode, struct file *filp) +static int tracing_time_stamp_mode_open(struct inode *inode, struct file *= file) { - struct ftrace_buffer_info *info; + struct trace_array *tr =3D inode->i_private; int ret; =20 - /* The following checks for tracefs lockdown */ - ret =3D tracing_buffers_open(inode, filp); - if (ret < 0) + ret =3D tracing_check_open_get_tr(tr); + if (ret) return ret; =20 - info =3D filp->private_data; - - if (tracer_uses_snapshot(info->iter.trace)) { - tracing_buffers_release(inode, filp); - return -EBUSY; - } - - info->iter.snapshot =3D true; - info->iter.array_buffer =3D &info->iter.tr->snapshot_buffer; + ret =3D single_open(file, tracing_time_stamp_mode_show, inode->i_private); + if (ret < 0) + trace_array_put(tr); =20 return ret; } =20 -#endif /* CONFIG_TRACER_SNAPSHOT */ +u64 tracing_event_time_stamp(struct trace_buffer *buffer, struct ring_buff= er_event *rbe) +{ + if (rbe =3D=3D this_cpu_read(trace_buffered_event)) + return ring_buffer_time_stamp(buffer); =20 + return ring_buffer_event_time_stamp(buffer, rbe); +} =20 static const struct file_operations tracing_thresh_fops =3D { .open =3D tracing_open_generic, @@ -7335,16 +6494,6 @@ static const struct file_operations tracing_thresh_f= ops =3D { .llseek =3D generic_file_llseek, }; =20 -#ifdef CONFIG_TRACER_MAX_TRACE -static const struct file_operations tracing_max_lat_fops =3D { - .open =3D tracing_open_generic_tr, - .read =3D tracing_max_lat_read, - .write =3D tracing_max_lat_write, - .llseek =3D generic_file_llseek, - .release =3D tracing_release_generic_tr, -}; -#endif - static const struct file_operations set_tracer_fops =3D { .open =3D tracing_open_generic_tr, .read =3D tracing_set_trace_read, @@ -7431,24 +6580,6 @@ static const struct file_operations last_boot_fops = =3D { .release =3D tracing_seq_release, }; =20 -#ifdef CONFIG_TRACER_SNAPSHOT -static const struct file_operations snapshot_fops =3D { - .open =3D tracing_snapshot_open, - .read =3D seq_read, - .write =3D tracing_snapshot_write, - .llseek =3D tracing_lseek, - .release =3D tracing_snapshot_release, -}; - -static const struct file_operations snapshot_raw_fops =3D { - .open =3D snapshot_raw_open, - .read =3D tracing_buffers_read, - .release =3D tracing_buffers_release, - .splice_read =3D tracing_buffers_splice_read, -}; - -#endif /* CONFIG_TRACER_SNAPSHOT */ - /* * trace_min_max_write - Write a u64 value to a trace_min_max_param struct * @filp: The active open file structure @@ -7808,7 +6939,7 @@ static const struct file_operations tracing_err_log_f= ops =3D { .release =3D tracing_err_log_release, }; =20 -static int tracing_buffers_open(struct inode *inode, struct file *filp) +int tracing_buffers_open(struct inode *inode, struct file *filp) { struct trace_array *tr =3D inode->i_private; struct ftrace_buffer_info *info; @@ -7856,9 +6987,8 @@ tracing_buffers_poll(struct file *filp, poll_table *p= oll_table) return trace_poll(iter, filp, poll_table); } =20 -static ssize_t -tracing_buffers_read(struct file *filp, char __user *ubuf, - size_t count, loff_t *ppos) +ssize_t tracing_buffers_read(struct file *filp, char __user *ubuf, + size_t count, loff_t *ppos) { struct ftrace_buffer_info *info =3D filp->private_data; struct trace_iterator *iter =3D &info->iter; @@ -7959,7 +7089,7 @@ static int tracing_buffers_flush(struct file *file, f= l_owner_t id) return 0; } =20 -static int tracing_buffers_release(struct inode *inode, struct file *file) +int tracing_buffers_release(struct inode *inode, struct file *file) { struct ftrace_buffer_info *info =3D file->private_data; struct trace_iterator *iter =3D &info->iter; @@ -8033,10 +7163,9 @@ static void buffer_spd_release(struct splice_pipe_de= sc *spd, unsigned int i) spd->partial[i].private =3D 0; } =20 -static ssize_t -tracing_buffers_splice_read(struct file *file, loff_t *ppos, - struct pipe_inode_info *pipe, size_t len, - unsigned int flags) +ssize_t tracing_buffers_splice_read(struct file *file, loff_t *ppos, + struct pipe_inode_info *pipe, size_t len, + unsigned int flags) { struct ftrace_buffer_info *info =3D file->private_data; struct trace_iterator *iter =3D &info->iter; @@ -8190,44 +7319,6 @@ static long tracing_buffers_ioctl(struct file *file,= unsigned int cmd, unsigned return 0; } =20 -#ifdef CONFIG_TRACER_SNAPSHOT -static int get_snapshot_map(struct trace_array *tr) -{ - int err =3D 0; - - /* - * Called with mmap_lock held. lockdep would be unhappy if we would now - * take trace_types_lock. Instead use the specific - * snapshot_trigger_lock. - */ - spin_lock(&tr->snapshot_trigger_lock); - - if (tr->snapshot || tr->mapped =3D=3D UINT_MAX) - err =3D -EBUSY; - else - tr->mapped++; - - spin_unlock(&tr->snapshot_trigger_lock); - - /* Wait for update_max_tr() to observe iter->tr->mapped */ - if (tr->mapped =3D=3D 1) - synchronize_rcu(); - - return err; - -} -static void put_snapshot_map(struct trace_array *tr) -{ - spin_lock(&tr->snapshot_trigger_lock); - if (!WARN_ON(!tr->mapped)) - tr->mapped--; - spin_unlock(&tr->snapshot_trigger_lock); -} -#else -static inline int get_snapshot_map(struct trace_array *tr) { return 0; } -static inline void put_snapshot_map(struct trace_array *tr) { } -#endif - /* * This is called when a VMA is duplicated (e.g., on fork()) to increment * the user_mapped counter without remapping pages. @@ -8408,170 +7499,6 @@ static const struct file_operations tracing_dyn_inf= o_fops =3D { }; #endif /* CONFIG_DYNAMIC_FTRACE */ =20 -#if defined(CONFIG_TRACER_SNAPSHOT) && defined(CONFIG_DYNAMIC_FTRACE) -static void -ftrace_snapshot(unsigned long ip, unsigned long parent_ip, - struct trace_array *tr, struct ftrace_probe_ops *ops, - void *data) -{ - tracing_snapshot_instance(tr); -} - -static void -ftrace_count_snapshot(unsigned long ip, unsigned long parent_ip, - struct trace_array *tr, struct ftrace_probe_ops *ops, - void *data) -{ - struct ftrace_func_mapper *mapper =3D data; - long *count =3D NULL; - - if (mapper) - count =3D (long *)ftrace_func_mapper_find_ip(mapper, ip); - - if (count) { - - if (*count <=3D 0) - return; - - (*count)--; - } - - tracing_snapshot_instance(tr); -} - -static int -ftrace_snapshot_print(struct seq_file *m, unsigned long ip, - struct ftrace_probe_ops *ops, void *data) -{ - struct ftrace_func_mapper *mapper =3D data; - long *count =3D NULL; - - seq_printf(m, "%ps:", (void *)ip); - - seq_puts(m, "snapshot"); - - if (mapper) - count =3D (long *)ftrace_func_mapper_find_ip(mapper, ip); - - if (count) - seq_printf(m, ":count=3D%ld\n", *count); - else - seq_puts(m, ":unlimited\n"); - - return 0; -} - -static int -ftrace_snapshot_init(struct ftrace_probe_ops *ops, struct trace_array *tr, - unsigned long ip, void *init_data, void **data) -{ - struct ftrace_func_mapper *mapper =3D *data; - - if (!mapper) { - mapper =3D allocate_ftrace_func_mapper(); - if (!mapper) - return -ENOMEM; - *data =3D mapper; - } - - return ftrace_func_mapper_add_ip(mapper, ip, init_data); -} - -static void -ftrace_snapshot_free(struct ftrace_probe_ops *ops, struct trace_array *tr, - unsigned long ip, void *data) -{ - struct ftrace_func_mapper *mapper =3D data; - - if (!ip) { - if (!mapper) - return; - free_ftrace_func_mapper(mapper, NULL); - return; - } - - ftrace_func_mapper_remove_ip(mapper, ip); -} - -static struct ftrace_probe_ops snapshot_probe_ops =3D { - .func =3D ftrace_snapshot, - .print =3D ftrace_snapshot_print, -}; - -static struct ftrace_probe_ops snapshot_count_probe_ops =3D { - .func =3D ftrace_count_snapshot, - .print =3D ftrace_snapshot_print, - .init =3D ftrace_snapshot_init, - .free =3D ftrace_snapshot_free, -}; - -static int -ftrace_trace_snapshot_callback(struct trace_array *tr, struct ftrace_hash = *hash, - char *glob, char *cmd, char *param, int enable) -{ - struct ftrace_probe_ops *ops; - void *count =3D (void *)-1; - char *number; - int ret; - - if (!tr) - return -ENODEV; - - /* hash funcs only work with set_ftrace_filter */ - if (!enable) - return -EINVAL; - - ops =3D param ? &snapshot_count_probe_ops : &snapshot_probe_ops; - - if (glob[0] =3D=3D '!') { - ret =3D unregister_ftrace_function_probe_func(glob+1, tr, ops); - if (!ret) - tracing_disarm_snapshot(tr); - - return ret; - } - - if (!param) - goto out_reg; - - number =3D strsep(¶m, ":"); - - if (!strlen(number)) - goto out_reg; - - /* - * We use the callback data field (which is a pointer) - * as our counter. - */ - ret =3D kstrtoul(number, 0, (unsigned long *)&count); - if (ret) - return ret; - - out_reg: - ret =3D tracing_arm_snapshot(tr); - if (ret < 0) - return ret; - - ret =3D register_ftrace_function_probe(glob, tr, ops, count); - if (ret < 0) - tracing_disarm_snapshot(tr); - - return ret < 0 ? ret : 0; -} - -static struct ftrace_func_command ftrace_snapshot_cmd =3D { - .name =3D "snapshot", - .func =3D ftrace_trace_snapshot_callback, -}; - -static __init int register_snapshot_cmd(void) -{ - return register_ftrace_command(&ftrace_snapshot_cmd); -} -#else -static inline __init int register_snapshot_cmd(void) { return 0; } -#endif /* defined(CONFIG_TRACER_SNAPSHOT) && defined(CONFIG_DYNAMIC_FTRACE= ) */ - static struct dentry *tracing_get_dentry(struct trace_array *tr) { /* Top directory uses NULL as the parent */ @@ -9364,8 +8291,7 @@ static void setup_trace_scratch(struct trace_array *t= r, memset(tscratch, 0, size); } =20 -static int -allocate_trace_buffer(struct trace_array *tr, struct array_buffer *buf, un= signed long size) +int allocate_trace_buffer(struct trace_array *tr, struct array_buffer *buf= , int size) { enum ring_buffer_flags rb_flags; struct trace_scratch *tscratch; @@ -9404,8 +8330,8 @@ allocate_trace_buffer(struct trace_array *tr, struct = array_buffer *buf, unsigned } =20 /* Allocate the first page for all buffers */ - set_buffer_entries(&tr->array_buffer, - ring_buffer_size(tr->array_buffer.buffer, 0)); + trace_set_buffer_entries(&tr->array_buffer, + ring_buffer_size(tr->array_buffer.buffer, 0)); =20 return 0; } @@ -9428,23 +8354,11 @@ static int allocate_trace_buffers(struct trace_arra= y *tr, unsigned long size) if (ret) return ret; =20 -#ifdef CONFIG_TRACER_SNAPSHOT - /* Fix mapped buffer trace arrays do not have snapshot buffers */ - if (tr->range_addr_start) - return 0; - - ret =3D allocate_trace_buffer(tr, &tr->snapshot_buffer, - allocate_snapshot ? size : 1); - if (MEM_FAIL(ret, "Failed to allocate trace buffer\n")) { + ret =3D trace_allocate_snapshot(tr, size); + if (MEM_FAIL(ret, "Failed to allocate trace buffer\n")) free_trace_buffer(&tr->array_buffer); - return -ENOMEM; - } - tr->allocated_snapshot =3D allocate_snapshot; - - allocate_snapshot =3D false; -#endif =20 - return 0; + return ret; } =20 static void free_trace_buffers(struct trace_array *tr) @@ -10552,47 +9466,6 @@ ssize_t trace_parse_run_command(struct file *file, = const char __user *buffer, return done; } =20 -#ifdef CONFIG_TRACER_SNAPSHOT -__init static bool tr_needs_alloc_snapshot(const char *name) -{ - char *test; - int len =3D strlen(name); - bool ret; - - if (!boot_snapshot_index) - return false; - - if (strncmp(name, boot_snapshot_info, len) =3D=3D 0 && - boot_snapshot_info[len] =3D=3D '\t') - return true; - - test =3D kmalloc(strlen(name) + 3, GFP_KERNEL); - if (!test) - return false; - - sprintf(test, "\t%s\t", name); - ret =3D strstr(boot_snapshot_info, test) =3D=3D NULL; - kfree(test); - return ret; -} - -__init static void do_allocate_snapshot(const char *name) -{ - if (!tr_needs_alloc_snapshot(name)) - return; - - /* - * When allocate_snapshot is set, the next call to - * allocate_trace_buffers() (called by trace_array_get_by_name()) - * will allocate the snapshot buffer. That will also clear - * this flag. - */ - allocate_snapshot =3D true; -} -#else -static inline void do_allocate_snapshot(const char *name) { } -#endif - __init static int backup_instance_area(const char *backup, unsigned long *addr, phys_addr_t *size) { @@ -10742,8 +9615,7 @@ __init static void enable_instances(void) } } else { /* Only non mapped buffers have snapshot buffers */ - if (IS_ENABLED(CONFIG_TRACER_SNAPSHOT)) - do_allocate_snapshot(name); + do_allocate_snapshot(name); } =20 tr =3D trace_array_create_systems(name, NULL, addr, size); @@ -10935,24 +9807,6 @@ struct trace_array *trace_get_global_array(void) } #endif =20 -void __init ftrace_boot_snapshot(void) -{ -#ifdef CONFIG_TRACER_SNAPSHOT - struct trace_array *tr; - - if (!snapshot_at_boot) - return; - - list_for_each_entry(tr, &ftrace_trace_arrays, list) { - if (!tr->allocated_snapshot) - continue; - - tracing_snapshot_instance(tr); - trace_array_puts(tr, "** Boot snapshot taken **\n"); - } -#endif -} - void __init early_trace_init(void) { if (tracepoint_printk) { diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 7db78a62f786..a3ea735a9ef6 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -264,6 +264,7 @@ static inline bool still_need_pid_events(int type, stru= ct trace_pid_list *pid_li =20 typedef bool (*cond_update_fn_t)(struct trace_array *tr, void *cond_data); =20 +#ifdef CONFIG_TRACER_SNAPSHOT /** * struct cond_snapshot - conditional snapshot data and callback * @@ -306,6 +307,7 @@ struct cond_snapshot { void *cond_data; cond_update_fn_t update; }; +#endif /* CONFIG_TRACER_SNAPSHOT */ =20 /* * struct trace_func_repeats - used to keep track of the consecutive @@ -675,6 +677,7 @@ void tracing_reset_all_online_cpus(void); void tracing_reset_all_online_cpus_unlocked(void); int tracing_open_generic(struct inode *inode, struct file *filp); int tracing_open_generic_tr(struct inode *inode, struct file *filp); +int tracing_release(struct inode *inode, struct file *file); int tracing_release_generic_tr(struct inode *inode, struct file *file); int tracing_open_file_tr(struct inode *inode, struct file *filp); int tracing_release_file_tr(struct inode *inode, struct file *filp); @@ -684,12 +687,48 @@ void tracer_tracing_on(struct trace_array *tr); void tracer_tracing_off(struct trace_array *tr); void tracer_tracing_disable(struct trace_array *tr); void tracer_tracing_enable(struct trace_array *tr); +int allocate_trace_buffer(struct trace_array *tr, struct array_buffer *buf= , int size); struct dentry *trace_create_file(const char *name, umode_t mode, struct dentry *parent, void *data, const struct file_operations *fops); =20 +struct trace_iterator *__tracing_open(struct inode *inode, struct file *fi= le, + bool snapshot); +int tracing_buffers_open(struct inode *inode, struct file *filp); +ssize_t tracing_buffers_read(struct file *filp, char __user *ubuf, + size_t count, loff_t *ppos); +int tracing_buffers_release(struct inode *inode, struct file *file); +ssize_t tracing_buffers_splice_read(struct file *file, loff_t *ppos, + struct pipe_inode_info *pipe, size_t len, unsigned int flags); + +ssize_t tracing_nsecs_read(unsigned long *ptr, char __user *ubuf, + size_t cnt, loff_t *ppos); +ssize_t tracing_nsecs_write(unsigned long *ptr, const char __user *ubuf, + size_t cnt, loff_t *ppos); + +void trace_set_buffer_entries(struct array_buffer *buf, unsigned long val); + +/* + * Should be used after trace_array_get(), trace_types_lock + * ensures that i_cdev was already initialized. + */ +static inline int tracing_get_cpu(struct inode *inode) +{ + if (inode->i_cdev) /* See trace_create_cpu_file() */ + return (long)inode->i_cdev - 1; + return RING_BUFFER_ALL_CPUS; +} +void tracing_reset_cpu(struct array_buffer *buf, int cpu); + +struct ftrace_buffer_info { + struct trace_iterator iter; + void *spare; + unsigned int spare_cpu; + unsigned int spare_size; + unsigned int read; +}; =20 /** * tracer_tracing_is_on_cpu - show real state of ring buffer enabled on fo= r a cpu @@ -828,11 +867,15 @@ static inline bool tracer_uses_snapshot(struct tracer= *tracer) { return tracer->use_max_tr; } +void trace_create_maxlat_file(struct trace_array *tr, + struct dentry *d_tracer); #else static inline bool tracer_uses_snapshot(struct tracer *tracer) { return false; } +static inline void trace_create_maxlat_file(struct trace_array *tr, + struct dentry *d_tracer) { } #endif =20 void trace_last_func_repeats(struct trace_array *tr, @@ -2140,12 +2183,6 @@ static inline bool event_command_needs_rec(struct ev= ent_command *cmd_ops) =20 extern int trace_event_enable_disable(struct trace_event_file *file, int enable, int soft_disable); -extern int tracing_alloc_snapshot(void); -extern void tracing_snapshot_cond(struct trace_array *tr, void *cond_data); -extern int tracing_snapshot_cond_enable(struct trace_array *tr, void *cond= _data, cond_update_fn_t update); - -extern int tracing_snapshot_cond_disable(struct trace_array *tr); -extern void *tracing_cond_snapshot_data(struct trace_array *tr); =20 extern const char *__start___trace_bprintk_fmt[]; extern const char *__stop___trace_bprintk_fmt[]; @@ -2233,19 +2270,71 @@ static inline void trace_event_update_all(struct tr= ace_eval_map **map, int len) #endif =20 #ifdef CONFIG_TRACER_SNAPSHOT +extern const struct file_operations snapshot_fops; +extern const struct file_operations snapshot_raw_fops; + +/* Used when creating instances */ +int trace_allocate_snapshot(struct trace_array *tr, int size); + +int tracing_alloc_snapshot(void); +void tracing_snapshot_cond(struct trace_array *tr, void *cond_data); +int tracing_snapshot_cond_enable(struct trace_array *tr, void *cond_data, = cond_update_fn_t update); +int tracing_snapshot_cond_disable(struct trace_array *tr); +void *tracing_cond_snapshot_data(struct trace_array *tr); void tracing_snapshot_instance(struct trace_array *tr); int tracing_alloc_snapshot_instance(struct trace_array *tr); +int tracing_arm_snapshot_locked(struct trace_array *tr); int tracing_arm_snapshot(struct trace_array *tr); void tracing_disarm_snapshot(struct trace_array *tr); -#else +void free_snapshot(struct trace_array *tr); +void print_snapshot_help(struct seq_file *m, struct trace_iterator *iter); +int get_snapshot_map(struct trace_array *tr); +void put_snapshot_map(struct trace_array *tr); +int resize_buffer_duplicate_size(struct array_buffer *trace_buf, + struct array_buffer *size_buf, int cpu_id); +__init void do_allocate_snapshot(const char *name); +# ifdef CONFIG_DYNAMIC_FTRACE +__init int register_snapshot_cmd(void); +# else +static inline int register_snapshot_cmd(void) { return 0; } +# endif +#else /* !CONFIG_TRACER_SNAPSHOT */ +static inline int trace_allocate_snapshot(struct trace_array *tr, int size= ) { return 0; } static inline void tracing_snapshot_instance(struct trace_array *tr) { } static inline int tracing_alloc_snapshot_instance(struct trace_array *tr) { return 0; } +static inline int tracing_arm_snapshot_locked(struct trace_array *tr) { re= turn -EBUSY; } static inline int tracing_arm_snapshot(struct trace_array *tr) { return 0;= } static inline void tracing_disarm_snapshot(struct trace_array *tr) { } -#endif +static inline void free_snapshot(struct trace_array *tr) {} +static inline void tracing_snapshot_cond(struct trace_array *tr, void *con= d_data) +{ + WARN_ONCE(1, "Snapshot feature not enabled, but internal conditional snap= shot used"); +} +static inline void *tracing_cond_snapshot_data(struct trace_array *tr) +{ + return NULL; +} +static inline int tracing_snapshot_cond_enable(struct trace_array *tr, voi= d *cond_data, cond_update_fn_t update) +{ + return -ENODEV; +} +static inline int tracing_snapshot_cond_disable(struct trace_array *tr) +{ + return false; +} +static inline void print_snapshot_help(struct seq_file *m, struct trace_it= erator *iter) +{ + /* Should never be called */ + WARN_ONCE(1, "Snapshot print function called without snapshot configured"= ); +} +static inline int get_snapshot_map(struct trace_array *tr) { return 0; } +static inline void put_snapshot_map(struct trace_array *tr) { } +static inline void do_allocate_snapshot(const char *name) { } +static inline int register_snapshot_cmd(void) { return 0; } +#endif /* CONFIG_TRACER_SNAPSHOT */ =20 #ifdef CONFIG_PREEMPT_TRACER void tracer_preempt_on(unsigned long a0, unsigned long a1); diff --git a/kernel/trace/trace_snapshot.c b/kernel/trace/trace_snapshot.c new file mode 100644 index 000000000000..8865b2ef2264 --- /dev/null +++ b/kernel/trace/trace_snapshot.c @@ -0,0 +1,1067 @@ +// SPDX-License-Identifier: GPL-2.0 +#include + +#include /* COMMAND_LINE_SIZE */ + +#include "trace.h" + +/* Used if snapshot allocated at boot */ +static bool allocate_snapshot; +static bool snapshot_at_boot; + +static char boot_snapshot_info[COMMAND_LINE_SIZE] __initdata; +static int boot_snapshot_index; + +static int __init boot_alloc_snapshot(char *str) +{ + char *slot =3D boot_snapshot_info + boot_snapshot_index; + int left =3D sizeof(boot_snapshot_info) - boot_snapshot_index; + int ret; + + if (str[0] =3D=3D '=3D') { + str++; + if (strlen(str) >=3D left) + return -1; + + ret =3D snprintf(slot, left, "%s\t", str); + boot_snapshot_index +=3D ret; + } else { + allocate_snapshot =3D true; + /* We also need the main ring buffer expanded */ + trace_set_ring_buffer_expanded(NULL); + } + return 1; +} +__setup("alloc_snapshot", boot_alloc_snapshot); + + +static int __init boot_snapshot(char *str) +{ + snapshot_at_boot =3D true; + boot_alloc_snapshot(str); + return 1; +} +__setup("ftrace_boot_snapshot", boot_snapshot); +static void tracing_snapshot_instance_cond(struct trace_array *tr, + void *cond_data) +{ + unsigned long flags; + + if (in_nmi()) { + trace_array_puts(tr, "*** SNAPSHOT CALLED FROM NMI CONTEXT ***\n"); + trace_array_puts(tr, "*** snapshot is being ignored ***\n"); + return; + } + + if (!tr->allocated_snapshot) { + trace_array_puts(tr, "*** SNAPSHOT NOT ALLOCATED ***\n"); + trace_array_puts(tr, "*** stopping trace here! ***\n"); + tracer_tracing_off(tr); + return; + } + + if (tr->mapped) { + trace_array_puts(tr, "*** BUFFER MEMORY MAPPED ***\n"); + trace_array_puts(tr, "*** Can not use snapshot (sorry) ***\n"); + return; + } + + /* Note, snapshot can not be used when the tracer uses it */ + if (tracer_uses_snapshot(tr->current_trace)) { + trace_array_puts(tr, "*** LATENCY TRACER ACTIVE ***\n"); + trace_array_puts(tr, "*** Can not use snapshot (sorry) ***\n"); + return; + } + + local_irq_save(flags); + update_max_tr(tr, current, smp_processor_id(), cond_data); + local_irq_restore(flags); +} + +void tracing_snapshot_instance(struct trace_array *tr) +{ + tracing_snapshot_instance_cond(tr, NULL); +} + +/** + * tracing_snapshot_cond - conditionally take a snapshot of the current bu= ffer. + * @tr: The tracing instance to snapshot + * @cond_data: The data to be tested conditionally, and possibly saved + * + * This is the same as tracing_snapshot() except that the snapshot is + * conditional - the snapshot will only happen if the + * cond_snapshot.update() implementation receiving the cond_data + * returns true, which means that the trace array's cond_snapshot + * update() operation used the cond_data to determine whether the + * snapshot should be taken, and if it was, presumably saved it along + * with the snapshot. + */ +void tracing_snapshot_cond(struct trace_array *tr, void *cond_data) +{ + tracing_snapshot_instance_cond(tr, cond_data); +} +EXPORT_SYMBOL_GPL(tracing_snapshot_cond); + +/** + * tracing_cond_snapshot_data - get the user data associated with a snapsh= ot + * @tr: The tracing instance + * + * When the user enables a conditional snapshot using + * tracing_snapshot_cond_enable(), the user-defined cond_data is saved + * with the snapshot. This accessor is used to retrieve it. + * + * Should not be called from cond_snapshot.update(), since it takes + * the tr->max_lock lock, which the code calling + * cond_snapshot.update() has already done. + * + * Returns the cond_data associated with the trace array's snapshot. + */ +void *tracing_cond_snapshot_data(struct trace_array *tr) +{ + void *cond_data =3D NULL; + + local_irq_disable(); + arch_spin_lock(&tr->max_lock); + + if (tr->cond_snapshot) + cond_data =3D tr->cond_snapshot->cond_data; + + arch_spin_unlock(&tr->max_lock); + local_irq_enable(); + + return cond_data; +} +EXPORT_SYMBOL_GPL(tracing_cond_snapshot_data); + +/* resize @tr's buffer to the size of @size_tr's entries */ +int resize_buffer_duplicate_size(struct array_buffer *trace_buf, + struct array_buffer *size_buf, int cpu_id) +{ + int cpu, ret =3D 0; + + if (cpu_id =3D=3D RING_BUFFER_ALL_CPUS) { + for_each_tracing_cpu(cpu) { + ret =3D ring_buffer_resize(trace_buf->buffer, + per_cpu_ptr(size_buf->data, cpu)->entries, cpu); + if (ret < 0) + break; + per_cpu_ptr(trace_buf->data, cpu)->entries =3D + per_cpu_ptr(size_buf->data, cpu)->entries; + } + } else { + ret =3D ring_buffer_resize(trace_buf->buffer, + per_cpu_ptr(size_buf->data, cpu_id)->entries, cpu_id); + if (ret =3D=3D 0) + per_cpu_ptr(trace_buf->data, cpu_id)->entries =3D + per_cpu_ptr(size_buf->data, cpu_id)->entries; + } + + return ret; +} + +int tracing_alloc_snapshot_instance(struct trace_array *tr) +{ + int order; + int ret; + + if (!tr->allocated_snapshot) { + + /* Make the snapshot buffer have the same order as main buffer */ + order =3D ring_buffer_subbuf_order_get(tr->array_buffer.buffer); + ret =3D ring_buffer_subbuf_order_set(tr->snapshot_buffer.buffer, order); + if (ret < 0) + return ret; + + /* allocate spare buffer */ + ret =3D resize_buffer_duplicate_size(&tr->snapshot_buffer, + &tr->array_buffer, RING_BUFFER_ALL_CPUS); + if (ret < 0) + return ret; + + tr->allocated_snapshot =3D true; + } + + return 0; +} + +void free_snapshot(struct trace_array *tr) +{ + /* + * We don't free the ring buffer. instead, resize it because + * The max_tr ring buffer has some state (e.g. ring->clock) and + * we want preserve it. + */ + ring_buffer_subbuf_order_set(tr->snapshot_buffer.buffer, 0); + ring_buffer_resize(tr->snapshot_buffer.buffer, 1, RING_BUFFER_ALL_CPUS); + trace_set_buffer_entries(&tr->snapshot_buffer, 1); + tracing_reset_online_cpus(&tr->snapshot_buffer); + tr->allocated_snapshot =3D false; +} + +int tracing_arm_snapshot_locked(struct trace_array *tr) +{ + int ret; + + lockdep_assert_held(&trace_types_lock); + + spin_lock(&tr->snapshot_trigger_lock); + if (tr->snapshot =3D=3D UINT_MAX || tr->mapped) { + spin_unlock(&tr->snapshot_trigger_lock); + return -EBUSY; + } + + tr->snapshot++; + spin_unlock(&tr->snapshot_trigger_lock); + + ret =3D tracing_alloc_snapshot_instance(tr); + if (ret) { + spin_lock(&tr->snapshot_trigger_lock); + tr->snapshot--; + spin_unlock(&tr->snapshot_trigger_lock); + } + + return ret; +} + +int tracing_arm_snapshot(struct trace_array *tr) +{ + guard(mutex)(&trace_types_lock); + return tracing_arm_snapshot_locked(tr); +} + +void tracing_disarm_snapshot(struct trace_array *tr) +{ + spin_lock(&tr->snapshot_trigger_lock); + if (!WARN_ON(!tr->snapshot)) + tr->snapshot--; + spin_unlock(&tr->snapshot_trigger_lock); +} + +/** + * tracing_snapshot_alloc - allocate and take a snapshot of the current bu= ffer. + * + * This is similar to tracing_snapshot(), but it will allocate the + * snapshot buffer if it isn't already allocated. Use this only + * where it is safe to sleep, as the allocation may sleep. + * + * This causes a swap between the snapshot buffer and the current live + * tracing buffer. You can use this to take snapshots of the live + * trace when some condition is triggered, but continue to trace. + */ +void tracing_snapshot_alloc(void) +{ + int ret; + + ret =3D tracing_alloc_snapshot(); + if (ret < 0) + return; + + tracing_snapshot(); +} +EXPORT_SYMBOL_GPL(tracing_snapshot_alloc); + +/** + * tracing_snapshot_cond_enable - enable conditional snapshot for an insta= nce + * @tr: The tracing instance + * @cond_data: User data to associate with the snapshot + * @update: Implementation of the cond_snapshot update function + * + * Check whether the conditional snapshot for the given instance has + * already been enabled, or if the current tracer is already using a + * snapshot; if so, return -EBUSY, else create a cond_snapshot and + * save the cond_data and update function inside. + * + * Returns 0 if successful, error otherwise. + */ +int tracing_snapshot_cond_enable(struct trace_array *tr, void *cond_data, + cond_update_fn_t update) +{ + struct cond_snapshot *cond_snapshot __free(kfree) =3D + kzalloc_obj(*cond_snapshot); + int ret; + + if (!cond_snapshot) + return -ENOMEM; + + cond_snapshot->cond_data =3D cond_data; + cond_snapshot->update =3D update; + + guard(mutex)(&trace_types_lock); + + if (tracer_uses_snapshot(tr->current_trace)) + return -EBUSY; + + /* + * The cond_snapshot can only change to NULL without the + * trace_types_lock. We don't care if we race with it going + * to NULL, but we want to make sure that it's not set to + * something other than NULL when we get here, which we can + * do safely with only holding the trace_types_lock and not + * having to take the max_lock. + */ + if (tr->cond_snapshot) + return -EBUSY; + + ret =3D tracing_arm_snapshot_locked(tr); + if (ret) + return ret; + + local_irq_disable(); + arch_spin_lock(&tr->max_lock); + tr->cond_snapshot =3D no_free_ptr(cond_snapshot); + arch_spin_unlock(&tr->max_lock); + local_irq_enable(); + + return 0; +} +EXPORT_SYMBOL_GPL(tracing_snapshot_cond_enable); + +/** + * tracing_snapshot_cond_disable - disable conditional snapshot for an ins= tance + * @tr: The tracing instance + * + * Check whether the conditional snapshot for the given instance is + * enabled; if so, free the cond_snapshot associated with it, + * otherwise return -EINVAL. + * + * Returns 0 if successful, error otherwise. + */ +int tracing_snapshot_cond_disable(struct trace_array *tr) +{ + int ret =3D 0; + + local_irq_disable(); + arch_spin_lock(&tr->max_lock); + + if (!tr->cond_snapshot) + ret =3D -EINVAL; + else { + kfree(tr->cond_snapshot); + tr->cond_snapshot =3D NULL; + } + + arch_spin_unlock(&tr->max_lock); + local_irq_enable(); + + tracing_disarm_snapshot(tr); + + return ret; +} +EXPORT_SYMBOL_GPL(tracing_snapshot_cond_disable); + +#ifdef CONFIG_TRACER_MAX_TRACE +#ifdef LATENCY_FS_NOTIFY +static struct workqueue_struct *fsnotify_wq; + +static void latency_fsnotify_workfn(struct work_struct *work) +{ + struct trace_array *tr =3D container_of(work, struct trace_array, + fsnotify_work); + fsnotify_inode(tr->d_max_latency->d_inode, FS_MODIFY); +} + +static void latency_fsnotify_workfn_irq(struct irq_work *iwork) +{ + struct trace_array *tr =3D container_of(iwork, struct trace_array, + fsnotify_irqwork); + queue_work(fsnotify_wq, &tr->fsnotify_work); +} + +__init static int latency_fsnotify_init(void) +{ + fsnotify_wq =3D alloc_workqueue("tr_max_lat_wq", + WQ_UNBOUND | WQ_HIGHPRI, 0); + if (!fsnotify_wq) { + pr_err("Unable to allocate tr_max_lat_wq\n"); + return -ENOMEM; + } + return 0; +} + +late_initcall_sync(latency_fsnotify_init); + +void latency_fsnotify(struct trace_array *tr) +{ + if (!fsnotify_wq) + return; + /* + * We cannot call queue_work(&tr->fsnotify_work) from here because it's + * possible that we are called from __schedule() or do_idle(), which + * could cause a deadlock. + */ + irq_work_queue(&tr->fsnotify_irqwork); +} +#else +static inline void latency_fsnotify(struct trace_array *tr) { } +#endif /* LATENCY_FS_NOTIFY */ +static const struct file_operations tracing_max_lat_fops; + +void trace_create_maxlat_file(struct trace_array *tr, + struct dentry *d_tracer) +{ +#ifdef LATENCY_FS_NOTIFY + INIT_WORK(&tr->fsnotify_work, latency_fsnotify_workfn); + init_irq_work(&tr->fsnotify_irqwork, latency_fsnotify_workfn_irq); +#endif + tr->d_max_latency =3D trace_create_file("tracing_max_latency", + TRACE_MODE_WRITE, + d_tracer, tr, + &tracing_max_lat_fops); +} + +/* + * Copy the new maximum trace into the separate maximum-trace + * structure. (this way the maximum trace is permanently saved, + * for later retrieval via /sys/kernel/tracing/tracing_max_latency) + */ +static void +__update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu) +{ + struct array_buffer *trace_buf =3D &tr->array_buffer; + struct trace_array_cpu *data =3D per_cpu_ptr(trace_buf->data, cpu); + struct array_buffer *max_buf =3D &tr->snapshot_buffer; + struct trace_array_cpu *max_data =3D per_cpu_ptr(max_buf->data, cpu); + + max_buf->cpu =3D cpu; + max_buf->time_start =3D data->preempt_timestamp; + + max_data->saved_latency =3D tr->max_latency; + max_data->critical_start =3D data->critical_start; + max_data->critical_end =3D data->critical_end; + + strscpy(max_data->comm, tsk->comm); + max_data->pid =3D tsk->pid; + /* + * If tsk =3D=3D current, then use current_uid(), as that does not use + * RCU. The irq tracer can be called out of RCU scope. + */ + if (tsk =3D=3D current) + max_data->uid =3D current_uid(); + else + max_data->uid =3D task_uid(tsk); + + max_data->nice =3D tsk->static_prio - 20 - MAX_RT_PRIO; + max_data->policy =3D tsk->policy; + max_data->rt_priority =3D tsk->rt_priority; + + /* record this tasks comm */ + tracing_record_cmdline(tsk); + latency_fsnotify(tr); +} +#else +static inline void __update_max_tr(struct trace_array *tr, + struct task_struct *tsk, int cpu) { } +#endif /* CONFIG_TRACER_MAX_TRACE */ + +/** + * update_max_tr - snapshot all trace buffers from global_trace to max_tr + * @tr: tracer + * @tsk: the task with the latency + * @cpu: The cpu that initiated the trace. + * @cond_data: User data associated with a conditional snapshot + * + * Flip the buffers between the @tr and the max_tr and record information + * about which task was the cause of this latency. + */ +void +update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu, + void *cond_data) +{ + if (tr->stop_count) + return; + + WARN_ON_ONCE(!irqs_disabled()); + + if (!tr->allocated_snapshot) { + /* Only the nop tracer should hit this when disabling */ + WARN_ON_ONCE(tr->current_trace !=3D &nop_trace); + return; + } + + arch_spin_lock(&tr->max_lock); + + /* Inherit the recordable setting from array_buffer */ + if (ring_buffer_record_is_set_on(tr->array_buffer.buffer)) + ring_buffer_record_on(tr->snapshot_buffer.buffer); + else + ring_buffer_record_off(tr->snapshot_buffer.buffer); + + if (tr->cond_snapshot && !tr->cond_snapshot->update(tr, cond_data)) { + arch_spin_unlock(&tr->max_lock); + return; + } + + swap(tr->array_buffer.buffer, tr->snapshot_buffer.buffer); + + __update_max_tr(tr, tsk, cpu); + + arch_spin_unlock(&tr->max_lock); + + /* Any waiters on the old snapshot buffer need to wake up */ + ring_buffer_wake_waiters(tr->array_buffer.buffer, RING_BUFFER_ALL_CPUS); +} + +/** + * update_max_tr_single - only copy one trace over, and reset the rest + * @tr: tracer + * @tsk: task with the latency + * @cpu: the cpu of the buffer to copy. + * + * Flip the trace of a single CPU buffer between the @tr and the max_tr. + */ +void +update_max_tr_single(struct trace_array *tr, struct task_struct *tsk, int = cpu) +{ + int ret; + + if (tr->stop_count) + return; + + WARN_ON_ONCE(!irqs_disabled()); + if (!tr->allocated_snapshot) { + /* Only the nop tracer should hit this when disabling */ + WARN_ON_ONCE(tr->current_trace !=3D &nop_trace); + return; + } + + arch_spin_lock(&tr->max_lock); + + ret =3D ring_buffer_swap_cpu(tr->snapshot_buffer.buffer, tr->array_buffer= .buffer, cpu); + + if (ret =3D=3D -EBUSY) { + /* + * We failed to swap the buffer due to a commit taking + * place on this CPU. We fail to record, but we reset + * the max trace buffer (no one writes directly to it) + * and flag that it failed. + * Another reason is resize is in progress. + */ + trace_array_printk_buf(tr->snapshot_buffer.buffer, _THIS_IP_, + "Failed to swap buffers due to commit or resize in progress\n"); + } + + WARN_ON_ONCE(ret && ret !=3D -EAGAIN && ret !=3D -EBUSY); + + __update_max_tr(tr, tsk, cpu); + arch_spin_unlock(&tr->max_lock); +} + +static void show_snapshot_main_help(struct seq_file *m) +{ + seq_puts(m, "# echo 0 > snapshot : Clears and frees snapshot buffer\n" + "# echo 1 > snapshot : Allocates snapshot buffer, if not already all= ocated.\n" + "# Takes a snapshot of the main buffer.\n" + "# echo 2 > snapshot : Clears snapshot buffer (but does not allocate= or free)\n" + "# (Doesn't have to be '2' works with any numbe= r that\n" + "# is not a '0' or '1')\n"); +} + +static void show_snapshot_percpu_help(struct seq_file *m) +{ + seq_puts(m, "# echo 0 > snapshot : Invalid for per_cpu snapshot file.\n"); +#ifdef CONFIG_RING_BUFFER_ALLOW_SWAP + seq_puts(m, "# echo 1 > snapshot : Allocates snapshot buffer, if not alre= ady allocated.\n" + "# Takes a snapshot of the main buffer for this= cpu.\n"); +#else + seq_puts(m, "# echo 1 > snapshot : Not supported with this kernel.\n" + "# Must use main snapshot file to allocate.\n"); +#endif + seq_puts(m, "# echo 2 > snapshot : Clears this cpu's snapshot buffer (but= does not allocate)\n" + "# (Doesn't have to be '2' works with any numbe= r that\n" + "# is not a '0' or '1')\n"); +} + +void print_snapshot_help(struct seq_file *m, struct trace_iterator *iter) +{ + if (iter->tr->allocated_snapshot) + seq_puts(m, "#\n# * Snapshot is allocated *\n#\n"); + else + seq_puts(m, "#\n# * Snapshot is freed *\n#\n"); + + seq_puts(m, "# Snapshot commands:\n"); + if (iter->cpu_file =3D=3D RING_BUFFER_ALL_CPUS) + show_snapshot_main_help(m); + else + show_snapshot_percpu_help(m); +} + +static int tracing_snapshot_open(struct inode *inode, struct file *file) +{ + struct trace_array *tr =3D inode->i_private; + struct trace_iterator *iter; + struct seq_file *m; + int ret; + + ret =3D tracing_check_open_get_tr(tr); + if (ret) + return ret; + + if (file->f_mode & FMODE_READ) { + iter =3D __tracing_open(inode, file, true); + if (IS_ERR(iter)) + ret =3D PTR_ERR(iter); + } else { + /* Writes still need the seq_file to hold the private data */ + ret =3D -ENOMEM; + m =3D kzalloc_obj(*m); + if (!m) + goto out; + iter =3D kzalloc_obj(*iter); + if (!iter) { + kfree(m); + goto out; + } + ret =3D 0; + + iter->tr =3D tr; + iter->array_buffer =3D &tr->snapshot_buffer; + iter->cpu_file =3D tracing_get_cpu(inode); + m->private =3D iter; + file->private_data =3D m; + } +out: + if (ret < 0) + trace_array_put(tr); + + return ret; +} + +static void tracing_swap_cpu_buffer(void *tr) +{ + update_max_tr_single((struct trace_array *)tr, current, smp_processor_id(= )); +} + +static ssize_t +tracing_snapshot_write(struct file *filp, const char __user *ubuf, size_t = cnt, + loff_t *ppos) +{ + struct seq_file *m =3D filp->private_data; + struct trace_iterator *iter =3D m->private; + struct trace_array *tr =3D iter->tr; + unsigned long val; + int ret; + + ret =3D tracing_update_buffers(tr); + if (ret < 0) + return ret; + + ret =3D kstrtoul_from_user(ubuf, cnt, 10, &val); + if (ret) + return ret; + + guard(mutex)(&trace_types_lock); + + if (tracer_uses_snapshot(tr->current_trace)) + return -EBUSY; + + local_irq_disable(); + arch_spin_lock(&tr->max_lock); + if (tr->cond_snapshot) + ret =3D -EBUSY; + arch_spin_unlock(&tr->max_lock); + local_irq_enable(); + if (ret) + return ret; + + switch (val) { + case 0: + if (iter->cpu_file !=3D RING_BUFFER_ALL_CPUS) + return -EINVAL; + if (tr->allocated_snapshot) + free_snapshot(tr); + break; + case 1: +/* Only allow per-cpu swap if the ring buffer supports it */ +#ifndef CONFIG_RING_BUFFER_ALLOW_SWAP + if (iter->cpu_file !=3D RING_BUFFER_ALL_CPUS) + return -EINVAL; +#endif + if (tr->allocated_snapshot) + ret =3D resize_buffer_duplicate_size(&tr->snapshot_buffer, + &tr->array_buffer, iter->cpu_file); + + ret =3D tracing_arm_snapshot_locked(tr); + if (ret) + return ret; + + /* Now, we're going to swap */ + if (iter->cpu_file =3D=3D RING_BUFFER_ALL_CPUS) { + local_irq_disable(); + update_max_tr(tr, current, smp_processor_id(), NULL); + local_irq_enable(); + } else { + smp_call_function_single(iter->cpu_file, tracing_swap_cpu_buffer, + (void *)tr, 1); + } + tracing_disarm_snapshot(tr); + break; + default: + if (tr->allocated_snapshot) { + if (iter->cpu_file =3D=3D RING_BUFFER_ALL_CPUS) + tracing_reset_online_cpus(&tr->snapshot_buffer); + else + tracing_reset_cpu(&tr->snapshot_buffer, iter->cpu_file); + } + break; + } + + if (ret >=3D 0) { + *ppos +=3D cnt; + ret =3D cnt; + } + + return ret; +} + +static int tracing_snapshot_release(struct inode *inode, struct file *file) +{ + struct seq_file *m =3D file->private_data; + int ret; + + ret =3D tracing_release(inode, file); + + if (file->f_mode & FMODE_READ) + return ret; + + /* If write only, the seq_file is just a stub */ + if (m) + kfree(m->private); + kfree(m); + + return 0; +} + +static int snapshot_raw_open(struct inode *inode, struct file *filp) +{ + struct ftrace_buffer_info *info; + int ret; + + /* The following checks for tracefs lockdown */ + ret =3D tracing_buffers_open(inode, filp); + if (ret < 0) + return ret; + + info =3D filp->private_data; + + if (tracer_uses_snapshot(info->iter.trace)) { + tracing_buffers_release(inode, filp); + return -EBUSY; + } + + info->iter.snapshot =3D true; + info->iter.array_buffer =3D &info->iter.tr->snapshot_buffer; + + return ret; +} + +const struct file_operations snapshot_fops =3D { + .open =3D tracing_snapshot_open, + .read =3D seq_read, + .write =3D tracing_snapshot_write, + .llseek =3D tracing_lseek, + .release =3D tracing_snapshot_release, +}; + +const struct file_operations snapshot_raw_fops =3D { + .open =3D snapshot_raw_open, + .read =3D tracing_buffers_read, + .release =3D tracing_buffers_release, + .splice_read =3D tracing_buffers_splice_read, +}; + +#ifdef CONFIG_TRACER_MAX_TRACE +static ssize_t +tracing_max_lat_read(struct file *filp, char __user *ubuf, + size_t cnt, loff_t *ppos) +{ + struct trace_array *tr =3D filp->private_data; + + return tracing_nsecs_read(&tr->max_latency, ubuf, cnt, ppos); +} + +static ssize_t +tracing_max_lat_write(struct file *filp, const char __user *ubuf, + size_t cnt, loff_t *ppos) +{ + struct trace_array *tr =3D filp->private_data; + + return tracing_nsecs_write(&tr->max_latency, ubuf, cnt, ppos); +} + +static const struct file_operations tracing_max_lat_fops =3D { + .open =3D tracing_open_generic_tr, + .read =3D tracing_max_lat_read, + .write =3D tracing_max_lat_write, + .llseek =3D generic_file_llseek, + .release =3D tracing_release_generic_tr, +}; +#endif /* CONFIG_TRACER_MAX_TRACE */ + +int get_snapshot_map(struct trace_array *tr) +{ + int err =3D 0; + + /* + * Called with mmap_lock held. lockdep would be unhappy if we would now + * take trace_types_lock. Instead use the specific + * snapshot_trigger_lock. + */ + spin_lock(&tr->snapshot_trigger_lock); + + if (tr->snapshot || tr->mapped =3D=3D UINT_MAX) + err =3D -EBUSY; + else + tr->mapped++; + + spin_unlock(&tr->snapshot_trigger_lock); + + /* Wait for update_max_tr() to observe iter->tr->mapped */ + if (tr->mapped =3D=3D 1) + synchronize_rcu(); + + return err; + +} + +void put_snapshot_map(struct trace_array *tr) +{ + spin_lock(&tr->snapshot_trigger_lock); + if (!WARN_ON(!tr->mapped)) + tr->mapped--; + spin_unlock(&tr->snapshot_trigger_lock); +} + +#ifdef CONFIG_DYNAMIC_FTRACE +static void +ftrace_snapshot(unsigned long ip, unsigned long parent_ip, + struct trace_array *tr, struct ftrace_probe_ops *ops, + void *data) +{ + tracing_snapshot_instance(tr); +} + +static void +ftrace_count_snapshot(unsigned long ip, unsigned long parent_ip, + struct trace_array *tr, struct ftrace_probe_ops *ops, + void *data) +{ + struct ftrace_func_mapper *mapper =3D data; + long *count =3D NULL; + + if (mapper) + count =3D (long *)ftrace_func_mapper_find_ip(mapper, ip); + + if (count) { + + if (*count <=3D 0) + return; + + (*count)--; + } + + tracing_snapshot_instance(tr); +} + +static int +ftrace_snapshot_print(struct seq_file *m, unsigned long ip, + struct ftrace_probe_ops *ops, void *data) +{ + struct ftrace_func_mapper *mapper =3D data; + long *count =3D NULL; + + seq_printf(m, "%ps:", (void *)ip); + + seq_puts(m, "snapshot"); + + if (mapper) + count =3D (long *)ftrace_func_mapper_find_ip(mapper, ip); + + if (count) + seq_printf(m, ":count=3D%ld\n", *count); + else + seq_puts(m, ":unlimited\n"); + + return 0; +} + +static int +ftrace_snapshot_init(struct ftrace_probe_ops *ops, struct trace_array *tr, + unsigned long ip, void *init_data, void **data) +{ + struct ftrace_func_mapper *mapper =3D *data; + + if (!mapper) { + mapper =3D allocate_ftrace_func_mapper(); + if (!mapper) + return -ENOMEM; + *data =3D mapper; + } + + return ftrace_func_mapper_add_ip(mapper, ip, init_data); +} + +static void +ftrace_snapshot_free(struct ftrace_probe_ops *ops, struct trace_array *tr, + unsigned long ip, void *data) +{ + struct ftrace_func_mapper *mapper =3D data; + + if (!ip) { + if (!mapper) + return; + free_ftrace_func_mapper(mapper, NULL); + return; + } + + ftrace_func_mapper_remove_ip(mapper, ip); +} + +static struct ftrace_probe_ops snapshot_probe_ops =3D { + .func =3D ftrace_snapshot, + .print =3D ftrace_snapshot_print, +}; + +static struct ftrace_probe_ops snapshot_count_probe_ops =3D { + .func =3D ftrace_count_snapshot, + .print =3D ftrace_snapshot_print, + .init =3D ftrace_snapshot_init, + .free =3D ftrace_snapshot_free, +}; + +static int +ftrace_trace_snapshot_callback(struct trace_array *tr, struct ftrace_hash = *hash, + char *glob, char *cmd, char *param, int enable) +{ + struct ftrace_probe_ops *ops; + void *count =3D (void *)-1; + char *number; + int ret; + + if (!tr) + return -ENODEV; + + /* hash funcs only work with set_ftrace_filter */ + if (!enable) + return -EINVAL; + + ops =3D param ? &snapshot_count_probe_ops : &snapshot_probe_ops; + + if (glob[0] =3D=3D '!') { + ret =3D unregister_ftrace_function_probe_func(glob+1, tr, ops); + if (!ret) + tracing_disarm_snapshot(tr); + + return ret; + } + + if (!param) + goto out_reg; + + number =3D strsep(¶m, ":"); + + if (!strlen(number)) + goto out_reg; + + /* + * We use the callback data field (which is a pointer) + * as our counter. + */ + ret =3D kstrtoul(number, 0, (unsigned long *)&count); + if (ret) + return ret; + + out_reg: + ret =3D tracing_arm_snapshot(tr); + if (ret < 0) + return ret; + + ret =3D register_ftrace_function_probe(glob, tr, ops, count); + if (ret < 0) + tracing_disarm_snapshot(tr); + + return ret < 0 ? ret : 0; +} + +static struct ftrace_func_command ftrace_snapshot_cmd =3D { + .name =3D "snapshot", + .func =3D ftrace_trace_snapshot_callback, +}; + +__init int register_snapshot_cmd(void) +{ + return register_ftrace_command(&ftrace_snapshot_cmd); +} +#endif /* CONFIG_DYNAMIC_FTRACE */ + +int trace_allocate_snapshot(struct trace_array *tr, int size) +{ + int ret; + + /* Fix mapped buffer trace arrays do not have snapshot buffers */ + if (tr->range_addr_start) + return 0; + + /* allocate_snapshot can only be true during system boot */ + ret =3D allocate_trace_buffer(tr, &tr->snapshot_buffer, + allocate_snapshot ? size : 1); + if (ret < 0) + return -ENOMEM; + + tr->allocated_snapshot =3D allocate_snapshot; + + allocate_snapshot =3D false; + return 0; +} + +__init static bool tr_needs_alloc_snapshot(const char *name) +{ + char *test; + int len =3D strlen(name); + bool ret; + + if (!boot_snapshot_index) + return false; + + if (strncmp(name, boot_snapshot_info, len) =3D=3D 0 && + boot_snapshot_info[len] =3D=3D '\t') + return true; + + test =3D kmalloc(strlen(name) + 3, GFP_KERNEL); + if (!test) + return false; + + sprintf(test, "\t%s\t", name); + ret =3D strstr(boot_snapshot_info, test) =3D=3D NULL; + kfree(test); + return ret; +} + +__init void do_allocate_snapshot(const char *name) +{ + if (!tr_needs_alloc_snapshot(name)) + return; + + /* + * When allocate_snapshot is set, the next call to + * allocate_trace_buffers() (called by trace_array_get_by_name()) + * will allocate the snapshot buffer. That will also clear + * this flag. + */ + allocate_snapshot =3D true; +} + +void __init ftrace_boot_snapshot(void) +{ + struct trace_array *tr; + + if (!snapshot_at_boot) + return; + + list_for_each_entry(tr, &ftrace_trace_arrays, list) { + if (!tr->allocated_snapshot) + continue; + + tracing_snapshot_instance(tr); + trace_array_puts(tr, "** Boot snapshot taken **\n"); + } +} --=20 2.51.0