Linux Trace Kernel
 help / color / mirror / Atom feed
* [PATCH v2 15/21] PCI: epf-test: Switch to use %ptSp
From: Andy Shevchenko @ 2025-11-11 12:20 UTC (permalink / raw)
  To: Corey Minyard, Christian König, Dr. David Alan Gilbert,
	Alex Deucher, Thomas Zimmermann, Dmitry Baryshkov, Rob Clark,
	Matthew Brost, Ulf Hansson, Andy Shevchenko, Vitaly Lifshits,
	Manivannan Sadhasivam, Niklas Cassel, Calvin Owens,
	Vadim Fedorenko, Sagi Maimon, Martin K. Petersen,
	Karan Tilak Kumar, Hans Verkuil, Casey Schaufler, Steven Rostedt,
	Petr Mladek, Viacheslav Dubeyko, Max Kellermann, linux-doc,
	linux-kernel, openipmi-developer, linux-media, dri-devel,
	linaro-mm-sig, amd-gfx, linux-arm-msm, freedreno, intel-xe,
	linux-mmc, netdev, intel-wired-lan, linux-pci, linux-s390,
	linux-scsi, linux-staging, ceph-devel, linux-trace-kernel
  Cc: Rasmus Villemoes, Sergey Senozhatsky, Jonathan Corbet,
	Sumit Semwal, Gustavo Padovan, David Airlie, Simona Vetter,
	Maarten Lankhorst, Maxime Ripard, Dmitry Baryshkov, Abhinav Kumar,
	Jessica Zhang, Sean Paul, Marijn Suijten, Konrad Dybcio,
	Lucas De Marchi, Thomas Hellström, Rodrigo Vivi,
	Vladimir Oltean, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Tony Nguyen, Przemek Kitszel,
	Krzysztof Wilczyński, Kishon Vijay Abraham I, Bjorn Helgaas,
	Rodolfo Giometti, Richard Cochran, Jonathan Lemon,
	Stefan Haberland, Jan Hoeppner, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Satish Kharat, Sesidhar Baddela, James E.J. Bottomley,
	Mauro Carvalho Chehab, Greg Kroah-Hartman, Xiubo Li, Ilya Dryomov,
	Masami Hiramatsu, Mathieu Desnoyers, Andrew Morton
In-Reply-To: <20251111122735.880607-1-andriy.shevchenko@linux.intel.com>

Use %ptSp instead of open coded variants to print content of
struct timespec64 in human readable format.

Acked-by: Bjorn Helgaas <bhelgaas@google.com>
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
 drivers/pci/endpoint/functions/pci-epf-test.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c
index b05e8db575c3..debd235253c5 100644
--- a/drivers/pci/endpoint/functions/pci-epf-test.c
+++ b/drivers/pci/endpoint/functions/pci-epf-test.c
@@ -331,9 +331,8 @@ static void pci_epf_test_print_rate(struct pci_epf_test *epf_test,
 		rate = div64_u64(size * NSEC_PER_SEC, ns * 1000);
 
 	dev_info(&epf_test->epf->dev,
-		 "%s => Size: %llu B, DMA: %s, Time: %llu.%09u s, Rate: %llu KB/s\n",
-		 op, size, dma ? "YES" : "NO",
-		 (u64)ts.tv_sec, (u32)ts.tv_nsec, rate);
+		 "%s => Size: %llu B, DMA: %s, Time: %ptSp s, Rate: %llu KB/s\n",
+		 op, size, dma ? "YES" : "NO", &ts, rate);
 }
 
 static void pci_epf_test_copy(struct pci_epf_test *epf_test,
-- 
2.50.1


^ permalink raw reply related

* [PATCH v2 16/21] pps: Switch to use %ptSp
From: Andy Shevchenko @ 2025-11-11 12:20 UTC (permalink / raw)
  To: Corey Minyard, Christian König, Dr. David Alan Gilbert,
	Alex Deucher, Thomas Zimmermann, Dmitry Baryshkov, Rob Clark,
	Matthew Brost, Ulf Hansson, Andy Shevchenko, Vitaly Lifshits,
	Manivannan Sadhasivam, Niklas Cassel, Calvin Owens,
	Vadim Fedorenko, Sagi Maimon, Martin K. Petersen,
	Karan Tilak Kumar, Hans Verkuil, Casey Schaufler, Steven Rostedt,
	Petr Mladek, Viacheslav Dubeyko, Max Kellermann, linux-doc,
	linux-kernel, openipmi-developer, linux-media, dri-devel,
	linaro-mm-sig, amd-gfx, linux-arm-msm, freedreno, intel-xe,
	linux-mmc, netdev, intel-wired-lan, linux-pci, linux-s390,
	linux-scsi, linux-staging, ceph-devel, linux-trace-kernel
  Cc: Rasmus Villemoes, Sergey Senozhatsky, Jonathan Corbet,
	Sumit Semwal, Gustavo Padovan, David Airlie, Simona Vetter,
	Maarten Lankhorst, Maxime Ripard, Dmitry Baryshkov, Abhinav Kumar,
	Jessica Zhang, Sean Paul, Marijn Suijten, Konrad Dybcio,
	Lucas De Marchi, Thomas Hellström, Rodrigo Vivi,
	Vladimir Oltean, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Tony Nguyen, Przemek Kitszel,
	Krzysztof Wilczyński, Kishon Vijay Abraham I, Bjorn Helgaas,
	Rodolfo Giometti, Richard Cochran, Jonathan Lemon,
	Stefan Haberland, Jan Hoeppner, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Satish Kharat, Sesidhar Baddela, James E.J. Bottomley,
	Mauro Carvalho Chehab, Greg Kroah-Hartman, Xiubo Li, Ilya Dryomov,
	Masami Hiramatsu, Mathieu Desnoyers, Andrew Morton
In-Reply-To: <20251111122735.880607-1-andriy.shevchenko@linux.intel.com>

Use %ptSp instead of open coded variants to print content of
struct timespec64 in human readable format.

Acked-by: Rodolfo Giometti <giometti@enneenne.com>
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
 drivers/pps/generators/pps_gen_parport.c | 3 +--
 drivers/pps/kapi.c                       | 3 +--
 2 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/pps/generators/pps_gen_parport.c b/drivers/pps/generators/pps_gen_parport.c
index f5eeb4dd01ad..05bbf8d30ef1 100644
--- a/drivers/pps/generators/pps_gen_parport.c
+++ b/drivers/pps/generators/pps_gen_parport.c
@@ -80,8 +80,7 @@ static enum hrtimer_restart hrtimer_event(struct hrtimer *timer)
 	/* check if we are late */
 	if (expire_time.tv_sec != ts1.tv_sec || ts1.tv_nsec > lim) {
 		local_irq_restore(flags);
-		pr_err("we are late this time %lld.%09ld\n",
-				(s64)ts1.tv_sec, ts1.tv_nsec);
+		pr_err("we are late this time %ptSp\n", &ts1);
 		goto done;
 	}
 
diff --git a/drivers/pps/kapi.c b/drivers/pps/kapi.c
index e9389876229e..6985c34de2ce 100644
--- a/drivers/pps/kapi.c
+++ b/drivers/pps/kapi.c
@@ -163,8 +163,7 @@ void pps_event(struct pps_device *pps, struct pps_event_time *ts, int event,
 	/* check event type */
 	BUG_ON((event & (PPS_CAPTUREASSERT | PPS_CAPTURECLEAR)) == 0);
 
-	dev_dbg(&pps->dev, "PPS event at %lld.%09ld\n",
-			(s64)ts->ts_real.tv_sec, ts->ts_real.tv_nsec);
+	dev_dbg(&pps->dev, "PPS event at %ptSp\n", &ts->ts_real);
 
 	timespec_to_pps_ktime(&ts_real, ts->ts_real);
 
-- 
2.50.1


^ permalink raw reply related

* [PATCH v2 17/21] ptp: ocp: Switch to use %ptSp
From: Andy Shevchenko @ 2025-11-11 12:20 UTC (permalink / raw)
  To: Corey Minyard, Christian König, Dr. David Alan Gilbert,
	Alex Deucher, Thomas Zimmermann, Dmitry Baryshkov, Rob Clark,
	Matthew Brost, Ulf Hansson, Andy Shevchenko, Vitaly Lifshits,
	Manivannan Sadhasivam, Niklas Cassel, Calvin Owens,
	Vadim Fedorenko, Sagi Maimon, Martin K. Petersen,
	Karan Tilak Kumar, Hans Verkuil, Casey Schaufler, Steven Rostedt,
	Petr Mladek, Viacheslav Dubeyko, Max Kellermann, linux-doc,
	linux-kernel, openipmi-developer, linux-media, dri-devel,
	linaro-mm-sig, amd-gfx, linux-arm-msm, freedreno, intel-xe,
	linux-mmc, netdev, intel-wired-lan, linux-pci, linux-s390,
	linux-scsi, linux-staging, ceph-devel, linux-trace-kernel
  Cc: Rasmus Villemoes, Sergey Senozhatsky, Jonathan Corbet,
	Sumit Semwal, Gustavo Padovan, David Airlie, Simona Vetter,
	Maarten Lankhorst, Maxime Ripard, Dmitry Baryshkov, Abhinav Kumar,
	Jessica Zhang, Sean Paul, Marijn Suijten, Konrad Dybcio,
	Lucas De Marchi, Thomas Hellström, Rodrigo Vivi,
	Vladimir Oltean, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Tony Nguyen, Przemek Kitszel,
	Krzysztof Wilczyński, Kishon Vijay Abraham I, Bjorn Helgaas,
	Rodolfo Giometti, Richard Cochran, Jonathan Lemon,
	Stefan Haberland, Jan Hoeppner, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Satish Kharat, Sesidhar Baddela, James E.J. Bottomley,
	Mauro Carvalho Chehab, Greg Kroah-Hartman, Xiubo Li, Ilya Dryomov,
	Masami Hiramatsu, Mathieu Desnoyers, Andrew Morton
In-Reply-To: <20251111122735.880607-1-andriy.shevchenko@linux.intel.com>

Use %ptSp instead of open coded variants to print content of
struct timespec64 in human readable format.

While at it, fix wrong use of %ptT against struct timespec64.
It's kinda lucky that it worked just because the first member
there 64-bit and it's of time64_t type. Now with %ptS it may
be used correctly.

Acked-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
 drivers/ptp/ptp_ocp.c | 13 +++++--------
 1 file changed, 5 insertions(+), 8 deletions(-)

diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c
index eeebe4d149f7..21a8109fae34 100644
--- a/drivers/ptp/ptp_ocp.c
+++ b/drivers/ptp/ptp_ocp.c
@@ -4293,11 +4293,9 @@ ptp_ocp_summary_show(struct seq_file *s, void *data)
 		ns += (s64)bp->utc_tai_offset * NSEC_PER_SEC;
 		sys_ts = ns_to_timespec64(ns);
 
-		seq_printf(s, "%7s: %lld.%ld == %ptT TAI\n", "PHC",
-			   ts.tv_sec, ts.tv_nsec, &ts);
-		seq_printf(s, "%7s: %lld.%ld == %ptT UTC offset %d\n", "SYS",
-			   sys_ts.tv_sec, sys_ts.tv_nsec, &sys_ts,
-			   bp->utc_tai_offset);
+		seq_printf(s, "%7s: %ptSp == %ptS TAI\n", "PHC", &ts, &ts);
+		seq_printf(s, "%7s: %ptSp == %ptS UTC offset %d\n", "SYS",
+			   &sys_ts, &sys_ts, bp->utc_tai_offset);
 		seq_printf(s, "%7s: PHC:SYS offset: %lld  window: %lld\n", "",
 			   timespec64_to_ns(&ts) - ns,
 			   post_ns - pre_ns);
@@ -4505,9 +4503,8 @@ ptp_ocp_phc_info(struct ptp_ocp *bp)
 		 ptp_clock_index(bp->ptp));
 
 	if (!ptp_ocp_gettimex(&bp->ptp_info, &ts, NULL))
-		dev_info(&bp->pdev->dev, "Time: %lld.%ld, %s\n",
-			 ts.tv_sec, ts.tv_nsec,
-			 bp->sync ? "in-sync" : "UNSYNCED");
+		dev_info(&bp->pdev->dev, "Time: %ptSp, %s\n",
+			 &ts, bp->sync ? "in-sync" : "UNSYNCED");
 }
 
 static void
-- 
2.50.1


^ permalink raw reply related

* [PATCH v2 18/21] s390/dasd: Switch to use %ptSp
From: Andy Shevchenko @ 2025-11-11 12:20 UTC (permalink / raw)
  To: Corey Minyard, Christian König, Dr. David Alan Gilbert,
	Alex Deucher, Thomas Zimmermann, Dmitry Baryshkov, Rob Clark,
	Matthew Brost, Ulf Hansson, Andy Shevchenko, Vitaly Lifshits,
	Manivannan Sadhasivam, Niklas Cassel, Calvin Owens,
	Vadim Fedorenko, Sagi Maimon, Martin K. Petersen,
	Karan Tilak Kumar, Hans Verkuil, Casey Schaufler, Steven Rostedt,
	Petr Mladek, Viacheslav Dubeyko, Max Kellermann, linux-doc,
	linux-kernel, openipmi-developer, linux-media, dri-devel,
	linaro-mm-sig, amd-gfx, linux-arm-msm, freedreno, intel-xe,
	linux-mmc, netdev, intel-wired-lan, linux-pci, linux-s390,
	linux-scsi, linux-staging, ceph-devel, linux-trace-kernel
  Cc: Rasmus Villemoes, Sergey Senozhatsky, Jonathan Corbet,
	Sumit Semwal, Gustavo Padovan, David Airlie, Simona Vetter,
	Maarten Lankhorst, Maxime Ripard, Dmitry Baryshkov, Abhinav Kumar,
	Jessica Zhang, Sean Paul, Marijn Suijten, Konrad Dybcio,
	Lucas De Marchi, Thomas Hellström, Rodrigo Vivi,
	Vladimir Oltean, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Tony Nguyen, Przemek Kitszel,
	Krzysztof Wilczyński, Kishon Vijay Abraham I, Bjorn Helgaas,
	Rodolfo Giometti, Richard Cochran, Jonathan Lemon,
	Stefan Haberland, Jan Hoeppner, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Satish Kharat, Sesidhar Baddela, James E.J. Bottomley,
	Mauro Carvalho Chehab, Greg Kroah-Hartman, Xiubo Li, Ilya Dryomov,
	Masami Hiramatsu, Mathieu Desnoyers, Andrew Morton
In-Reply-To: <20251111122735.880607-1-andriy.shevchenko@linux.intel.com>

Use %ptSp instead of open coded variants to print content of
struct timespec64 in human readable format.

Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
 drivers/s390/block/dasd.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 7765e40f7cea..97dcc70f669e 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -974,8 +974,7 @@ static void dasd_stats_array(struct seq_file *m, unsigned int *array)
 static void dasd_stats_seq_print(struct seq_file *m,
 				 struct dasd_profile_info *data)
 {
-	seq_printf(m, "start_time %lld.%09ld\n",
-		   (s64)data->starttod.tv_sec, data->starttod.tv_nsec);
+	seq_printf(m, "start_time %ptSp\n", &data->starttod);
 	seq_printf(m, "total_requests %u\n", data->dasd_io_reqs);
 	seq_printf(m, "total_sectors %u\n", data->dasd_io_sects);
 	seq_printf(m, "total_pav %u\n", data->dasd_io_alias);
-- 
2.50.1


^ permalink raw reply related

* [PATCH v2 20/21] scsi: snic: Switch to use %ptSp
From: Andy Shevchenko @ 2025-11-11 12:20 UTC (permalink / raw)
  To: Corey Minyard, Christian König, Dr. David Alan Gilbert,
	Alex Deucher, Thomas Zimmermann, Dmitry Baryshkov, Rob Clark,
	Matthew Brost, Ulf Hansson, Andy Shevchenko, Vitaly Lifshits,
	Manivannan Sadhasivam, Niklas Cassel, Calvin Owens,
	Vadim Fedorenko, Sagi Maimon, Martin K. Petersen,
	Karan Tilak Kumar, Hans Verkuil, Casey Schaufler, Steven Rostedt,
	Petr Mladek, Viacheslav Dubeyko, Max Kellermann, linux-doc,
	linux-kernel, openipmi-developer, linux-media, dri-devel,
	linaro-mm-sig, amd-gfx, linux-arm-msm, freedreno, intel-xe,
	linux-mmc, netdev, intel-wired-lan, linux-pci, linux-s390,
	linux-scsi, linux-staging, ceph-devel, linux-trace-kernel
  Cc: Rasmus Villemoes, Sergey Senozhatsky, Jonathan Corbet,
	Sumit Semwal, Gustavo Padovan, David Airlie, Simona Vetter,
	Maarten Lankhorst, Maxime Ripard, Dmitry Baryshkov, Abhinav Kumar,
	Jessica Zhang, Sean Paul, Marijn Suijten, Konrad Dybcio,
	Lucas De Marchi, Thomas Hellström, Rodrigo Vivi,
	Vladimir Oltean, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Tony Nguyen, Przemek Kitszel,
	Krzysztof Wilczyński, Kishon Vijay Abraham I, Bjorn Helgaas,
	Rodolfo Giometti, Richard Cochran, Jonathan Lemon,
	Stefan Haberland, Jan Hoeppner, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Satish Kharat, Sesidhar Baddela, James E.J. Bottomley,
	Mauro Carvalho Chehab, Greg Kroah-Hartman, Xiubo Li, Ilya Dryomov,
	Masami Hiramatsu, Mathieu Desnoyers, Andrew Morton
In-Reply-To: <20251111122735.880607-1-andriy.shevchenko@linux.intel.com>

Use %ptSp instead of open coded variants to print content of
struct timespec64 in human readable format.

Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
 drivers/scsi/snic/snic_debugfs.c | 10 ++++------
 drivers/scsi/snic/snic_trc.c     |  5 ++---
 2 files changed, 6 insertions(+), 9 deletions(-)

diff --git a/drivers/scsi/snic/snic_debugfs.c b/drivers/scsi/snic/snic_debugfs.c
index 9dd975b36b5b..edf3e5ef28a6 100644
--- a/drivers/scsi/snic/snic_debugfs.c
+++ b/drivers/scsi/snic/snic_debugfs.c
@@ -282,8 +282,8 @@ snic_stats_show(struct seq_file *sfp, void *data)
 	jiffies_to_timespec64(stats->misc.last_ack_time, &last_ack_tms);
 
 	seq_printf(sfp,
-		   "Last ISR Time               : %llu (%8llu.%09lu)\n"
-		   "Last Ack Time               : %llu (%8llu.%09lu)\n"
+		   "Last ISR Time               : %llu (%ptSp)\n"
+		   "Last Ack Time               : %llu (%ptSp)\n"
 		   "Ack ISRs                    : %llu\n"
 		   "IO Cmpl ISRs                : %llu\n"
 		   "Err Notify ISRs             : %llu\n"
@@ -298,10 +298,8 @@ snic_stats_show(struct seq_file *sfp, void *data)
 		   "Queue Ramp Down             : %lld\n"
 		   "Queue Last Queue Depth      : %lld\n"
 		   "Target Not Ready            : %lld\n",
-		   (u64) stats->misc.last_isr_time,
-		   last_isr_tms.tv_sec, last_isr_tms.tv_nsec,
-		   (u64)stats->misc.last_ack_time,
-		   last_ack_tms.tv_sec, last_ack_tms.tv_nsec,
+		   (u64) stats->misc.last_isr_time, &last_isr_tms,
+		   (u64) stats->misc.last_ack_time, &last_ack_tms,
 		   (u64) atomic64_read(&stats->misc.ack_isr_cnt),
 		   (u64) atomic64_read(&stats->misc.cmpl_isr_cnt),
 		   (u64) atomic64_read(&stats->misc.errnotify_isr_cnt),
diff --git a/drivers/scsi/snic/snic_trc.c b/drivers/scsi/snic/snic_trc.c
index c2e5ab7e976c..6bad1ea9a6a7 100644
--- a/drivers/scsi/snic/snic_trc.c
+++ b/drivers/scsi/snic/snic_trc.c
@@ -56,9 +56,8 @@ snic_fmt_trc_data(struct snic_trc_data *td, char *buf, int buf_sz)
 	jiffies_to_timespec64(td->ts, &tmspec);
 
 	len += snprintf(buf, buf_sz,
-			"%llu.%09lu %-25s %3d %4x %16llx %16llx %16llx %16llx %16llx\n",
-			tmspec.tv_sec,
-			tmspec.tv_nsec,
+			"%ptSp %-25s %3d %4x %16llx %16llx %16llx %16llx %16llx\n",
+			&tmspec,
 			td->fn,
 			td->hno,
 			td->tag,
-- 
2.50.1


^ permalink raw reply related

* [PATCH v2 19/21] scsi: fnic: Switch to use %ptS
From: Andy Shevchenko @ 2025-11-11 12:20 UTC (permalink / raw)
  To: Corey Minyard, Christian König, Dr. David Alan Gilbert,
	Alex Deucher, Thomas Zimmermann, Dmitry Baryshkov, Rob Clark,
	Matthew Brost, Ulf Hansson, Andy Shevchenko, Vitaly Lifshits,
	Manivannan Sadhasivam, Niklas Cassel, Calvin Owens,
	Vadim Fedorenko, Sagi Maimon, Martin K. Petersen,
	Karan Tilak Kumar, Hans Verkuil, Casey Schaufler, Steven Rostedt,
	Petr Mladek, Viacheslav Dubeyko, Max Kellermann, linux-doc,
	linux-kernel, openipmi-developer, linux-media, dri-devel,
	linaro-mm-sig, amd-gfx, linux-arm-msm, freedreno, intel-xe,
	linux-mmc, netdev, intel-wired-lan, linux-pci, linux-s390,
	linux-scsi, linux-staging, ceph-devel, linux-trace-kernel
  Cc: Rasmus Villemoes, Sergey Senozhatsky, Jonathan Corbet,
	Sumit Semwal, Gustavo Padovan, David Airlie, Simona Vetter,
	Maarten Lankhorst, Maxime Ripard, Dmitry Baryshkov, Abhinav Kumar,
	Jessica Zhang, Sean Paul, Marijn Suijten, Konrad Dybcio,
	Lucas De Marchi, Thomas Hellström, Rodrigo Vivi,
	Vladimir Oltean, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Tony Nguyen, Przemek Kitszel,
	Krzysztof Wilczyński, Kishon Vijay Abraham I, Bjorn Helgaas,
	Rodolfo Giometti, Richard Cochran, Jonathan Lemon,
	Stefan Haberland, Jan Hoeppner, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Satish Kharat, Sesidhar Baddela, James E.J. Bottomley,
	Mauro Carvalho Chehab, Greg Kroah-Hartman, Xiubo Li, Ilya Dryomov,
	Masami Hiramatsu, Mathieu Desnoyers, Andrew Morton
In-Reply-To: <20251111122735.880607-1-andriy.shevchenko@linux.intel.com>

Use %ptS instead of open coded variants to print content of
struct timespec64 in human readable format.

Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
 drivers/scsi/fnic/fnic_trace.c | 46 +++++++++++++++-------------------
 1 file changed, 20 insertions(+), 26 deletions(-)

diff --git a/drivers/scsi/fnic/fnic_trace.c b/drivers/scsi/fnic/fnic_trace.c
index cdc6b12b1ec2..f5543bb92ee4 100644
--- a/drivers/scsi/fnic/fnic_trace.c
+++ b/drivers/scsi/fnic/fnic_trace.c
@@ -138,9 +138,8 @@ int fnic_get_trace_data(fnic_dbgfs_t *fnic_dbgfs_prt)
 			 */
 			len += scnprintf(fnic_dbgfs_prt->buffer + len,
 				  (trace_max_pages * PAGE_SIZE * 3) - len,
-				  "%16llu.%09lu %-50s %8x %8x %16llx %16llx "
-				  "%16llx %16llx %16llx\n", (u64)val.tv_sec,
-				  val.tv_nsec, str, tbp->host_no, tbp->tag,
+				  "%ptSp %-50s %8x %8x %16llx %16llx %16llx %16llx %16llx\n",
+				  &val, str, tbp->host_no, tbp->tag,
 				  tbp->data[0], tbp->data[1], tbp->data[2],
 				  tbp->data[3], tbp->data[4]);
 			rd_idx++;
@@ -180,9 +179,8 @@ int fnic_get_trace_data(fnic_dbgfs_t *fnic_dbgfs_prt)
 			 */
 			len += scnprintf(fnic_dbgfs_prt->buffer + len,
 				  (trace_max_pages * PAGE_SIZE * 3) - len,
-				  "%16llu.%09lu %-50s %8x %8x %16llx %16llx "
-				  "%16llx %16llx %16llx\n", (u64)val.tv_sec,
-				  val.tv_nsec, str, tbp->host_no, tbp->tag,
+				  "%ptSp %-50s %8x %8x %16llx %16llx %16llx %16llx %16llx\n",
+				  &val, str, tbp->host_no, tbp->tag,
 				  tbp->data[0], tbp->data[1], tbp->data[2],
 				  tbp->data[3], tbp->data[4]);
 			rd_idx++;
@@ -225,20 +223,16 @@ int fnic_get_stats_data(struct stats_debug_info *debug,
 		"------------------------------------------\n");
 
 	len += scnprintf(debug->debug_buffer + len, buf_size - len,
-		"Current time :          [%lld:%ld]\n"
-		"Last stats reset time:  [%lld:%09ld]\n"
-		"Last stats read time:   [%lld:%ld]\n"
-		"delta since last reset: [%lld:%ld]\n"
-		"delta since last read:  [%lld:%ld]\n",
-	(s64)val1.tv_sec, val1.tv_nsec,
-	(s64)stats->stats_timestamps.last_reset_time.tv_sec,
-	stats->stats_timestamps.last_reset_time.tv_nsec,
-	(s64)stats->stats_timestamps.last_read_time.tv_sec,
-	stats->stats_timestamps.last_read_time.tv_nsec,
-	(s64)timespec64_sub(val1, stats->stats_timestamps.last_reset_time).tv_sec,
-	timespec64_sub(val1, stats->stats_timestamps.last_reset_time).tv_nsec,
-	(s64)timespec64_sub(val1, stats->stats_timestamps.last_read_time).tv_sec,
-	timespec64_sub(val1, stats->stats_timestamps.last_read_time).tv_nsec);
+		"Current time :          [%ptSp]\n"
+		"Last stats reset time:  [%ptSp]\n"
+		"Last stats read time:   [%ptSp]\n"
+		"delta since last reset: [%ptSp]\n"
+		"delta since last read:  [%ptSp]\n",
+	&val1,
+	&stats->stats_timestamps.last_reset_time,
+	&stats->stats_timestamps.last_read_time,
+	&timespec64_sub(val1, stats->stats_timestamps.last_reset_time),
+	&timespec64_sub(val1, stats->stats_timestamps.last_read_time));
 
 	stats->stats_timestamps.last_read_time = val1;
 
@@ -416,8 +410,8 @@ int fnic_get_stats_data(struct stats_debug_info *debug,
 	jiffies_to_timespec64(stats->misc_stats.last_ack_time, &val2);
 
 	len += scnprintf(debug->debug_buffer + len, buf_size - len,
-		  "Last ISR time: %llu (%8llu.%09lu)\n"
-		  "Last ACK time: %llu (%8llu.%09lu)\n"
+		  "Last ISR time: %llu (%ptSp)\n"
+		  "Last ACK time: %llu (%ptSp)\n"
 		  "Max ISR jiffies: %llu\n"
 		  "Max ISR time (ms) (0 denotes < 1 ms): %llu\n"
 		  "Corr. work done: %llu\n"
@@ -438,9 +432,9 @@ int fnic_get_stats_data(struct stats_debug_info *debug,
 		 "Number of receive frame errors: %lld\n"
 		 "Port speed (in Mbps): %lld\n",
 		  (u64)stats->misc_stats.last_isr_time,
-		  (s64)val1.tv_sec, val1.tv_nsec,
+		  &val1,
 		  (u64)stats->misc_stats.last_ack_time,
-		  (s64)val2.tv_sec, val2.tv_nsec,
+		  &val2,
 		  (u64)atomic64_read(&stats->misc_stats.max_isr_jiffies),
 		  (u64)atomic64_read(&stats->misc_stats.max_isr_time_ms),
 		  (u64)atomic64_read(&stats->misc_stats.corr_work_done),
@@ -857,8 +851,8 @@ void copy_and_format_trace_data(struct fc_trace_hdr *tdata,
 	len = *orig_len;
 
 	len += scnprintf(fnic_dbgfs_prt->buffer + len, max_size - len,
-			 "%ptTs.%09lu ns%8x       %c%8x\t",
-			 &tdata->time_stamp.tv_sec, tdata->time_stamp.tv_nsec,
+			 "%ptSs ns%8x       %c%8x\t",
+			 &tdata->time_stamp,
 			 tdata->host_no, tdata->frame_type, tdata->frame_len);
 
 	fc_trace = (char *)FC_TRACE_ADDRESS(tdata);
-- 
2.50.1


^ permalink raw reply related

* [PATCH v2 21/21] tracing: Switch to use %ptSp
From: Andy Shevchenko @ 2025-11-11 12:20 UTC (permalink / raw)
  To: Corey Minyard, Christian König, Dr. David Alan Gilbert,
	Alex Deucher, Thomas Zimmermann, Dmitry Baryshkov, Rob Clark,
	Matthew Brost, Ulf Hansson, Andy Shevchenko, Vitaly Lifshits,
	Manivannan Sadhasivam, Niklas Cassel, Calvin Owens,
	Vadim Fedorenko, Sagi Maimon, Martin K. Petersen,
	Karan Tilak Kumar, Hans Verkuil, Casey Schaufler, Steven Rostedt,
	Petr Mladek, Viacheslav Dubeyko, Max Kellermann, linux-doc,
	linux-kernel, openipmi-developer, linux-media, dri-devel,
	linaro-mm-sig, amd-gfx, linux-arm-msm, freedreno, intel-xe,
	linux-mmc, netdev, intel-wired-lan, linux-pci, linux-s390,
	linux-scsi, linux-staging, ceph-devel, linux-trace-kernel
  Cc: Rasmus Villemoes, Sergey Senozhatsky, Jonathan Corbet,
	Sumit Semwal, Gustavo Padovan, David Airlie, Simona Vetter,
	Maarten Lankhorst, Maxime Ripard, Dmitry Baryshkov, Abhinav Kumar,
	Jessica Zhang, Sean Paul, Marijn Suijten, Konrad Dybcio,
	Lucas De Marchi, Thomas Hellström, Rodrigo Vivi,
	Vladimir Oltean, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Tony Nguyen, Przemek Kitszel,
	Krzysztof Wilczyński, Kishon Vijay Abraham I, Bjorn Helgaas,
	Rodolfo Giometti, Richard Cochran, Jonathan Lemon,
	Stefan Haberland, Jan Hoeppner, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Satish Kharat, Sesidhar Baddela, James E.J. Bottomley,
	Mauro Carvalho Chehab, Greg Kroah-Hartman, Xiubo Li, Ilya Dryomov,
	Masami Hiramatsu, Mathieu Desnoyers, Andrew Morton
In-Reply-To: <20251111122735.880607-1-andriy.shevchenko@linux.intel.com>

Use %ptSp instead of open coded variants to print content of
struct timespec64 in human readable format.

Acked-by: Steven Rostedt (Google) <rostedt@goodmis.org>
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
 kernel/trace/trace_output.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/kernel/trace/trace_output.c b/kernel/trace/trace_output.c
index ebbab3e9622b..cc2d3306bb60 100644
--- a/kernel/trace/trace_output.c
+++ b/kernel/trace/trace_output.c
@@ -1490,12 +1490,12 @@ trace_hwlat_print(struct trace_iterator *iter, int flags,
 
 	trace_assign_type(field, entry);
 
-	trace_seq_printf(s, "#%-5u inner/outer(us): %4llu/%-5llu ts:%lld.%09ld count:%d",
+	trace_seq_printf(s, "#%-5u inner/outer(us): %4llu/%-5llu ts:%ptSp count:%d",
 			 field->seqnum,
 			 field->duration,
 			 field->outer_duration,
-			 (long long)field->timestamp.tv_sec,
-			 field->timestamp.tv_nsec, field->count);
+			 &field->timestamp,
+			 field->count);
 
 	if (field->nmi_count) {
 		/*
-- 
2.50.1


^ permalink raw reply related

* Re: [PATCH] function_graph: Enable funcgraph-args and funcgraph-retaddr to work simultaneously
From: Donglin Peng @ 2025-11-11 13:47 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: linux-kernel, linux-trace-kernel, Sven Schnelle, Masami Hiramatsu,
	pengdonglin
In-Reply-To: <20251110154337.774db22f@gandalf.local.home>

On Tue, Nov 11, 2025 at 4:43 AM Steven Rostedt <rostedt@goodmis.org> wrote:
>
> On Sun, 12 Oct 2025 00:41:56 +0800
> pengdonglin <dolinux.peng@gmail.com> wrote:
>
> > From: pengdonglin <pengdonglin@xiaomi.com>
>
> Sorry for the late reply. I finally got around to looking at this.
>
> >
> > Currently, funcgraph-args and funcgraph-retaddr cannot be used together. This patch
> > resolves the conflict by having funcgraph-retaddr reuse the implementation of
> > funcgraph-args -- specifically, storing the return address in the last entry of the
> > args array.
> >
> > As a result, both features now coexist seamlessly and function as intended.
> >
> > To verify the change, use perf to trace vfs_write with both options enabled:
> >
> >  # perf_6_17 ftrace -G vfs_write --graph-opts args,retaddr
> >  ......
> >  0)               |  down_read(sem=0xffff8880100bea78) { /* <-n_tty_write+0xa3/0x540 */
> >  0)   0.075 us    |    __cond_resched(); /* <-down_read+0x12/0x160 */
> >  0)   0.079 us    |    preempt_count_add(val=1); /* <-down_read+0x3b/0x160 */
> >  0)   0.077 us    |    preempt_count_sub(val=1); /* <-down_read+0x8b/0x160 */
> >  0)   0.754 us    |  }
> >
> > Cc: Steven Rostedt (Google) <rostedt@goodmis.org>
> > Cc: Sven Schnelle <svens@linux.ibm.com>
> > Cc: Masami Hiramatsu <mhiramat@kernel.org>
> > Signed-off-by: pengdonglin <pengdonglin@xiaomi.com>
> > Signed-off-by: pengdonglin <dolinux.peng@gmail.com>
> > ---
> >  include/linux/ftrace.h               |  11 --
> >  kernel/trace/trace.h                 |   7 --
> >  kernel/trace/trace_entries.h         |  29 +-----
> >  kernel/trace/trace_functions_graph.c | 148 +++++++++++----------------
> >  kernel/trace/trace_selftest.c        |   1 -
> >  5 files changed, 58 insertions(+), 138 deletions(-)
> >
> > diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
> > index 7ded7df6e9b5..88cb54d73bdb 100644
> > --- a/include/linux/ftrace.h
> > +++ b/include/linux/ftrace.h
> > @@ -1129,17 +1129,6 @@ struct ftrace_graph_ent {
> >       int depth;
> >  } __packed;
> >
> > -/*
> > - * Structure that defines an entry function trace with retaddr.
> > - * It's already packed but the attribute "packed" is needed
> > - * to remove extra padding at the end.
> > - */
> > -struct fgraph_retaddr_ent {
> > -     unsigned long func; /* Current function */
> > -     int depth;
> > -     unsigned long retaddr;  /* Return address */
> > -} __packed;
>
> I really like the clean up, but unfortunately, this breaks user space.
>
> We still need the retaddr event, as that is what user space expects.
>
> That said, this could do the same thing as the func-args. That is, it can
> add the function arguments after the retaddr field.

Thanks, will do in v2.

Thanks,
Donglin

>
> >       TRACE_GRAPH_RET,
> > diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c
> > index a7f4b9a47a71..b618b6a673b7 100644
> > --- a/kernel/trace/trace_functions_graph.c
> > +++ b/kernel/trace/trace_functions_graph.c
> > @@ -16,6 +16,12 @@
> >  #include "trace.h"
> >  #include "trace_output.h"
> >
> > +#ifdef CONFIG_FUNCTION_GRAPH_RETADDR
> > +#define  STORE_RETADDR  1
> > +#else
> > +#define  STORE_RETADDR  0
> > +#endif
> > +
> >  /* When set, irq functions will be ignored */
> >  static int ftrace_graph_skip_irqs;
> >
> > @@ -29,19 +35,17 @@ struct fgraph_cpu_data {
> >
> >  struct fgraph_ent_args {
> >       struct ftrace_graph_ent_entry   ent;
> > -     /* Force the sizeof of args[] to have FTRACE_REGS_MAX_ARGS entries */
> > -     unsigned long                   args[FTRACE_REGS_MAX_ARGS];
> > +     /* Force the sizeof of args[] to have (FTRACE_REGS_MAX_ARGS+STORE_RETADDR) entries,
> > +      * and the last entry is used to store the retaddr
> > +      */
> > +     unsigned long                   args[FTRACE_REGS_MAX_ARGS + STORE_RETADDR];
>
> I'm thinking, if it is a different event, then it can still use the same
> array. But retaddr will be first, and not last.

Thanks, will do in v2.

Thanks,
Donglin

>
> >  };
> >
> >  struct fgraph_data {
> >       struct fgraph_cpu_data __percpu *cpu_data;
> >
> >       /* Place to preserve last processed entry. */
> > -     union {
> > -             struct fgraph_ent_args          ent;
> > -             /* TODO allow retaddr to have args */
> > -             struct fgraph_retaddr_ent_entry rent;
> > -     };
> > +     struct fgraph_ent_args          ent;
>
> Where this could still be the same.
>
> >       struct ftrace_graph_ret_entry   ret;
> >       int                             failed;
> >       int                             cpu;
> > @@ -127,11 +131,19 @@ static int __graph_entry(struct trace_array *tr, struct ftrace_graph_ent *trace,
> >       struct ring_buffer_event *event;
> >       struct trace_buffer *buffer = tr->array_buffer.buffer;
> >       struct ftrace_graph_ent_entry *entry;
> > +     unsigned long retaddr = 0;
> >       int size;
> > +     int i = 0;
> >
> >       /* If fregs is defined, add FTRACE_REGS_MAX_ARGS long size words */
> >       size = sizeof(*entry) + (FTRACE_REGS_MAX_ARGS * !!fregs * sizeof(long));
> >
> > +     if (IS_ENABLED(CONFIG_FUNCTION_GRAPH_RETADDR) &&
> > +         tracer_flags_is_set(TRACE_GRAPH_PRINT_RETADDR)) {
> > +             retaddr = ftrace_graph_top_ret_addr(current);
> > +             size += sizeof(long);
> > +     }
> > +
> >       event = trace_buffer_lock_reserve(buffer, TRACE_GRAPH_ENT, size, trace_ctx);
> >       if (!event)
> >               return 0;
> > @@ -141,11 +153,17 @@ static int __graph_entry(struct trace_array *tr, struct ftrace_graph_ent *trace,
> >
> >  #ifdef CONFIG_HAVE_FUNCTION_ARG_ACCESS_API
> >       if (fregs) {
> > -             for (int i = 0; i < FTRACE_REGS_MAX_ARGS; i++)
> > +             for (; i < FTRACE_REGS_MAX_ARGS; i++)
> >                       entry->args[i] = ftrace_regs_get_argument(fregs, i);
> >       }
> >  #endif
> >
> > +     /*
> > +      * Store retaddr to [0] if fregs is NULL, else to [FTRACE_REGS_MAX_ARGS]
> > +      */
> > +     if (retaddr)
> > +             entry->args[i] = retaddr;
> > +
>
> Move this up before the args.

Thanks, will do in v2.

Thanks,
Donglin

>
> >       trace_buffer_unlock_commit_nostack(buffer, event);
> >
> >       return 1;
> > @@ -158,38 +176,6 @@ int __trace_graph_entry(struct trace_array *tr,
> >       return __graph_entry(tr, trace, trace_ctx, NULL);
> >  }
> >
> > -#ifdef CONFIG_FUNCTION_GRAPH_RETADDR
> > -int __trace_graph_retaddr_entry(struct trace_array *tr,
> > -                             struct ftrace_graph_ent *trace,
> > -                             unsigned int trace_ctx,
> > -                             unsigned long retaddr)
> > -{
> > -     struct ring_buffer_event *event;
> > -     struct trace_buffer *buffer = tr->array_buffer.buffer;
> > -     struct fgraph_retaddr_ent_entry *entry;
> > -
> > -     event = trace_buffer_lock_reserve(buffer, TRACE_GRAPH_RETADDR_ENT,
> > -                                       sizeof(*entry), trace_ctx);
>
> The reserve would need to use TRACE_GRAPH_RETADDR_ENT if retaddr is set.
> But I still think you can consolidate the code.
>
> -- Steve
>
> > -     if (!event)
> > -             return 0;
> > -     entry   = ring_buffer_event_data(event);
> > -     entry->graph_ent.func = trace->func;
> > -     entry->graph_ent.depth = trace->depth;
> > -     entry->graph_ent.retaddr = retaddr;
> > -     trace_buffer_unlock_commit_nostack(buffer, event);
> > -
> > -     return 1;
> > -}
> > -#else
> > -int __trace_graph_retaddr_entry(struct trace_array *tr,
> > -                             struct ftrace_graph_ent *trace,
> > -                             unsigned int trace_ctx,
> > -                             unsigned long retaddr)
> > -{
> > -     return 1;
> > -}
> > -#endif
> > -
> >  static inline int ftrace_graph_ignore_irqs(void)
> >  {
> >       if (!ftrace_graph_skip_irqs || trace_recursion_test(TRACE_IRQ_BIT))

^ permalink raw reply

* [PATCH v2] function_graph: Enable funcgraph-args and funcgraph-retaddr to work simultaneously
From: Donglin Peng @ 2025-11-11 13:54 UTC (permalink / raw)
  To: rostedt
  Cc: linux-trace-kernel, linux-kernel, Donglin Peng, Sven Schnelle,
	Masami Hiramatsu, Donglin Peng

From: Donglin Peng <pengdonglin@xiaomi.com>

Currently, the funcgraph-args and funcgraph-retaddr features are mutually exclusive.
This patch resolves this limitation by modifying funcgraph-retaddr to adopt the same
implementation approach as funcgraph-args, specifically by storing the return address
in the first entry of the args array.

As a result, both features now coexist seamlessly and function as intended.

To verify the change, use perf to trace vfs_write with both options enabled:

Before:
 # perf_6_17 ftrace -G vfs_write --graph-opts args,retaddr
 ......
 0)               |  down_read() { /* <-n_tty_write+0xa3/0x540 */
 0)   0.075 us    |    __cond_resched(); /* <-down_read+0x12/0x160 */
 0)   0.079 us    |    preempt_count_add(); /* <-down_read+0x3b/0x160 */
 0)   0.077 us    |    preempt_count_sub(); /* <-down_read+0x8b/0x160 */
 0)   0.754 us    |  }

After:
 # perf_6_17 ftrace -G vfs_write --graph-opts args,retaddr
 ......
 0)               |  down_read(sem=0xffff8880100bea78) { /* <-n_tty_write+0xa3/0x540 */
 0)   0.075 us    |    __cond_resched(); /* <-down_read+0x12/0x160 */
 0)   0.079 us    |    preempt_count_add(val=1); /* <-down_read+0x3b/0x160 */
 0)   0.077 us    |    preempt_count_sub(val=1); /* <-down_read+0x8b/0x160 */
 0)   0.754 us    |  }

Cc: Steven Rostedt (Google) <rostedt@goodmis.org>
Cc: Sven Schnelle <svens@linux.ibm.com>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Signed-off-by: Donglin Peng <pengdonglin@xiaomi.com>
Signed-off-by: Donglin Peng <dolinux.peng@gmail.com>
---
v2:
- do not remove retaddr event, suggested by Steven
- store the retaddr in args[0], suggested by Steven
---
 include/linux/ftrace.h               |  11 --
 kernel/trace/trace.h                 |   4 -
 kernel/trace/trace_entries.h         |   6 +-
 kernel/trace/trace_functions_graph.c | 148 ++++++++++++---------------
 4 files changed, 71 insertions(+), 98 deletions(-)

diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index 7ded7df6e9b5..88cb54d73bdb 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -1129,17 +1129,6 @@ struct ftrace_graph_ent {
 	int depth;
 } __packed;
 
-/*
- * Structure that defines an entry function trace with retaddr.
- * It's already packed but the attribute "packed" is needed
- * to remove extra padding at the end.
- */
-struct fgraph_retaddr_ent {
-	unsigned long func; /* Current function */
-	int depth;
-	unsigned long retaddr;  /* Return address */
-} __packed;
-
 /*
  * Structure that defines a return function trace.
  * It's already packed but the attribute "packed" is needed
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 85eabb454bee..9fac291b913a 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -955,10 +955,6 @@ extern void graph_trace_close(struct trace_iterator *iter);
 extern int __trace_graph_entry(struct trace_array *tr,
 			       struct ftrace_graph_ent *trace,
 			       unsigned int trace_ctx);
-extern int __trace_graph_retaddr_entry(struct trace_array *tr,
-				struct ftrace_graph_ent *trace,
-				unsigned int trace_ctx,
-				unsigned long retaddr);
 extern void __trace_graph_return(struct trace_array *tr,
 				 struct ftrace_graph_ret *trace,
 				 unsigned int trace_ctx,
diff --git a/kernel/trace/trace_entries.h b/kernel/trace/trace_entries.h
index de294ae2c5c5..593a74663c65 100644
--- a/kernel/trace/trace_entries.h
+++ b/kernel/trace/trace_entries.h
@@ -95,14 +95,14 @@ FTRACE_ENTRY_PACKED(fgraph_retaddr_entry, fgraph_retaddr_ent_entry,
 	TRACE_GRAPH_RETADDR_ENT,
 
 	F_STRUCT(
-		__field_struct(	struct fgraph_retaddr_ent,	graph_ent	)
+		__field_struct(	struct ftrace_graph_ent,	graph_ent	)
 		__field_packed(	unsigned long,	graph_ent,	func		)
 		__field_packed(	unsigned int,	graph_ent,	depth		)
-		__field_packed(	unsigned long,	graph_ent,	retaddr		)
+		__dynamic_array(unsigned long,	args				)
 	),
 
 	F_printk("--> %ps (%u) <- %ps", (void *)__entry->func, __entry->depth,
-		(void *)__entry->retaddr)
+		(void *)__entry->args[0])
 );
 
 #else
diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c
index a7f4b9a47a71..06b140d510e3 100644
--- a/kernel/trace/trace_functions_graph.c
+++ b/kernel/trace/trace_functions_graph.c
@@ -16,6 +16,15 @@
 #include "trace.h"
 #include "trace_output.h"
 
+#ifdef CONFIG_FUNCTION_GRAPH_RETADDR
+#define HAVE_RETADDR	1
+#define ARGS_OFFS(args_size) \
+	((args_size) > FTRACE_REGS_MAX_ARGS * sizeof(long) ? 1 : 0)
+#else
+#define HAVE_RETADDR	0
+#define ARGS_OFFS(args_size)	0
+#endif
+
 /* When set, irq functions will be ignored */
 static int ftrace_graph_skip_irqs;
 
@@ -27,21 +36,25 @@ struct fgraph_cpu_data {
 	unsigned long	enter_funcs[FTRACE_RETFUNC_DEPTH];
 };
 
+/*
+ * fgraph_retaddr_ent_entry and ftrace_graph_ent_entry share layout, ent
+ * member repurposed for storage
+ */
 struct fgraph_ent_args {
 	struct ftrace_graph_ent_entry	ent;
-	/* Force the sizeof of args[] to have FTRACE_REGS_MAX_ARGS entries */
-	unsigned long			args[FTRACE_REGS_MAX_ARGS];
+	/*
+	 * Force the sizeof of args[] to have (FTRACE_REGS_MAX_ARGS + HAVE_RETADDR)
+	 * entries with the first entry storing the return address for
+	 * TRACE_GRAPH_RETADDR_ENT.
+	 */
+	unsigned long		args[FTRACE_REGS_MAX_ARGS + HAVE_RETADDR];
 };
 
 struct fgraph_data {
 	struct fgraph_cpu_data __percpu *cpu_data;
 
 	/* Place to preserve last processed entry. */
-	union {
-		struct fgraph_ent_args		ent;
-		/* TODO allow retaddr to have args */
-		struct fgraph_retaddr_ent_entry	rent;
-	};
+	struct fgraph_ent_args		ent;
 	struct ftrace_graph_ret_entry	ret;
 	int				failed;
 	int				cpu;
@@ -127,22 +140,44 @@ static int __graph_entry(struct trace_array *tr, struct ftrace_graph_ent *trace,
 	struct ring_buffer_event *event;
 	struct trace_buffer *buffer = tr->array_buffer.buffer;
 	struct ftrace_graph_ent_entry *entry;
-	int size;
+	unsigned long retaddr = 0;
+	int size = sizeof(*entry);
+	int type = TRACE_GRAPH_ENT;
+	bool store_args = false;
+	int nr_args = 0, i = 0;
+
+	if (tracer_flags_is_set(TRACE_GRAPH_PRINT_RETADDR)) {
+		retaddr = ftrace_graph_top_ret_addr(current);
+		type = TRACE_GRAPH_RETADDR_ENT;
+		nr_args += 1;
+	}
 
 	/* If fregs is defined, add FTRACE_REGS_MAX_ARGS long size words */
-	size = sizeof(*entry) + (FTRACE_REGS_MAX_ARGS * !!fregs * sizeof(long));
+	if (tracer_flags_is_set(TRACE_GRAPH_ARGS)) {
+		store_args = !!fregs;
+		if (store_args)
+			nr_args += FTRACE_REGS_MAX_ARGS;
+	}
 
-	event = trace_buffer_lock_reserve(buffer, TRACE_GRAPH_ENT, size, trace_ctx);
+	size += nr_args * sizeof(long);
+	event = trace_buffer_lock_reserve(buffer, type, size, trace_ctx);
 	if (!event)
 		return 0;
 
 	entry = ring_buffer_event_data(event);
 	entry->graph_ent = *trace;
 
+	/* Store the retaddr in args[0] */
+	if (type == TRACE_GRAPH_RETADDR_ENT)
+		entry->args[i++] = retaddr;
+
 #ifdef CONFIG_HAVE_FUNCTION_ARG_ACCESS_API
-	if (fregs) {
-		for (int i = 0; i < FTRACE_REGS_MAX_ARGS; i++)
-			entry->args[i] = ftrace_regs_get_argument(fregs, i);
+	if (store_args) {
+		while (i < nr_args) {
+			entry->args[i] = ftrace_regs_get_argument(fregs,
+						i - (type == TRACE_GRAPH_RETADDR_ENT ? 1 : 0));
+			i++;
+		}
 	}
 #endif
 
@@ -158,38 +193,6 @@ int __trace_graph_entry(struct trace_array *tr,
 	return __graph_entry(tr, trace, trace_ctx, NULL);
 }
 
-#ifdef CONFIG_FUNCTION_GRAPH_RETADDR
-int __trace_graph_retaddr_entry(struct trace_array *tr,
-				struct ftrace_graph_ent *trace,
-				unsigned int trace_ctx,
-				unsigned long retaddr)
-{
-	struct ring_buffer_event *event;
-	struct trace_buffer *buffer = tr->array_buffer.buffer;
-	struct fgraph_retaddr_ent_entry *entry;
-
-	event = trace_buffer_lock_reserve(buffer, TRACE_GRAPH_RETADDR_ENT,
-					  sizeof(*entry), trace_ctx);
-	if (!event)
-		return 0;
-	entry	= ring_buffer_event_data(event);
-	entry->graph_ent.func = trace->func;
-	entry->graph_ent.depth = trace->depth;
-	entry->graph_ent.retaddr = retaddr;
-	trace_buffer_unlock_commit_nostack(buffer, event);
-
-	return 1;
-}
-#else
-int __trace_graph_retaddr_entry(struct trace_array *tr,
-				struct ftrace_graph_ent *trace,
-				unsigned int trace_ctx,
-				unsigned long retaddr)
-{
-	return 1;
-}
-#endif
-
 static inline int ftrace_graph_ignore_irqs(void)
 {
 	if (!ftrace_graph_skip_irqs || trace_recursion_test(TRACE_IRQ_BIT))
@@ -211,7 +214,6 @@ static int graph_entry(struct ftrace_graph_ent *trace,
 	struct trace_array *tr = gops->private;
 	struct fgraph_times *ftimes;
 	unsigned int trace_ctx;
-	int ret = 0;
 
 	if (*task_var & TRACE_GRAPH_NOTRACE)
 		return 0;
@@ -262,15 +264,7 @@ static int graph_entry(struct ftrace_graph_ent *trace,
 		return 1;
 
 	trace_ctx = tracing_gen_ctx();
-	if (IS_ENABLED(CONFIG_FUNCTION_GRAPH_RETADDR) &&
-	    tracer_flags_is_set(TRACE_GRAPH_PRINT_RETADDR)) {
-		unsigned long retaddr = ftrace_graph_top_ret_addr(current);
-		ret = __trace_graph_retaddr_entry(tr, trace, trace_ctx, retaddr);
-	} else {
-		ret = __graph_entry(tr, trace, trace_ctx, fregs);
-	}
-
-	return ret;
+	return __graph_entry(tr, trace, trace_ctx, fregs);
 }
 
 int trace_graph_entry(struct ftrace_graph_ent *trace,
@@ -634,13 +628,9 @@ get_return_for_leaf(struct trace_iterator *iter,
 			 * Save current and next entries for later reference
 			 * if the output fails.
 			 */
-			if (unlikely(curr->ent.type == TRACE_GRAPH_RETADDR_ENT)) {
-				data->rent = *(struct fgraph_retaddr_ent_entry *)curr;
-			} else {
-				int size = min((int)sizeof(data->ent), (int)iter->ent_size);
+			int size = min((int)sizeof(data->ent), (int)iter->ent_size);
 
-				memcpy(&data->ent, curr, size);
-			}
+			memcpy(&data->ent, curr, size);
 			/*
 			 * If the next event is not a return type, then
 			 * we only care about what type it is. Otherwise we can
@@ -811,21 +801,21 @@ print_graph_duration(struct trace_array *tr, unsigned long long duration,
 
 #ifdef CONFIG_FUNCTION_GRAPH_RETADDR
 #define __TRACE_GRAPH_PRINT_RETADDR TRACE_GRAPH_PRINT_RETADDR
-static void print_graph_retaddr(struct trace_seq *s, struct fgraph_retaddr_ent_entry *entry,
-				u32 trace_flags, bool comment)
+static void print_graph_retaddr(struct trace_seq *s, unsigned long retaddr, u32 trace_flags,
+				bool comment)
 {
 	if (comment)
 		trace_seq_puts(s, " /*");
 
 	trace_seq_puts(s, " <-");
-	seq_print_ip_sym(s, entry->graph_ent.retaddr, trace_flags | TRACE_ITER_SYM_OFFSET);
+	seq_print_ip_sym(s, retaddr, trace_flags | TRACE_ITER_SYM_OFFSET);
 
 	if (comment)
 		trace_seq_puts(s, " */");
 }
 #else
 #define __TRACE_GRAPH_PRINT_RETADDR 0
-#define print_graph_retaddr(_seq, _entry, _tflags, _comment)		do { } while (0)
+#define print_graph_retaddr(_seq, _retaddr, _tflags, _comment)		do { } while (0)
 #endif
 
 #if defined(CONFIG_FUNCTION_GRAPH_RETVAL) || defined(CONFIG_FUNCTION_GRAPH_RETADDR)
@@ -869,10 +859,12 @@ static void print_graph_retval(struct trace_seq *s, struct ftrace_graph_ent_entr
 		trace_seq_printf(s, "%ps", func);
 
 		if (args_size >= FTRACE_REGS_MAX_ARGS * sizeof(long)) {
-			print_function_args(s, entry->args, (unsigned long)func);
+			print_function_args(s, entry->args + ARGS_OFFS(args_size),
+					    (unsigned long)func);
 			trace_seq_putc(s, ';');
-		} else
+		} else {
 			trace_seq_puts(s, "();");
+		}
 
 		if (print_retval || print_retaddr)
 			trace_seq_puts(s, " /*");
@@ -882,8 +874,7 @@ static void print_graph_retval(struct trace_seq *s, struct ftrace_graph_ent_entr
 	}
 
 	if (print_retaddr)
-		print_graph_retaddr(s, (struct fgraph_retaddr_ent_entry *)entry,
-				    trace_flags, false);
+		print_graph_retaddr(s, entry->args[0], trace_flags, false);
 
 	if (print_retval) {
 		if (hex_format || (err_code == 0))
@@ -964,10 +955,12 @@ print_graph_entry_leaf(struct trace_iterator *iter,
 		trace_seq_printf(s, "%ps", (void *)ret_func);
 
 		if (args_size >= FTRACE_REGS_MAX_ARGS * sizeof(long)) {
-			print_function_args(s, entry->args, ret_func);
+			print_function_args(s, entry->args + ARGS_OFFS(args_size),
+					    ret_func);
 			trace_seq_putc(s, ';');
-		} else
+		} else {
 			trace_seq_puts(s, "();");
+		}
 	}
 	trace_seq_putc(s, '\n');
 
@@ -1016,7 +1009,7 @@ print_graph_entry_nested(struct trace_iterator *iter,
 	args_size = iter->ent_size - offsetof(struct ftrace_graph_ent_entry, args);
 
 	if (args_size >= FTRACE_REGS_MAX_ARGS * sizeof(long))
-		print_function_args(s, entry->args, func);
+		print_function_args(s, entry->args + ARGS_OFFS(args_size), func);
 	else
 		trace_seq_puts(s, "()");
 
@@ -1024,8 +1017,7 @@ print_graph_entry_nested(struct trace_iterator *iter,
 
 	if (flags & __TRACE_GRAPH_PRINT_RETADDR  &&
 		entry->ent.type == TRACE_GRAPH_RETADDR_ENT)
-		print_graph_retaddr(s, (struct fgraph_retaddr_ent_entry *)entry,
-			tr->trace_flags, true);
+		print_graph_retaddr(s, entry->args[0], tr->trace_flags, true);
 	trace_seq_putc(s, '\n');
 
 	if (trace_seq_has_overflowed(s))
@@ -1202,7 +1194,7 @@ print_graph_entry(struct ftrace_graph_ent_entry *field, struct trace_seq *s,
 	 * it can be safely saved at the stack.
 	 */
 	struct ftrace_graph_ent_entry *entry;
-	u8 save_buf[sizeof(*entry) + FTRACE_REGS_MAX_ARGS * sizeof(long)];
+	u8 save_buf[sizeof(*entry) + (FTRACE_REGS_MAX_ARGS + HAVE_RETADDR) * sizeof(long)];
 
 	/* The ent_size is expected to be as big as the entry */
 	if (iter->ent_size > sizeof(save_buf))
@@ -1429,16 +1421,12 @@ print_graph_function_flags(struct trace_iterator *iter, u32 flags)
 		trace_assign_type(field, entry);
 		return print_graph_entry(field, s, iter, flags);
 	}
-#ifdef CONFIG_FUNCTION_GRAPH_RETADDR
 	case TRACE_GRAPH_RETADDR_ENT: {
-		struct fgraph_retaddr_ent_entry saved;
 		struct fgraph_retaddr_ent_entry *rfield;
 
 		trace_assign_type(rfield, entry);
-		saved = *rfield;
-		return print_graph_entry((struct ftrace_graph_ent_entry *)&saved, s, iter, flags);
+		return print_graph_entry((typeof(field))rfield, s, iter, flags);
 	}
-#endif
 	case TRACE_GRAPH_RET: {
 		struct ftrace_graph_ret_entry *field;
 		trace_assign_type(field, entry);
-- 
2.34.1


^ permalink raw reply related

* Re: [PATCH v1 12/23] ipmi: Switch to use %ptSp
From: Corey Minyard @ 2025-11-11 14:37 UTC (permalink / raw)
  To: Sergey Senozhatsky
  Cc: Andy Shevchenko, Christian K??nig, Dr. David Alan Gilbert,
	Alex Deucher, Thomas Zimmermann, Dmitry Baryshkov, Rob Clark,
	Matthew Brost, Hans Verkuil, Laurent Pinchart, Ulf Hansson,
	Vitaly Lifshits, Manivannan Sadhasivam, Niklas Cassel,
	Calvin Owens, Sagi Maimon, Martin K. Petersen, Karan Tilak Kumar,
	Casey Schaufler, Steven Rostedt, Petr Mladek, Max Kellermann,
	Takashi Iwai, linux-doc, linux-kernel, openipmi-developer,
	linux-media, dri-devel, linaro-mm-sig, amd-gfx, linux-arm-msm,
	freedreno, intel-xe, linux-mmc, netdev, intel-wired-lan,
	linux-pci, linux-s390, linux-scsi, linux-staging, ceph-devel,
	linux-trace-kernel, linux-sound, Rasmus Villemoes,
	Jonathan Corbet, Sumit Semwal, Gustavo Padovan, David Airlie,
	Simona Vetter, Maarten Lankhorst, Maxime Ripard, Dmitry Baryshkov,
	Abhinav Kumar, Jessica Zhang, Sean Paul, Marijn Suijten,
	Konrad Dybcio, Lucas De Marchi, Thomas Hellstr??m, Rodrigo Vivi,
	Mauro Carvalho Chehab, Vladimir Oltean, Andrew Lunn,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Tony Nguyen, Przemek Kitszel, Krzysztof Wilczy??ski,
	Kishon Vijay Abraham I, Bjorn Helgaas, Rodolfo Giometti,
	Jonathan Lemon, Vadim Fedorenko, Richard Cochran,
	Stefan Haberland, Jan Hoeppner, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Satish Kharat, Sesidhar Baddela, James E.J. Bottomley,
	Greg Kroah-Hartman, Xiubo Li, Ilya Dryomov, Masami Hiramatsu,
	Mathieu Desnoyers, Andrew Morton, Jaroslav Kysela, Takashi Iwai
In-Reply-To: <pvjnjwm25ogu7khrpg5ttxylwnxazwxxb4jpvxhw7ysvqzkkpa@ucekjrrppaqm>

On Tue, Nov 11, 2025 at 05:08:25PM +0900, Sergey Senozhatsky wrote:
> On (25/11/10 19:40), Andy Shevchenko wrote:
> [..]
> > +	dev_dbg(smi_info->io.dev, "**%s: %ptSp\n", msg, &t);
> 
> Strictly speaking, this is not exactly equivalent to %lld.%9.9ld
> or %lld.%6.6ld but I don't know if that's of any importance.
> 

Dang it, I'm traveling and used the wrong way to send the previous response.
Sorry.

Anyway, yes, it's not equivalent, but it's not important.  It's better
to use a standard output format.  Thanks for pointing this out.

Thanks,

-corey

^ permalink raw reply

* Re: [PATCH v2 04/21] dma-buf: Switch to use %ptSp
From: Sumit Semwal @ 2025-11-11 14:43 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Corey Minyard, Christian König, Dr. David Alan Gilbert,
	Alex Deucher, Thomas Zimmermann, Dmitry Baryshkov, Rob Clark,
	Matthew Brost, Ulf Hansson, Vitaly Lifshits,
	Manivannan Sadhasivam, Niklas Cassel, Calvin Owens,
	Vadim Fedorenko, Sagi Maimon, Martin K. Petersen,
	Karan Tilak Kumar, Hans Verkuil, Casey Schaufler, Steven Rostedt,
	Petr Mladek, Viacheslav Dubeyko, Max Kellermann, linux-doc,
	linux-kernel, openipmi-developer, linux-media, dri-devel,
	linaro-mm-sig, amd-gfx, linux-arm-msm, freedreno, intel-xe,
	linux-mmc, netdev, intel-wired-lan, linux-pci, linux-s390,
	linux-scsi, linux-staging, ceph-devel, linux-trace-kernel,
	Rasmus Villemoes, Sergey Senozhatsky, Jonathan Corbet,
	Gustavo Padovan, David Airlie, Simona Vetter, Maarten Lankhorst,
	Maxime Ripard, Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang,
	Sean Paul, Marijn Suijten, Konrad Dybcio, Lucas De Marchi,
	Thomas Hellström, Rodrigo Vivi, Vladimir Oltean, Andrew Lunn,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Tony Nguyen, Przemek Kitszel, Krzysztof Wilczyński,
	Kishon Vijay Abraham I, Bjorn Helgaas, Rodolfo Giometti,
	Richard Cochran, Jonathan Lemon, Stefan Haberland, Jan Hoeppner,
	Heiko Carstens, Vasily Gorbik, Alexander Gordeev,
	Christian Borntraeger, Sven Schnelle, Satish Kharat,
	Sesidhar Baddela, James E.J. Bottomley, Mauro Carvalho Chehab,
	Greg Kroah-Hartman, Xiubo Li, Ilya Dryomov, Masami Hiramatsu,
	Mathieu Desnoyers, Andrew Morton
In-Reply-To: <20251111122735.880607-5-andriy.shevchenko@linux.intel.com>

Hello Andy,


On Tue, 11 Nov 2025 at 17:57, Andy Shevchenko
<andriy.shevchenko@linux.intel.com> wrote:
>
> Use %ptSp instead of open coded variants to print content of
> struct timespec64 in human readable format.
>
> Reviewed-by: Christian König <christian.koenig@amd.com>
> Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Thanks for the patch.

FWIW, please feel free to add
Acked-by: Sumit Semwal <sumit.semwal@linaro.org>

Best,
Sumit.
> ---
>  drivers/dma-buf/sync_debug.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/dma-buf/sync_debug.c b/drivers/dma-buf/sync_debug.c
> index 67cd69551e42..9e5d662cd4e8 100644
> --- a/drivers/dma-buf/sync_debug.c
> +++ b/drivers/dma-buf/sync_debug.c
> @@ -59,7 +59,7 @@ static void sync_print_fence(struct seq_file *s,
>                 struct timespec64 ts64 =
>                         ktime_to_timespec64(fence->timestamp);
>
> -               seq_printf(s, "@%lld.%09ld", (s64)ts64.tv_sec, ts64.tv_nsec);
> +               seq_printf(s, "@%ptSp", &ts64);
>         }
>
>         seq_printf(s, ": %lld", fence->seqno);
> --
> 2.50.1
>

^ permalink raw reply

* RE: [PATCH v2 05/21] drm/amdgpu: Switch to use %ptSp
From: Deucher, Alexander @ 2025-11-11 14:49 UTC (permalink / raw)
  To: Andy Shevchenko, Corey Minyard, Koenig, Christian,
	Dr. David Alan Gilbert, Thomas Zimmermann, Dmitry Baryshkov,
	Rob Clark, Matthew Brost, Ulf Hansson, Vitaly Lifshits,
	Manivannan Sadhasivam, Niklas Cassel, Calvin Owens,
	Vadim Fedorenko, Sagi Maimon, Martin K. Petersen,
	Karan Tilak Kumar, Hans Verkuil, Casey Schaufler, Steven Rostedt,
	Petr Mladek, Viacheslav Dubeyko, Max Kellermann,
	linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org,
	openipmi-developer@lists.sourceforge.net,
	linux-media@vger.kernel.org, dri-devel@lists.freedesktop.org,
	linaro-mm-sig@lists.linaro.org, amd-gfx@lists.freedesktop.org,
	linux-arm-msm@vger.kernel.org, freedreno@lists.freedesktop.org,
	intel-xe@lists.freedesktop.org, linux-mmc@vger.kernel.org,
	netdev@vger.kernel.org, intel-wired-lan@lists.osuosl.org,
	linux-pci@vger.kernel.org, linux-s390@vger.kernel.org,
	linux-scsi@vger.kernel.org, linux-staging@lists.linux.dev,
	ceph-devel@vger.kernel.org, linux-trace-kernel@vger.kernel.org
  Cc: Rasmus Villemoes, Sergey Senozhatsky, Jonathan Corbet,
	Sumit Semwal, Gustavo Padovan, David Airlie, Simona Vetter,
	Maarten Lankhorst, Maxime Ripard, Dmitry Baryshkov, Abhinav Kumar,
	Jessica Zhang, Sean Paul, Marijn Suijten, Konrad Dybcio,
	Lucas De Marchi, Thomas Hellström, Rodrigo Vivi,
	Vladimir Oltean, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Tony Nguyen, Przemek Kitszel,
	Krzysztof Wilczyński, Kishon Vijay Abraham I, Bjorn Helgaas,
	Rodolfo Giometti, Richard Cochran, Jonathan Lemon,
	Stefan Haberland, Jan Hoeppner, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Satish Kharat, Sesidhar Baddela, James E.J. Bottomley,
	Mauro Carvalho Chehab, Greg Kroah-Hartman, Xiubo Li, Ilya Dryomov,
	Masami Hiramatsu, Mathieu Desnoyers, Andrew Morton
In-Reply-To: <20251111122735.880607-6-andriy.shevchenko@linux.intel.com>

[Public]

> -----Original Message-----
> From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> Sent: Tuesday, November 11, 2025 7:20 AM
> To: Corey Minyard <corey@minyard.net>; Koenig, Christian
> <Christian.Koenig@amd.com>; Dr. David Alan Gilbert <linux@treblig.org>;
> Deucher, Alexander <Alexander.Deucher@amd.com>; Thomas Zimmermann
> <tzimmermann@suse.de>; Dmitry Baryshkov
> <dmitry.baryshkov@oss.qualcomm.com>; Rob Clark
> <robin.clark@oss.qualcomm.com>; Matthew Brost
> <matthew.brost@intel.com>; Ulf Hansson <ulf.hansson@linaro.org>; Andy
> Shevchenko <andriy.shevchenko@linux.intel.com>; Vitaly Lifshits
> <vitaly.lifshits@intel.com>; Manivannan Sadhasivam <mani@kernel.org>;
> Niklas Cassel <cassel@kernel.org>; Calvin Owens <calvin@wbinvd.org>; Vadim
> Fedorenko <vadim.fedorenko@linux.dev>; Sagi Maimon
> <maimon.sagi@gmail.com>; Martin K. Petersen
> <martin.petersen@oracle.com>; Karan Tilak Kumar <kartilak@cisco.com>;
> Hans Verkuil <hverkuil+cisco@kernel.org>; Casey Schaufler <casey@schaufler-
> ca.com>; Steven Rostedt <rostedt@goodmis.org>; Petr Mladek
> <pmladek@suse.com>; Viacheslav Dubeyko <Slava.Dubeyko@ibm.com>; Max
> Kellermann <max.kellermann@ionos.com>; linux-doc@vger.kernel.org; linux-
> kernel@vger.kernel.org; openipmi-developer@lists.sourceforge.net; linux-
> media@vger.kernel.org; dri-devel@lists.freedesktop.org; linaro-mm-
> sig@lists.linaro.org; amd-gfx@lists.freedesktop.org; linux-arm-
> msm@vger.kernel.org; freedreno@lists.freedesktop.org; intel-
> xe@lists.freedesktop.org; linux-mmc@vger.kernel.org;
> netdev@vger.kernel.org; intel-wired-lan@lists.osuosl.org; linux-
> pci@vger.kernel.org; linux-s390@vger.kernel.org; linux-scsi@vger.kernel.org;
> linux-staging@lists.linux.dev; ceph-devel@vger.kernel.org; linux-trace-
> kernel@vger.kernel.org
> Cc: Rasmus Villemoes <linux@rasmusvillemoes.dk>; Sergey Senozhatsky
> <senozhatsky@chromium.org>; Jonathan Corbet <corbet@lwn.net>; Sumit
> Semwal <sumit.semwal@linaro.org>; Gustavo Padovan
> <gustavo@padovan.org>; David Airlie <airlied@gmail.com>; Simona Vetter
> <simona@ffwll.ch>; Maarten Lankhorst
> <maarten.lankhorst@linux.intel.com>; Maxime Ripard <mripard@kernel.org>;
> Dmitry Baryshkov <lumag@kernel.org>; Abhinav Kumar
> <abhinav.kumar@linux.dev>; Jessica Zhang <jesszhan0024@gmail.com>; Sean
> Paul <sean@poorly.run>; Marijn Suijten <marijn.suijten@somainline.org>;
> Konrad Dybcio <konradybcio@kernel.org>; Lucas De Marchi
> <lucas.demarchi@intel.com>; Thomas Hellström
> <thomas.hellstrom@linux.intel.com>; Rodrigo Vivi <rodrigo.vivi@intel.com>;
> Vladimir Oltean <olteanv@gmail.com>; Andrew Lunn <andrew@lunn.ch>;
> David S. Miller <davem@davemloft.net>; Eric Dumazet
> <edumazet@google.com>; Jakub Kicinski <kuba@kernel.org>; Paolo Abeni
> <pabeni@redhat.com>; Tony Nguyen <anthony.l.nguyen@intel.com>;
> Przemek Kitszel <przemyslaw.kitszel@intel.com>; Krzysztof Wilczyński
> <kwilczynski@kernel.org>; Kishon Vijay Abraham I <kishon@kernel.org>;
> Bjorn Helgaas <bhelgaas@google.com>; Rodolfo Giometti
> <giometti@enneenne.com>; Richard Cochran <richardcochran@gmail.com>;
> Jonathan Lemon <jonathan.lemon@gmail.com>; Stefan Haberland
> <sth@linux.ibm.com>; Jan Hoeppner <hoeppner@linux.ibm.com>; Heiko
> Carstens <hca@linux.ibm.com>; Vasily Gorbik <gor@linux.ibm.com>;
> Alexander Gordeev <agordeev@linux.ibm.com>; Christian Borntraeger
> <borntraeger@linux.ibm.com>; Sven Schnelle <svens@linux.ibm.com>; Satish
> Kharat <satishkh@cisco.com>; Sesidhar Baddela <sebaddel@cisco.com>;
> James E.J. Bottomley <James.Bottomley@HansenPartnership.com>; Mauro
> Carvalho Chehab <mchehab@kernel.org>; Greg Kroah-Hartman
> <gregkh@linuxfoundation.org>; Xiubo Li <xiubli@redhat.com>; Ilya Dryomov
> <idryomov@gmail.com>; Masami Hiramatsu <mhiramat@kernel.org>;
> Mathieu Desnoyers <mathieu.desnoyers@efficios.com>; Andrew Morton
> <akpm@linux-foundation.org>
> Subject: [PATCH v2 05/21] drm/amdgpu: Switch to use %ptSp
>
> Use %ptSp instead of open coded variants to print content of struct
> timespec64 in human readable format.
>
> Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>

Acked-by: Alex Deucher <alexander.deucher@amd.com>

> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c | 3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c
> index 8a026bc9ea44..4e2fe6674db8 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c
> @@ -217,8 +217,7 @@ amdgpu_devcoredump_read(char *buffer, loff_t
> offset, size_t count,
>       drm_printf(&p, "version: " AMDGPU_COREDUMP_VERSION "\n");
>       drm_printf(&p, "kernel: " UTS_RELEASE "\n");
>       drm_printf(&p, "module: " KBUILD_MODNAME "\n");
> -     drm_printf(&p, "time: %lld.%09ld\n", coredump->reset_time.tv_sec,
> -                coredump->reset_time.tv_nsec);
> +     drm_printf(&p, "time: %ptSp\n", &coredump->reset_time);
>
>       if (coredump->reset_task_info.task.pid)
>               drm_printf(&p, "process_name: %s PID: %d\n",
> --
> 2.50.1


^ permalink raw reply

* Re: [PATCH v2 01/21] lib/vsprintf: Add specifier for printing struct timespec64
From: Petr Mladek @ 2025-11-11 15:03 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Corey Minyard, Christian König, Dr. David Alan Gilbert,
	Alex Deucher, Thomas Zimmermann, Dmitry Baryshkov, Rob Clark,
	Matthew Brost, Ulf Hansson, Vitaly Lifshits,
	Manivannan Sadhasivam, Niklas Cassel, Calvin Owens,
	Vadim Fedorenko, Sagi Maimon, Martin K. Petersen,
	Karan Tilak Kumar, Hans Verkuil, Casey Schaufler, Steven Rostedt,
	Viacheslav Dubeyko, Max Kellermann, linux-doc, linux-kernel,
	openipmi-developer, linux-media, dri-devel, linaro-mm-sig,
	amd-gfx, linux-arm-msm, freedreno, intel-xe, linux-mmc, netdev,
	intel-wired-lan, linux-pci, linux-s390, linux-scsi, linux-staging,
	ceph-devel, linux-trace-kernel, Rasmus Villemoes,
	Sergey Senozhatsky, Jonathan Corbet, Sumit Semwal,
	Gustavo Padovan, David Airlie, Simona Vetter, Maarten Lankhorst,
	Maxime Ripard, Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang,
	Sean Paul, Marijn Suijten, Konrad Dybcio, Lucas De Marchi,
	Thomas Hellström, Rodrigo Vivi, Vladimir Oltean, Andrew Lunn,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Tony Nguyen, Przemek Kitszel, Krzysztof Wilczyński,
	Kishon Vijay Abraham I, Bjorn Helgaas, Rodolfo Giometti,
	Richard Cochran, Jonathan Lemon, Stefan Haberland, Jan Hoeppner,
	Heiko Carstens, Vasily Gorbik, Alexander Gordeev,
	Christian Borntraeger, Sven Schnelle, Satish Kharat,
	Sesidhar Baddela, James E.J. Bottomley, Mauro Carvalho Chehab,
	Greg Kroah-Hartman, Xiubo Li, Ilya Dryomov, Masami Hiramatsu,
	Mathieu Desnoyers, Andrew Morton
In-Reply-To: <20251111122735.880607-2-andriy.shevchenko@linux.intel.com>

On Tue 2025-11-11 13:20:01, Andy Shevchenko wrote:
> A handful drivers want to print a content of the struct timespec64
> in a format of %lld:%09ld. In order to make their lives easier, add
> the respecting specifier directly to the printf() implementation.
> 
> Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> ---
>  Documentation/core-api/printk-formats.rst | 11 ++++++++--
>  lib/tests/printf_kunit.c                  |  4 ++++
>  lib/vsprintf.c                            | 25 +++++++++++++++++++++++
>  3 files changed, 38 insertions(+), 2 deletions(-)
> 
> diff --git a/Documentation/core-api/printk-formats.rst b/Documentation/core-api/printk-formats.rst
> index 7f2f11b48286..c0b1b6089307 100644
> --- a/Documentation/core-api/printk-formats.rst
> +++ b/Documentation/core-api/printk-formats.rst
> @@ -547,11 +547,13 @@ Time and date
>  	%pt[RT]s		YYYY-mm-dd HH:MM:SS
>  	%pt[RT]d		YYYY-mm-dd
>  	%pt[RT]t		HH:MM:SS
> -	%pt[RT][dt][r][s]
> +	%ptSp			<seconds>.<nanoseconds>

I know that that there was no good choice. But I am curious.
Does the 'p' stands for some particular word, for example, "plain" ?

I do not want to start bike shedding but I think about
using 'n' as "number".

> +	%pt[RST][dt][r][s]
>  
>  For printing date and time as represented by::
>  
> -	R  struct rtc_time structure
> +	R  content of struct rtc_time
> +	S  content of struct timespec64
>  	T  time64_t type
>  
>  in human readable format.
> @@ -563,6 +565,11 @@ The %pt[RT]s (space) will override ISO 8601 separator by using ' ' (space)
>  instead of 'T' (Capital T) between date and time. It won't have any effect
>  when date or time is omitted.
>  
> +The %ptSp is equivalent to %lld.%09ld for the content of the struct timespec64.
> +When the other specifiers are given, it becomes the respective equivalent of
> +%ptT[dt][r][s].%09ld. In other words, the seconds are being printed in
> +the human readable format followed by a dot and nanoseconds.
> +
>  Passed by reference.
>  
>  struct clk
> diff --git a/lib/vsprintf.c b/lib/vsprintf.c
> index 3f99834fd788..fdd06e8957a3 100644
> --- a/lib/vsprintf.c
> +++ b/lib/vsprintf.c
> @@ -2464,6 +2488,7 @@ early_param("no_hash_pointers", no_hash_pointers_enable);
>   * - 'g' For block_device name (gendisk + partition number)
>   * - 't[RT][dt][r][s]' For time and date as represented by:

We should add 'S' here as well:

   * - 't[RST][dt][r][s]' For time and date as represented by:

That said, I am not sure about the optional '[p]'. We could
either do:

   * - 't[RST][p][dt][r][s]' For time and date as represented by:

or

   * - 'tSp'	For time represented by struct timespec64 printed
		as seconds.nanoseconds
   * - 't[RST][dt][r][s]' For time and date as represented by:

>   *      R    struct rtc_time
> + *      S    struct timespec64
>   *      T    time64_t
>   * - 'C' For a clock, it prints the name (Common Clock Framework) or address
>   *       (legacy clock framework) of the clock

Otherwise, it looks good.

Best Regards,
Petr

^ permalink raw reply

* Re: [PATCH] trace/pid_list: optimize pid_list->lock contention
From: Steven Rostedt @ 2025-11-11 15:27 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: Yongliang Gao, mhiramat, mathieu.desnoyers, linux-kernel,
	linux-trace-kernel, Yongliang Gao, Huang Cun
In-Reply-To: <20251111081314.j8CFfAD6@linutronix.de>

On Tue, 11 Nov 2025 09:13:14 +0100
Sebastian Andrzej Siewior <bigeasy@linutronix.de> wrote:

> Nope, no read-write lock that can be used in atomic sections. Well,
> there is RCU.

Well, it can't simply be replaced by RCU as the write side is also a
critical path. It happens when new tasks are spawned.

Now we could possibly do some RCU like magic, and remove the lock in the
read, but it would need some care with the writes.

Something like this (untested):

bool trace_pid_list_is_set(struct trace_pid_list *pid_list, unsigned int pid)
{
	union upper_chunk *upper_chunk;
	union lower_chunk *lower_chunk;
	unsigned long flags;
	unsigned int upper1;
	unsigned int upper2;
	unsigned int lower;
	bool ret = false;

	if (!pid_list)
		return false;

	if (pid_split(pid, &upper1, &upper2, &lower) < 0)
		return false;

	upper_chunk = READ_ONCE(pid_list->upper[upper1]);
	if (upper_chunk) {
		lower_chunk = READ_ONCE(upper_chunk->data[upper2]);
		if (lower_chunk)
			ret = test_bit(lower, lower_chunk->data);
	}

	return ret;
}

Now when all the bits of a chunk is cleared, it goes to a free-list. And
when a new chunk is needed, it acquires it from that free-list. We need to
make sure that the chunk acquired in the read hasn't gone through the
free-list.

Now we could have an atomic counter in the pid_list and make this more of a
seqcount? That is, have the counter updated when a chunk goes to the free
list and also when it is taken from the free list. We could then make this:

 again:
	counter = atomic_read(&pid_list->counter);
	smp_rmb();
	upper_chunk = READ_ONCE(pid_list->upper[upper1]);
	if (upper_chunk) {
		lower_chunk = READ_ONCE(upper_chunk->data[upper2]);
		if (lower_chunk) {
			ret = test_bit(lower, lower_chunk->data);
			smp_rmb();
			if (unlikely(counter != atomic_read(&pid_list->counter))) {
				ret = false;
				goto again;
			}
		}
	}


And in the set we need:

	upper_chunk = pid_list->upper[upper1];
	if (!upper_chunk) {
		upper_chunk = get_upper_chunk(pid_list);
		if (!upper_chunk) {
			ret = -ENOMEM;
			goto out;
		}
		atomic_inc(&pid_list->counter);
		smp_wmb();
		WRITE_ONCE(pid_list->upper[upper1], upper_chunk);
	}
	lower_chunk = upper_chunk->data[upper2];
	if (!lower_chunk) {
		lower_chunk = get_lower_chunk(pid_list);
		if (!lower_chunk) {
			ret = -ENOMEM;
			goto out;
		}
		atomic_inc(&pid_list->counter);
		smp_wmb();
		WRITE_ONCE(upper_chunk->data[upper2], lower_chunk);
	}

and in the clear:

	if (find_first_bit(lower_chunk->data, LOWER_MAX) >= LOWER_MAX) {
		put_lower_chunk(pid_list, lower_chunk);
		WRITE_ONCE(upper_chunk->data[upper2], NULL);
		smp_wmb();
		atomic_inc(&pid_list->counter);
		if (upper_empty(upper_chunk)) {
			put_upper_chunk(pid_list, upper_chunk);
			WRITE_ONCE(pid_list->upper[upper1], NULL);
			smp_wmb();
			atomic_inc(&pid_list->counter);
		}
	}

That is, the counter gets updated after setting the chunk to NULL and
before assigning it a new value. And reading it, the counter is read before
looking at any of the chunks, and tested after getting the result. If the
value is the same, then the chunks are for the correct PID and haven't
swapped in a free/alloc swap where it's looking at a chunk for a different
PID.

This would allow for the read to not take any locks.

-- Steve

^ permalink raw reply

* [syzbot] [block?] [trace?] INFO: task hung in blk_trace_startstop
From: syzbot @ 2025-11-11 16:43 UTC (permalink / raw)
  To: axboe, linux-block, linux-kernel, linux-trace-kernel,
	mathieu.desnoyers, mhiramat, rostedt, syzkaller-bugs

Hello,

syzbot found the following issue on:

HEAD commit:    4a0c9b339199 Merge tag 'probes-fixes-v6.18-rc4' of git://g..
git tree:       upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=12323812580000
kernel config:  https://syzkaller.appspot.com/x/.config?x=e46b8a1c645465a9
dashboard link: https://syzkaller.appspot.com/bug?extid=774863666ef5b025c9d0
compiler:       Debian clang version 20.1.8 (++20250708063551+0c9f909b7976-1~exp1~20250708183702.136), Debian LLD 20.1.8

Unfortunately, I don't have any reproducer for this issue yet.

Downloadable assets:
disk image: https://storage.googleapis.com/syzbot-assets/2d880d82a810/disk-4a0c9b33.raw.xz
vmlinux: https://storage.googleapis.com/syzbot-assets/75307faea32a/vmlinux-4a0c9b33.xz
kernel image: https://storage.googleapis.com/syzbot-assets/9d3f4c38a2eb/bzImage-4a0c9b33.xz

IMPORTANT: if you fix the issue, please add the following tag to the commit:
Reported-by: syzbot+774863666ef5b025c9d0@syzkaller.appspotmail.com

INFO: task syz.6.3379:19656 blocked for more than 143 seconds.
      Not tainted syzkaller #0
"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
task:syz.6.3379      state:D stack:28776 pid:19656 tgid:19654 ppid:16553  task_flags:0x400040 flags:0x00080002
Call Trace:
 <TASK>
 context_switch kernel/sched/core.c:5325 [inline]
 __schedule+0x1798/0x4cc0 kernel/sched/core.c:6929
 __schedule_loop kernel/sched/core.c:7011 [inline]
 schedule+0x165/0x360 kernel/sched/core.c:7026
 schedule_preempt_disabled+0x13/0x30 kernel/sched/core.c:7083
 __mutex_lock_common kernel/locking/mutex.c:676 [inline]
 __mutex_lock+0x7e6/0x1350 kernel/locking/mutex.c:760
 blk_trace_startstop+0xa3/0x640 kernel/trace/blktrace.c:682
 blk_trace_ioctl+0x19b/0x430 kernel/trace/blktrace.c:724
 blkdev_common_ioctl+0xdf4/0x2550 block/ioctl.c:630
 blkdev_ioctl+0x4f6/0x6d0 block/ioctl.c:699
 vfs_ioctl fs/ioctl.c:51 [inline]
 __do_sys_ioctl fs/ioctl.c:597 [inline]
 __se_sys_ioctl+0xfc/0x170 fs/ioctl.c:583
 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
 do_syscall_64+0xfa/0xfa0 arch/x86/entry/syscall_64.c:94
 entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7fbcfcb8f6c9
RSP: 002b:00007fbcfdaa3038 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
RAX: ffffffffffffffda RBX: 00007fbcfcde6090 RCX: 00007fbcfcb8f6c9
RDX: 0000000000000000 RSI: 0000000000001275 RDI: 0000000000000003
RBP: 00007fbcfcc11f91 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
R13: 00007fbcfcde6128 R14: 00007fbcfcde6090 R15: 00007fbcfcf0fa28
 </TASK>

Showing all locks held in the system:
1 lock held by khungtaskd/31:
 #0: ffffffff8df3d660 (rcu_read_lock){....}-{1:3}, at: rcu_lock_acquire include/linux/rcupdate.h:331 [inline]
 #0: ffffffff8df3d660 (rcu_read_lock){....}-{1:3}, at: rcu_read_lock include/linux/rcupdate.h:867 [inline]
 #0: ffffffff8df3d660 (rcu_read_lock){....}-{1:3}, at: debug_show_all_locks+0x2e/0x180 kernel/locking/lockdep.c:6775
2 locks held by getty/5588:
 #0: ffff888032fa10a0 (&tty->ldisc_sem){++++}-{0:0}, at: tty_ldisc_ref_wait+0x25/0x70 drivers/tty/tty_ldisc.c:243
 #1: ffffc9000332b2f0 (&ldata->atomic_read_lock){+.+.}-{4:4}, at: n_tty_read+0x43e/0x1400 drivers/tty/n_tty.c:2222
3 locks held by syz.6.3379/19655:
1 lock held by syz.6.3379/19656:
 #0: ffff888142f2b068 (&q->debugfs_mutex){+.+.}-{4:4}, at: blk_trace_startstop+0xa3/0x640 kernel/trace/blktrace.c:682

=============================================

NMI backtrace for cpu 0
CPU: 0 UID: 0 PID: 31 Comm: khungtaskd Not tainted syzkaller #0 PREEMPT(full) 
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/02/2025
Call Trace:
 <TASK>
 dump_stack_lvl+0x189/0x250 lib/dump_stack.c:120
 nmi_cpu_backtrace+0x39e/0x3d0 lib/nmi_backtrace.c:113
 nmi_trigger_cpumask_backtrace+0x17a/0x300 lib/nmi_backtrace.c:62
 trigger_all_cpu_backtrace include/linux/nmi.h:160 [inline]
 check_hung_uninterruptible_tasks kernel/hung_task.c:332 [inline]
 watchdog+0xf60/0xfa0 kernel/hung_task.c:495
 kthread+0x711/0x8a0 kernel/kthread.c:463
 ret_from_fork+0x4bc/0x870 arch/x86/kernel/process.c:158
 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
 </TASK>
Sending NMI from CPU 0 to CPUs 1:
NMI backtrace for cpu 1
CPU: 1 UID: 0 PID: 19655 Comm: syz.6.3379 Not tainted syzkaller #0 PREEMPT(full) 
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/02/2025
RIP: 0010:unwind_get_return_address+0x4d/0x90 arch/x86/kernel/unwind_orc.c:369
Code: c0 75 4c 83 3b 00 74 3a 48 83 c3 48 49 89 df 49 c1 ef 03 43 80 3c 37 00 74 08 48 89 df e8 4b 30 b2 00 48 8b 3b e8 b3 cf 18 00 <85> c0 74 14 43 80 3c 37 00 74 08 48 89 df e8 30 30 b2 00 48 8b 03
RSP: 0018:ffffc9000b257668 EFLAGS: 00000202
RAX: 0000000000000001 RBX: ffffc9000b2576d0 RCX: 6861806b914a4f00
RDX: 0000000000000001 RSI: ffffffff8d8f46a3 RDI: ffffffff846da7ad
RBP: ffffc9000b257710 R08: ffffc9000b257dd0 R09: 0000000000000000
R10: ffffc9000b2576d8 R11: fffff5200164aedd R12: ffff888066a03c80
R13: 1ffff9200164aefc R14: dffffc0000000000 R15: 1ffff9200164aeda
FS:  00007fbcfdac46c0(0000) GS:ffff88812623b000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007f184bdb3ad8 CR3: 0000000043d28000 CR4: 00000000003526f0
Call Trace:
 <TASK>
 arch_stack_walk+0xfc/0x150 arch/x86/kernel/stacktrace.c:26
 stack_trace_save+0x9c/0xe0 kernel/stacktrace.c:122
 save_stack+0xf5/0x1f0 mm/page_owner.c:156
 __reset_page_owner+0x71/0x1f0 mm/page_owner.c:311
 reset_page_owner include/linux/page_owner.h:25 [inline]
 free_pages_prepare mm/page_alloc.c:1394 [inline]
 __free_frozen_pages+0xbc4/0xd30 mm/page_alloc.c:2906
 relay_destroy_buf+0x10e/0x3a0 kernel/relay.c:200
 relay_remove_buf kernel/relay.c:220 [inline]
 kref_put include/linux/kref.h:65 [inline]
 relay_close_buf kernel/relay.c:435 [inline]
 relay_open+0x734/0x920 kernel/relay.c:531
 do_blk_trace_setup+0x561/0x980 kernel/trace/blktrace.c:572
 blk_trace_setup+0x116/0x1f0 kernel/trace/blktrace.c:614
 blk_trace_ioctl+0x181/0x430 kernel/trace/blktrace.c:712
 blkdev_ioctl+0x41d/0x6d0 block/ioctl.c:694
 vfs_ioctl fs/ioctl.c:51 [inline]
 __do_sys_ioctl fs/ioctl.c:597 [inline]
 __se_sys_ioctl+0xfc/0x170 fs/ioctl.c:583
 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
 do_syscall_64+0xfa/0xfa0 arch/x86/entry/syscall_64.c:94
 entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7fbcfcb8f6c9
Code: ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 a8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007fbcfdac4038 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
RAX: ffffffffffffffda RBX: 00007fbcfcde5fa0 RCX: 00007fbcfcb8f6c9
RDX: 00002000000000c0 RSI: 00000000c0481273 RDI: 0000000000000003
RBP: 00007fbcfcc11f91 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
R13: 00007fbcfcde6038 R14: 00007fbcfcde5fa0 R15: 00007fbcfcf0fa28
 </TASK>


---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller@googlegroups.com.

syzbot will keep track of this issue. See:
https://goo.gl/tpsmEJ#status for how to communicate with syzbot.

If the report is already addressed, let syzbot know by replying with:
#syz fix: exact-commit-title

If you want to overwrite report's subsystems, reply with:
#syz set subsystems: new-subsystem
(See the list of subsystem names on the web dashboard)

If the report is a duplicate of another one, reply with:
#syz dup: exact-subject-of-another-report

If you want to undo deduplication, reply with:
#syz undup

^ permalink raw reply

* [syzbot] [trace?] WARNING in tracing_buffers_mmap_close (2)
From: syzbot @ 2025-11-11 17:05 UTC (permalink / raw)
  To: linux-kernel, linux-trace-kernel, mathieu.desnoyers, mhiramat,
	rostedt, syzkaller-bugs

Hello,

syzbot found the following issue on:

HEAD commit:    4a0c9b339199 Merge tag 'probes-fixes-v6.18-rc4' of git://g..
git tree:       upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=127c3bcd980000
kernel config:  https://syzkaller.appspot.com/x/.config?x=19d831c6d0386a9c
dashboard link: https://syzkaller.appspot.com/bug?extid=a72c325b042aae6403c7
compiler:       gcc (Debian 12.2.0-14+deb12u1) 12.2.0, GNU ld (GNU Binutils for Debian) 2.40
syz repro:      https://syzkaller.appspot.com/x/repro.syz?x=13fb5342580000
C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=167c3bcd980000

Downloadable assets:
disk image: https://storage.googleapis.com/syzbot-assets/0885fd14dc45/disk-4a0c9b33.raw.xz
vmlinux: https://storage.googleapis.com/syzbot-assets/d090edb8df65/vmlinux-4a0c9b33.xz
kernel image: https://storage.googleapis.com/syzbot-assets/fe620e34d128/bzImage-4a0c9b33.xz

IMPORTANT: if you fix the issue, please add the following tag to the commit:
Reported-by: syzbot+a72c325b042aae6403c7@syzkaller.appspotmail.com

------------[ cut here ]------------
WARNING: CPU: 0 PID: 5989 at kernel/trace/trace.c:8780 tracing_buffers_mmap_close kernel/trace/trace.c:8780 [inline]
WARNING: CPU: 0 PID: 5989 at kernel/trace/trace.c:8780 tracing_buffers_mmap_close+0xdd/0x130 kernel/trace/trace.c:8775
Modules linked in:
CPU: 0 UID: 0 PID: 5989 Comm: syz.0.17 Not tainted syzkaller #0 PREEMPT(full) 
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/02/2025
RIP: 0010:tracing_buffers_mmap_close kernel/trace/trace.c:8780 [inline]
RIP: 0010:tracing_buffers_mmap_close+0xdd/0x130 kernel/trace/trace.c:8775
Code: 75 46 48 8b 7b 08 e8 b2 94 ff ff 31 ff 89 c3 89 c6 e8 07 4b fb ff 85 db 75 0a 48 83 c4 08 5b e9 b9 4f fb ff e8 b4 4f fb ff 90 <0f> 0b 90 48 83 c4 08 5b e9 a6 4f fb ff e8 b1 e6 62 00 eb 87 e8 da
RSP: 0018:ffffc90003047ba8 EFLAGS: 00010293
RAX: 0000000000000000 RBX: 00000000ffffffed RCX: ffffffff81c11d89
RDX: ffff888020713c80 RSI: ffffffff81c11d9c RDI: 0000000000000005
RBP: ffffffff81c11cc0 R08: 0000000000000005 R09: 0000000000000000
R10: 00000000ffffffed R11: 0000000000000000 R12: ffff8880217512c8
R13: dffffc0000000000 R14: ffffc90003047c30 R15: 0000000000000000
FS:  0000000000000000(0000) GS:ffff888124a0d000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00005555606ff808 CR3: 000000000e182000 CR4: 00000000003526f0
Call Trace:
 <TASK>
 vma_close mm/internal.h:190 [inline]
 remove_vma+0x88/0x160 mm/vma.c:464
 exit_mmap+0x50a/0xb90 mm/mmap.c:1305
 __mmput+0x12a/0x410 kernel/fork.c:1133
 mmput+0x62/0x70 kernel/fork.c:1156
 exit_mm kernel/exit.c:582 [inline]
 do_exit+0x7c7/0x2bf0 kernel/exit.c:954
 do_group_exit+0xd3/0x2a0 kernel/exit.c:1107
 __do_sys_exit_group kernel/exit.c:1118 [inline]
 __se_sys_exit_group kernel/exit.c:1116 [inline]
 __x64_sys_exit_group+0x3e/0x50 kernel/exit.c:1116
 x64_sys_call+0x150b/0x1730 arch/x86/include/generated/asm/syscalls_64.h:232
 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
 do_syscall_64+0xcd/0xfa0 arch/x86/entry/syscall_64.c:94
 entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f168a18f6c9
Code: Unable to access opcode bytes at 0x7f168a18f69f.
RSP: 002b:00007ffff8c604f8 EFLAGS: 00000246 ORIG_RAX: 00000000000000e7
RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f168a18f6c9
RDX: 0000000000000064 RSI: 0000000000000000 RDI: 0000000000000000
RBP: 0000000000000003 R08: 00000004f8c605ef R09: 00007f168a3b1280
R10: 0000000000000001 R11: 0000000000000246 R12: 0000000000000000
R13: 00007f168a3b1280 R14: 0000000000000003 R15: 00007ffff8c605b0
 </TASK>


---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller@googlegroups.com.

syzbot will keep track of this issue. See:
https://goo.gl/tpsmEJ#status for how to communicate with syzbot.

If the report is already addressed, let syzbot know by replying with:
#syz fix: exact-commit-title

If you want syzbot to run the reproducer, reply with:
#syz test: git://repo/address.git branch-or-commit-hash
If you attach or paste a git patch, syzbot will apply it before testing.

If you want to overwrite report's subsystems, reply with:
#syz set subsystems: new-subsystem
(See the list of subsystem names on the web dashboard)

If the report is a duplicate of another one, reply with:
#syz dup: exact-subject-of-another-report

If you want to undo deduplication, reply with:
#syz undup

^ permalink raw reply

* Re: [PATCH v12 mm-new 12/15] khugepaged: Introduce mTHP collapse support
From: Nico Pache @ 2025-11-11 21:56 UTC (permalink / raw)
  To: Wei Yang
  Cc: linux-kernel, linux-trace-kernel, linux-mm, linux-doc, david, ziy,
	baolin.wang, lorenzo.stoakes, Liam.Howlett, ryan.roberts,
	dev.jain, corbet, rostedt, mhiramat, mathieu.desnoyers, akpm,
	baohua, willy, peterx, wangkefeng.wang, usamaarif642, sunnanyong,
	vishal.moola, thomas.hellstrom, yang, kas, aarcange, raquini,
	anshuman.khandual, catalin.marinas, tiwai, will, dave.hansen,
	jack, cl, jglisse, surenb, zokeefe, hannes, rientjes, mhocko,
	rdunlap, hughd, lance.yang, vbabka, rppt, jannh, pfalcato
In-Reply-To: <20251109020802.g6dytbixd4aygdgh@master>

On Sat, Nov 8, 2025 at 7:08 PM Wei Yang <richard.weiyang@gmail.com> wrote:
>
> On Wed, Oct 22, 2025 at 12:37:14PM -0600, Nico Pache wrote:
> >During PMD range scanning, track occupied pages in a bitmap. If mTHPs are
> >enabled we remove the restriction of max_ptes_none during the scan phase
> >to avoid missing potential mTHP candidates.
> >
> >Implement collapse_scan_bitmap() to perform binary recursion on the bitmap
> >and determine the best eligible order for the collapse. A stack struct is
> >used instead of traditional recursion. The algorithm splits the bitmap
> >into smaller chunks to find the best fit mTHP.  max_ptes_none is scaled by
> >the attempted collapse order to determine how "full" an order must be
> >before being considered for collapse.
> >
> >Once we determine what mTHP sizes fits best in that PMD range a collapse
> >is attempted. A minimum collapse order of 2 is used as this is the lowest
> >order supported by anon memory.
> >
> >mTHP collapses reject regions containing swapped out or shared pages.
> >This is because adding new entries can lead to new none pages, and these
> >may lead to constant promotion into a higher order (m)THP. A similar
> >issue can occur with "max_ptes_none > HPAGE_PMD_NR/2" due to a collapse
> >introducing at least 2x the number of pages, and on a future scan will
> >satisfy the promotion condition once again. This issue is prevented via
> >the collapse_allowable_orders() function.
> >
> >Currently madv_collapse is not supported and will only attempt PMD
> >collapse.
> >
> >We can also remove the check for is_khugepaged inside the PMD scan as
> >the collapse_max_ptes_none() function handles this logic now.
> >
> >Signed-off-by: Nico Pache <npache@redhat.com>
>
> Generally LGTM.
>
> Some nit below.
>
> >---
> > include/linux/khugepaged.h |   2 +
> > mm/khugepaged.c            | 128 ++++++++++++++++++++++++++++++++++---
> > 2 files changed, 122 insertions(+), 8 deletions(-)
> >
> >diff --git a/include/linux/khugepaged.h b/include/linux/khugepaged.h
> >index eb1946a70cff..179ce716e769 100644
> >--- a/include/linux/khugepaged.h
> >+++ b/include/linux/khugepaged.h
> >@@ -1,6 +1,8 @@
> > /* SPDX-License-Identifier: GPL-2.0 */
> > #ifndef _LINUX_KHUGEPAGED_H
> > #define _LINUX_KHUGEPAGED_H
> >+#define KHUGEPAGED_MIN_MTHP_ORDER     2
> >+#define MAX_MTHP_BITMAP_STACK (1UL << (ilog2(MAX_PTRS_PER_PTE) - KHUGEPAGED_MIN_MTHP_ORDER))
> >
> > #include <linux/mm.h>
> >
> >diff --git a/mm/khugepaged.c b/mm/khugepaged.c
> >index 89a105124790..e2319bfd0065 100644
> >--- a/mm/khugepaged.c
> >+++ b/mm/khugepaged.c
> >@@ -93,6 +93,11 @@ static DEFINE_READ_MOSTLY_HASHTABLE(mm_slots_hash, MM_SLOTS_HASH_BITS);
> >
> > static struct kmem_cache *mm_slot_cache __ro_after_init;
> >
> >+struct scan_bit_state {
> >+      u8 order;
> >+      u16 offset;
> >+};
> >+
> > struct collapse_control {
> >       bool is_khugepaged;
> >
> >@@ -101,6 +106,13 @@ struct collapse_control {
> >
> >       /* nodemask for allocation fallback */
> >       nodemask_t alloc_nmask;
> >+
> >+      /*
> >+       * bitmap used to collapse mTHP sizes.
> >+       */
> >+       DECLARE_BITMAP(mthp_bitmap, HPAGE_PMD_NR);
> >+       DECLARE_BITMAP(mthp_bitmap_mask, HPAGE_PMD_NR);
> >+      struct scan_bit_state mthp_bitmap_stack[MAX_MTHP_BITMAP_STACK];
>
> Looks like an indent issue.

Thanks!
>
> > };
> >
> > /**
> >@@ -1357,6 +1369,85 @@ static int collapse_huge_page(struct mm_struct *mm, unsigned long pmd_address,
> >       return result;
> > }
> >
> >+static void push_mthp_bitmap_stack(struct collapse_control *cc, int *top,
> >+                                 u8 order, u16 offset)
> >+{
> >+      cc->mthp_bitmap_stack[++*top] = (struct scan_bit_state)
> >+              { order, offset };
> >+}
> >+
>
> For me, I may introduce pop_mth_bitmap_stack() .
>
> And use it ...
>
> >+/*
> >+ * collapse_scan_bitmap() consumes the bitmap that is generated during
> >+ * collapse_scan_pmd() to determine what regions and mTHP orders fit best.
> >+ *
> >+ * Each bit in the bitmap represents a single occupied (!none/zero) page.
> >+ * A stack structure cc->mthp_bitmap_stack is used to check different regions
> >+ * of the bitmap for collapse eligibility. We start at the PMD order and
> >+ * check if it is eligible for collapse; if not, we add two entries to the
> >+ * stack at a lower order to represent the left and right halves of the region.
> >+ *
> >+ * For each region, we calculate the number of set bits and compare it
> >+ * against a threshold derived from collapse_max_ptes_none(). A region is
> >+ * eligible if the number of set bits exceeds this threshold.
> >+ */
> >+static int collapse_scan_bitmap(struct mm_struct *mm, unsigned long address,
> >+              int referenced, int unmapped, struct collapse_control *cc,
> >+              bool *mmap_locked, unsigned long enabled_orders)
> >+{
> >+      u8 order, next_order;
> >+      u16 offset, mid_offset;
> >+      int num_chunks;
> >+      int bits_set, threshold_bits;
> >+      int top = -1;
> >+      int collapsed = 0;
> >+      int ret;
> >+      struct scan_bit_state state;
> >+      unsigned int max_none_ptes;
> >+
> >+      push_mthp_bitmap_stack(cc, &top, HPAGE_PMD_ORDER - KHUGEPAGED_MIN_MTHP_ORDER, 0);
> >+
> >+      while (top >= 0) {
> >+              state = cc->mthp_bitmap_stack[top--];
>
> ... here.

Ack!

>
> >+              order = state.order + KHUGEPAGED_MIN_MTHP_ORDER;
>
> We push real_order - KHUGEPAGED_MIN_MTHP_ORDER, and get it by add
> KHUGEPAGED_MIN_MTHP_ORDER.
>
> Maybe we can push real_order ...
>
> >+              offset = state.offset;
> >+              num_chunks = 1UL << order;
> >+
> >+              /* Skip mTHP orders that are not enabled */
> >+              if (!test_bit(order, &enabled_orders))
> >+                      goto next_order;
> >+
> >+              max_none_ptes = collapse_max_ptes_none(order, !cc->is_khugepaged);
> >+
> >+              /* Calculate weight of the range */
> >+              bitmap_zero(cc->mthp_bitmap_mask, HPAGE_PMD_NR);
> >+              bitmap_set(cc->mthp_bitmap_mask, offset, num_chunks);
> >+              bits_set = bitmap_weight_and(cc->mthp_bitmap,
> >+                                           cc->mthp_bitmap_mask, HPAGE_PMD_NR);
> >+
> >+              threshold_bits = (1UL << order) - max_none_ptes - 1;
> >+
> >+              /* Check if the region is eligible based on the threshold */
> >+              if (bits_set > threshold_bits) {
> >+                      ret = collapse_huge_page(mm, address, referenced,
> >+                                               unmapped, cc, mmap_locked,
> >+                                               order, offset);
> >+                      if (ret == SCAN_SUCCEED) {
> >+                              collapsed += 1UL << order;
> >+                              continue;
> >+                      }
> >+              }
> >+
> >+next_order:
> >+              if (state.order > 0) {
>
> ...and if (order > KHUGEPAGED_MIN_MTHP_ORDER) here?
>
> Not sure you would like it.

I went ahead and implemented this based on real order. Thanks for the
suggestion, it's much cleaner now. It made more sense like this when I
had the bitmap compressed into 128 bits.

>
> >+                      next_order = state.order - 1;
> >+                      mid_offset = offset + (num_chunks / 2);
> >+                      push_mthp_bitmap_stack(cc, &top, next_order, mid_offset);
> >+                      push_mthp_bitmap_stack(cc, &top, next_order, offset);
> >+              }
> >+      }
> >+      return collapsed;
> >+}
> >+
> > static int collapse_scan_pmd(struct mm_struct *mm,
> >                            struct vm_area_struct *vma,
> >                            unsigned long start_addr, bool *mmap_locked,
> >@@ -1364,11 +1455,15 @@ static int collapse_scan_pmd(struct mm_struct *mm,
> > {
> >       pmd_t *pmd;
> >       pte_t *pte, *_pte;
> >+      int i;
> >       int result = SCAN_FAIL, referenced = 0;
> >-      int none_or_zero = 0, shared = 0;
> >+      int none_or_zero = 0, shared = 0, nr_collapsed = 0;
> >       struct page *page = NULL;
> >+      unsigned int max_ptes_none;
> >       struct folio *folio = NULL;
> >       unsigned long addr;
> >+      unsigned long enabled_orders;
> >+      bool full_scan = true;
> >       spinlock_t *ptl;
> >       int node = NUMA_NO_NODE, unmapped = 0;
> >
> >@@ -1378,16 +1473,29 @@ static int collapse_scan_pmd(struct mm_struct *mm,
> >       if (result != SCAN_SUCCEED)
> >               goto out;
> >
> >+      bitmap_zero(cc->mthp_bitmap, HPAGE_PMD_NR);
> >       memset(cc->node_load, 0, sizeof(cc->node_load));
> >       nodes_clear(cc->alloc_nmask);
> >+
> >+      enabled_orders = collapse_allowable_orders(vma, vma->vm_flags, cc->is_khugepaged);
> >+
> >+      /*
> >+       * If PMD is the only enabled order, enforce max_ptes_none, otherwise
> >+       * scan all pages to populate the bitmap for mTHP collapse.
> >+       */
> >+      if (cc->is_khugepaged && enabled_orders == _BITUL(HPAGE_PMD_ORDER))
>
> We sometimes use BIT(), e.g. in collapse_allowable_orders().
> And sometimes use _BITUL().
>
> Suggest to use the same form.

Yeah I caught this after posting, I missed this one!

>
> Nothing else, great job!

Thank you :) I appreciate the reviews!

>
> >+              full_scan = false;
> >+      max_ptes_none = collapse_max_ptes_none(HPAGE_PMD_ORDER, full_scan);
> >+
> >       pte = pte_offset_map_lock(mm, pmd, start_addr, &ptl);
> >       if (!pte) {
> >               result = SCAN_PMD_NULL;
> >               goto out;
> >       }
> >
> >-      for (addr = start_addr, _pte = pte; _pte < pte + HPAGE_PMD_NR;
> >-           _pte++, addr += PAGE_SIZE) {
> >+      for (i = 0; i < HPAGE_PMD_NR; i++) {
> >+              _pte = pte + i;
> >+              addr = start_addr + i * PAGE_SIZE;
> >               pte_t pteval = ptep_get(_pte);
> >               if (is_swap_pte(pteval)) {
> >                       ++unmapped;
> >@@ -1412,8 +1520,7 @@ static int collapse_scan_pmd(struct mm_struct *mm,
> >               if (pte_none_or_zero(pteval)) {
> >                       ++none_or_zero;
> >                       if (!userfaultfd_armed(vma) &&
> >-                          (!cc->is_khugepaged ||
> >-                           none_or_zero <= khugepaged_max_ptes_none)) {
> >+                          none_or_zero <= max_ptes_none) {
> >                               continue;
> >                       } else {
> >                               result = SCAN_EXCEED_NONE_PTE;
> >@@ -1461,6 +1568,8 @@ static int collapse_scan_pmd(struct mm_struct *mm,
> >                       }
> >               }
> >
> >+              /* Set bit for occupied pages */
> >+              bitmap_set(cc->mthp_bitmap, i, 1);
> >               /*
> >                * Record which node the original page is from and save this
> >                * information to cc->node_load[].
> >@@ -1517,9 +1626,12 @@ static int collapse_scan_pmd(struct mm_struct *mm,
> > out_unmap:
> >       pte_unmap_unlock(pte, ptl);
> >       if (result == SCAN_SUCCEED) {
> >-              result = collapse_huge_page(mm, start_addr, referenced,
> >-                                          unmapped, cc, mmap_locked,
> >-                                          HPAGE_PMD_ORDER, 0);
> >+              nr_collapsed = collapse_scan_bitmap(mm, start_addr, referenced, unmapped,
> >+                                            cc, mmap_locked, enabled_orders);
> >+              if (nr_collapsed > 0)
> >+                      result = SCAN_SUCCEED;
> >+              else
> >+                      result = SCAN_FAIL;
> >       }
> > out:
> >       trace_mm_khugepaged_scan_pmd(mm, folio, referenced,
> >--
> >2.51.0
>
> --
> Wei Yang
> Help you, Help me
>


^ permalink raw reply

* [PATCH v4 2/3] tracing: Have function tracer define options per instance
From: Steven Rostedt @ 2025-11-11 23:24 UTC (permalink / raw)
  To: linux-kernel, linux-trace-kernel
  Cc: Masami Hiramatsu, Mark Rutland, Mathieu Desnoyers, Andrew Morton
In-Reply-To: <20251111232406.183056289@kernel.org>

From: Steven Rostedt <rostedt@goodmis.org>

Currently the function tracer's options are saved via a global mask when
it should be per instance. Use the new infrastructure to define a
"default_flags" field in the tracer structure that is used for the top
level instance as well as new ones.

Currently the global mask causes confusion:

  # cd /sys/kernel/tracing
  # mkdir instances/foo
  # echo function > instances/foo/current_tracer
  # echo 1 > options/func-args
  # echo function > current_tracer
  # cat trace
[..]
  <idle>-0       [005] d..3.  1050.656187: rcu_needs_cpu() <-tick_nohz_next_event
  <idle>-0       [005] d..3.  1050.656188: get_next_timer_interrupt(basej=0x10002dbad, basem=0xf45fd7d300) <-tick_nohz_next_event
  <idle>-0       [005] d..3.  1050.656189: _raw_spin_lock(lock=0xffff8944bdf5de80) <-__get_next_timer_interrupt
  <idle>-0       [005] d..4.  1050.656190: do_raw_spin_lock(lock=0xffff8944bdf5de80) <-__get_next_timer_interrupt
  <idle>-0       [005] d..4.  1050.656191: _raw_spin_lock_nested(lock=0xffff8944bdf5f140, subclass=1) <-__get_next_timer_interrupt
 # cat instances/foo/options/func-args
 1
 # cat instances/foo/trace
[..]
  kworker/4:1-88      [004] ...1.   298.127735: next_zone <-refresh_cpu_vm_stats
  kworker/4:1-88      [004] ...1.   298.127736: first_online_pgdat <-refresh_cpu_vm_stats
  kworker/4:1-88      [004] ...1.   298.127738: next_online_pgdat <-refresh_cpu_vm_stats
  kworker/4:1-88      [004] ...1.   298.127739: fold_diff <-refresh_cpu_vm_stats
  kworker/4:1-88      [004] ...1.   298.127741: round_jiffies_relative <-vmstat_update
[..]

The above shows that updating the "func-args" option at the top level
instance also updates the "func-args" option in the instance but because
the update is only done by the instance that gets changed (as it should),
it's confusing to see that the option is already set in the other instance.

Fixes: f20a580627f43 ("ftrace: Allow instances to use function tracing")
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
---
 kernel/trace/trace_functions.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/kernel/trace/trace_functions.c b/kernel/trace/trace_functions.c
index d17c18934445..c12795c2fb39 100644
--- a/kernel/trace/trace_functions.c
+++ b/kernel/trace/trace_functions.c
@@ -154,11 +154,11 @@ static int function_trace_init(struct trace_array *tr)
 	if (!tr->ops)
 		return -ENOMEM;
 
-	func = select_trace_function(func_flags.val);
+	func = select_trace_function(tr->current_trace_flags->val);
 	if (!func)
 		return -EINVAL;
 
-	if (!handle_func_repeats(tr, func_flags.val))
+	if (!handle_func_repeats(tr, tr->current_trace_flags->val))
 		return -ENOMEM;
 
 	ftrace_init_array_ops(tr, func);
@@ -459,14 +459,14 @@ func_set_flag(struct trace_array *tr, u32 old_flags, u32 bit, int set)
 	u32 new_flags;
 
 	/* Do nothing if already set. */
-	if (!!set == !!(func_flags.val & bit))
+	if (!!set == !!(tr->current_trace_flags->val & bit))
 		return 0;
 
 	/* We can change this flag only when not running. */
 	if (tr->current_trace != &function_trace)
 		return 0;
 
-	new_flags = (func_flags.val & ~bit) | (set ? bit : 0);
+	new_flags = (tr->current_trace_flags->val & ~bit) | (set ? bit : 0);
 	func = select_trace_function(new_flags);
 	if (!func)
 		return -EINVAL;
@@ -491,7 +491,7 @@ static struct tracer function_trace __tracer_data =
 	.init		= function_trace_init,
 	.reset		= function_trace_reset,
 	.start		= function_trace_start,
-	.flags		= &func_flags,
+	.default_flags	= &func_flags,
 	.set_flag	= func_set_flag,
 	.allow_instances = true,
 #ifdef CONFIG_FTRACE_SELFTEST
-- 
2.51.0



^ permalink raw reply related

* [PATCH v4 0/3] tracing: Fix tracer options per instance
From: Steven Rostedt @ 2025-11-11 23:24 UTC (permalink / raw)
  To: linux-kernel, linux-trace-kernel
  Cc: Masami Hiramatsu, Mark Rutland, Mathieu Desnoyers, Andrew Morton

The tracers (like function and function_graph) have options that modify
how they behave or how they are shown in the trace file. As these options
were created before instances (multiple buffers), the flags variable that
represent these options were global for the tracer.

Now that a tracer may exist in multiple instances, having a global flags
that kinda affect every instance of that tracer does not make sense.
The reason it "kinda" affects them, is that the code that updates an option
for an instance, only does the change for the tracer running in that instance.
If a tracer is already running in another instance, it will not be affected.
But because the option is saved in a global variable, if the tracer is stopped
and restarted in the instance, then the option will take affect.

Since each instance has its own interface to modify the options, the effect
of an option should only affect the tracer for the given instance. This means
that the state of the options for each tracer must be saved for each instance
separately.

Add a new struct tracers field in the trace_array (instance descriptor) that
holds a descriptor that points to a tracer and contains its flags values. This
will be used to see what tracers are available for an instance.

Now when a tracer option is modified for an instance, it only affects the
tracer in that instance and not semi-effects the tracers in other instances.


Changes since v3: https://lore.kernel.org/linux-trace-kernel/20251110234157.808080361@kernel.org/

- Fix registering of command line tracers.
  A command line tracer is registered before the global array attaches
  itself to the list of instances. This keeps the tracer from attaching to
  the global array and that keeps the tracer from adding itself to the
  global array, and this means it fails to start at boot.

- Also add a warning if the starting of a boot tracer fails to start.

Steven Rostedt (3):
      tracing: Have tracer option be instance specific
      tracing: Have function tracer define options per instance
      tracing: Have function graph tracer define options per instance

----
 kernel/trace/trace.c                 | 257 +++++++++++++++++++++++++----------
 kernel/trace/trace.h                 |   3 +
 kernel/trace/trace_functions.c       |  10 +-
 kernel/trace/trace_functions_graph.c |  18 ++-
 4 files changed, 202 insertions(+), 86 deletions(-)

^ permalink raw reply

* [PATCH v4 1/3] tracing: Have tracer option be instance specific
From: Steven Rostedt @ 2025-11-11 23:24 UTC (permalink / raw)
  To: linux-kernel, linux-trace-kernel
  Cc: Masami Hiramatsu, Mark Rutland, Mathieu Desnoyers, Andrew Morton
In-Reply-To: <20251111232406.183056289@kernel.org>

From: Steven Rostedt <rostedt@goodmis.org>

Tracers can add specify options to modify them. This logic was added
before instances were created and the tracer flags were global variables.
After instances were created where a tracer may exist in more than one
instance, the flags were not updated from being global into instance
specific. This causes confusion with these options. For example, the
function tracer has an option to enable function arguments:

  # cd /sys/kernel/tracing
  # mkdir instances/foo
  # echo function > instances/foo/current_tracer
  # echo 1 > options/func-args
  # echo function > current_tracer
  # cat trace
[..]
  <idle>-0       [005] d..3.  1050.656187: rcu_needs_cpu() <-tick_nohz_next_event
  <idle>-0       [005] d..3.  1050.656188: get_next_timer_interrupt(basej=0x10002dbad, basem=0xf45fd7d300) <-tick_nohz_next_event
  <idle>-0       [005] d..3.  1050.656189: _raw_spin_lock(lock=0xffff8944bdf5de80) <-__get_next_timer_interrupt
  <idle>-0       [005] d..4.  1050.656190: do_raw_spin_lock(lock=0xffff8944bdf5de80) <-__get_next_timer_interrupt
  <idle>-0       [005] d..4.  1050.656191: _raw_spin_lock_nested(lock=0xffff8944bdf5f140, subclass=1) <-__get_next_timer_interrupt
 # cat instances/foo/options/func-args
 1
 # cat instances/foo/trace
[..]
  kworker/4:1-88      [004] ...1.   298.127735: next_zone <-refresh_cpu_vm_stats
  kworker/4:1-88      [004] ...1.   298.127736: first_online_pgdat <-refresh_cpu_vm_stats
  kworker/4:1-88      [004] ...1.   298.127738: next_online_pgdat <-refresh_cpu_vm_stats
  kworker/4:1-88      [004] ...1.   298.127739: fold_diff <-refresh_cpu_vm_stats
  kworker/4:1-88      [004] ...1.   298.127741: round_jiffies_relative <-vmstat_update
[..]

The above shows that setting "func-args" in the top level instance also
set it in the instance "foo", but since the interface of the trace flags
are per instance, the update didn't take affect in the "foo" instance.

Update the infrastructure to allow tracers to add a "default_flags" field
in the tracer structure that can be set instead of "flags" which will make
the flags per instance. If a tracer needs to keep the flags global (like
blktrace), keeping the "flags" field set will keep the old behavior.

This does not update function or the function graph tracers. That will be
handled later.

Fixes: f20a580627f43 ("ftrace: Allow instances to use function tracing")
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
---
Changes since v3: https://patch.msgid.link/20251110234341.767135255@kernel.org

- Fix registering of command line tracers.
  A command line tracer is registered before the global array attaches
  itself to the list of instances. This keeps the tracer from attaching to
  the global array and that keeps the tracer from adding itself to the
  global array, and this means it fails to start at boot.

- Also add a warning if the starting of a boot tracer fails to start.

 kernel/trace/trace.c | 257 ++++++++++++++++++++++++++++++-------------
 kernel/trace/trace.h |   3 +
 2 files changed, 186 insertions(+), 74 deletions(-)

diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 0aea9cb84276..9268489d2ce8 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -94,6 +94,13 @@ static bool tracepoint_printk_stop_on_boot __initdata;
 static bool traceoff_after_boot __initdata;
 static DEFINE_STATIC_KEY_FALSE(tracepoint_printk_key);
 
+/* Store tracers and their flags per instance */
+struct tracers {
+	struct list_head	list;
+	struct tracer		*tracer;
+	struct tracer_flags	*flags;
+};
+
 /*
  * To prevent the comm cache from being overwritten when no
  * tracing is active, only save the comm when a trace event
@@ -2164,6 +2171,7 @@ static int save_selftest(struct tracer *type)
 static int run_tracer_selftest(struct tracer *type)
 {
 	struct trace_array *tr = &global_trace;
+	struct tracer_flags *saved_flags = tr->current_trace_flags;
 	struct tracer *saved_tracer = tr->current_trace;
 	int ret;
 
@@ -2194,6 +2202,7 @@ static int run_tracer_selftest(struct tracer *type)
 	tracing_reset_online_cpus(&tr->array_buffer);
 
 	tr->current_trace = type;
+	tr->current_trace_flags = type->flags ? : type->default_flags;
 
 #ifdef CONFIG_TRACER_MAX_TRACE
 	if (type->use_max_tr) {
@@ -2210,6 +2219,7 @@ static int run_tracer_selftest(struct tracer *type)
 	ret = type->selftest(type, tr);
 	/* the test is responsible for resetting too */
 	tr->current_trace = saved_tracer;
+	tr->current_trace_flags = saved_flags;
 	if (ret) {
 		printk(KERN_CONT "FAILED!\n");
 		/* Add the warning after printing 'FAILED' */
@@ -2302,10 +2312,23 @@ static inline int do_run_tracer_selftest(struct tracer *type)
 }
 #endif /* CONFIG_FTRACE_STARTUP_TEST */
 
-static int add_tracer_options(struct trace_array *tr, struct tracer *t);
+static int add_tracer(struct trace_array *tr, struct tracer *t);
 
 static void __init apply_trace_boot_options(void);
 
+static void free_tracers(struct trace_array *tr)
+{
+	struct tracers *t, *n;
+
+	lockdep_assert_held(&trace_types_lock);
+
+	list_for_each_entry_safe(t, n, &tr->tracers, list) {
+		list_del(&t->list);
+		kfree(t->flags);
+		kfree(t);
+	}
+}
+
 /**
  * register_tracer - register a tracer with the ftrace system.
  * @type: the plugin for the tracer
@@ -2314,6 +2337,7 @@ static void __init apply_trace_boot_options(void);
  */
 int __init register_tracer(struct tracer *type)
 {
+	struct trace_array *tr;
 	struct tracer *t;
 	int ret = 0;
 
@@ -2353,10 +2377,13 @@ int __init register_tracer(struct tracer *type)
 	if (ret < 0)
 		goto out;
 
-	ret = add_tracer_options(&global_trace, type);
-	if (ret < 0) {
-		pr_warn("Failed to create tracer options for %s\n", type->name);
-		goto out;
+	list_for_each_entry(tr, &ftrace_trace_arrays, list) {
+		ret = add_tracer(tr, type);
+		if (ret < 0) {
+			/* The tracer will still exist but without options */
+			pr_warn("Failed to create tracer options for %s\n", type->name);
+			break;
+		}
 	}
 
 	type->next = trace_types;
@@ -2373,7 +2400,7 @@ int __init register_tracer(struct tracer *type)
 
 	printk(KERN_INFO "Starting tracer '%s'\n", type->name);
 	/* Do we want this tracer to start on bootup? */
-	tracing_set_tracer(&global_trace, type->name);
+	WARN_ON(tracing_set_tracer(&global_trace, type->name) < 0);
 	default_bootup_tracer = NULL;
 
 	apply_trace_boot_options();
@@ -5139,6 +5166,7 @@ static int tracing_trace_options_show(struct seq_file *m, void *v)
 {
 	struct tracer_opt *trace_opts;
 	struct trace_array *tr = m->private;
+	struct tracer_flags *flags;
 	struct tracer *trace;
 	u32 tracer_flags;
 	int i;
@@ -5152,12 +5180,14 @@ static int tracing_trace_options_show(struct seq_file *m, void *v)
 			seq_printf(m, "no%s\n", trace_options[i]);
 	}
 
-	trace = tr->current_trace;
-	if (!trace->flags || !trace->flags->opts)
+	flags = tr->current_trace_flags;
+	if (!flags || !flags->opts)
 		return 0;
 
-	tracer_flags = tr->current_trace->flags->val;
-	trace_opts = tr->current_trace->flags->opts;
+	trace = tr->current_trace;
+
+	tracer_flags = flags->val;
+	trace_opts = flags->opts;
 
 	for (i = 0; trace_opts[i].name; i++) {
 		if (tracer_flags & trace_opts[i].bit)
@@ -5191,8 +5221,7 @@ static int __set_tracer_option(struct trace_array *tr,
 /* Try to assign a tracer specific option */
 static int set_tracer_option(struct trace_array *tr, char *cmp, int neg)
 {
-	struct tracer *trace = tr->current_trace;
-	struct tracer_flags *tracer_flags = trace->flags;
+	struct tracer_flags *tracer_flags = tr->current_trace_flags;
 	struct tracer_opt *opts = NULL;
 	int i;
 
@@ -5203,7 +5232,7 @@ static int set_tracer_option(struct trace_array *tr, char *cmp, int neg)
 		opts = &tracer_flags->opts[i];
 
 		if (strcmp(cmp, opts->name) == 0)
-			return __set_tracer_option(tr, trace->flags, opts, neg);
+			return __set_tracer_option(tr, tracer_flags, opts, neg);
 	}
 
 	return -EINVAL;
@@ -6235,11 +6264,6 @@ int tracing_update_buffers(struct trace_array *tr)
 	return ret;
 }
 
-struct trace_option_dentry;
-
-static int
-create_trace_option_files(struct trace_array *tr, struct tracer *tracer);
-
 /*
  * Used to clear out the tracer before deletion of an instance.
  * Must have trace_types_lock held.
@@ -6255,26 +6279,15 @@ static void tracing_set_nop(struct trace_array *tr)
 		tr->current_trace->reset(tr);
 
 	tr->current_trace = &nop_trace;
+	tr->current_trace_flags = nop_trace.flags;
 }
 
 static bool tracer_options_updated;
 
-static int add_tracer_options(struct trace_array *tr, struct tracer *t)
-{
-	/* Only enable if the directory has been created already. */
-	if (!tr->dir && !(tr->flags & TRACE_ARRAY_FL_GLOBAL))
-		return 0;
-
-	/* Only create trace option files after update_tracer_options finish */
-	if (!tracer_options_updated)
-		return 0;
-
-	return create_trace_option_files(tr, t);
-}
-
 int tracing_set_tracer(struct trace_array *tr, const char *buf)
 {
-	struct tracer *t;
+	struct tracer *trace = NULL;
+	struct tracers *t;
 #ifdef CONFIG_TRACER_MAX_TRACE
 	bool had_max_tr;
 #endif
@@ -6292,18 +6305,20 @@ int tracing_set_tracer(struct trace_array *tr, const char *buf)
 		ret = 0;
 	}
 
-	for (t = trace_types; t; t = t->next) {
-		if (strcmp(t->name, buf) == 0)
+	list_for_each_entry(t, &tr->tracers, list) {
+		if (strcmp(t->tracer->name, buf) == 0) {
+			trace = t->tracer;
 			break;
+		}
 	}
-	if (!t)
+	if (!trace)
 		return -EINVAL;
 
-	if (t == tr->current_trace)
+	if (trace == tr->current_trace)
 		return 0;
 
 #ifdef CONFIG_TRACER_SNAPSHOT
-	if (t->use_max_tr) {
+	if (trace->use_max_tr) {
 		local_irq_disable();
 		arch_spin_lock(&tr->max_lock);
 		ret = tr->cond_snapshot ? -EBUSY : 0;
@@ -6314,14 +6329,14 @@ int tracing_set_tracer(struct trace_array *tr, const char *buf)
 	}
 #endif
 	/* Some tracers won't work on kernel command line */
-	if (system_state < SYSTEM_RUNNING && t->noboot) {
+	if (system_state < SYSTEM_RUNNING && trace->noboot) {
 		pr_warn("Tracer '%s' is not allowed on command line, ignored\n",
-			t->name);
+			trace->name);
 		return -EINVAL;
 	}
 
 	/* Some tracers are only allowed for the top level buffer */
-	if (!trace_ok_for_array(t, tr))
+	if (!trace_ok_for_array(trace, tr))
 		return -EINVAL;
 
 	/* If trace pipe files are being read, we can't change the tracer */
@@ -6340,8 +6355,9 @@ int tracing_set_tracer(struct trace_array *tr, const char *buf)
 
 	/* Current trace needs to be nop_trace before synchronize_rcu */
 	tr->current_trace = &nop_trace;
+	tr->current_trace_flags = nop_trace.flags;
 
-	if (had_max_tr && !t->use_max_tr) {
+	if (had_max_tr && !trace->use_max_tr) {
 		/*
 		 * We need to make sure that the update_max_tr sees that
 		 * current_trace changed to nop_trace to keep it from
@@ -6354,7 +6370,7 @@ int tracing_set_tracer(struct trace_array *tr, const char *buf)
 		tracing_disarm_snapshot(tr);
 	}
 
-	if (!had_max_tr && t->use_max_tr) {
+	if (!had_max_tr && trace->use_max_tr) {
 		ret = tracing_arm_snapshot_locked(tr);
 		if (ret)
 			return ret;
@@ -6363,18 +6379,21 @@ int tracing_set_tracer(struct trace_array *tr, const char *buf)
 	tr->current_trace = &nop_trace;
 #endif
 
-	if (t->init) {
-		ret = tracer_init(t, tr);
+	tr->current_trace_flags = t->flags ? : t->tracer->flags;
+
+	if (trace->init) {
+		ret = tracer_init(trace, tr);
 		if (ret) {
 #ifdef CONFIG_TRACER_MAX_TRACE
-			if (t->use_max_tr)
+			if (trace->use_max_tr)
 				tracing_disarm_snapshot(tr);
 #endif
+			tr->current_trace_flags = nop_trace.flags;
 			return ret;
 		}
 	}
 
-	tr->current_trace = t;
+	tr->current_trace = trace;
 	tr->current_trace->enabled++;
 	trace_branch_enable(tr);
 
@@ -9598,40 +9617,20 @@ create_trace_option_file(struct trace_array *tr,
 
 	topt->entry = trace_create_file(opt->name, TRACE_MODE_WRITE,
 					t_options, topt, &trace_options_fops);
-
 }
 
 static int
-create_trace_option_files(struct trace_array *tr, struct tracer *tracer)
+create_trace_option_files(struct trace_array *tr, struct tracer *tracer,
+			  struct tracer_flags *flags)
 {
 	struct trace_option_dentry *topts;
 	struct trace_options *tr_topts;
-	struct tracer_flags *flags;
 	struct tracer_opt *opts;
 	int cnt;
-	int i;
-
-	if (!tracer)
-		return 0;
-
-	flags = tracer->flags;
 
 	if (!flags || !flags->opts)
 		return 0;
 
-	/*
-	 * If this is an instance, only create flags for tracers
-	 * the instance may have.
-	 */
-	if (!trace_ok_for_array(tracer, tr))
-		return 0;
-
-	for (i = 0; i < tr->nr_topts; i++) {
-		/* Make sure there's no duplicate flags. */
-		if (WARN_ON_ONCE(tr->topts[i].tracer->flags == tracer->flags))
-			return -EINVAL;
-	}
-
 	opts = flags->opts;
 
 	for (cnt = 0; opts[cnt].name; cnt++)
@@ -9663,6 +9662,96 @@ create_trace_option_files(struct trace_array *tr, struct tracer *tracer)
 	return 0;
 }
 
+static int get_global_flags_val(struct tracer *tracer)
+{
+	struct tracers *t;
+
+	list_for_each_entry(t, &global_trace.tracers, list) {
+		if (t->tracer != tracer)
+			continue;
+		if (!t->flags)
+			return -1;
+		return t->flags->val;
+	}
+	return -1;
+}
+
+static int add_tracer_options(struct trace_array *tr, struct tracers *t)
+{
+	struct tracer *tracer = t->tracer;
+	struct tracer_flags *flags = t->flags ?: tracer->flags;
+
+	if (!flags)
+		return 0;
+
+	/* Only add tracer options after update_tracer_options finish */
+	if (!tracer_options_updated)
+		return 0;
+
+	return create_trace_option_files(tr, tracer, flags);
+}
+
+static int add_tracer(struct trace_array *tr, struct tracer *tracer)
+{
+	struct tracer_flags *flags;
+	struct tracers *t;
+	int ret;
+
+	/* Only enable if the directory has been created already. */
+	if (!tr->dir && !(tr->flags & TRACE_ARRAY_FL_GLOBAL))
+		return 0;
+
+	/*
+	 * If this is an instance, only create flags for tracers
+	 * the instance may have.
+	 */
+	if (!trace_ok_for_array(tracer, tr))
+		return 0;
+
+	t = kmalloc(sizeof(*t), GFP_KERNEL);
+	if (!t)
+		return -ENOMEM;
+
+	t->tracer = tracer;
+	t->flags = NULL;
+	list_add(&t->list, &tr->tracers);
+
+	flags = tracer->flags;
+	if (!flags) {
+		if (!tracer->default_flags)
+			return 0;
+
+		/*
+		 * If the tracer defines default flags, it means the flags are
+		 * per trace instance.
+		 */
+		flags = kmalloc(sizeof(*flags), GFP_KERNEL);
+		if (!flags)
+			return -ENOMEM;
+
+		*flags = *tracer->default_flags;
+		flags->trace = tracer;
+
+		t->flags = flags;
+
+		/* If this is an instance, inherit the global_trace flags */
+		if (!(tr->flags & TRACE_ARRAY_FL_GLOBAL)) {
+			int val = get_global_flags_val(tracer);
+			if (!WARN_ON_ONCE(val < 0))
+				flags->val = val;
+		}
+	}
+
+	ret = add_tracer_options(tr, t);
+	if (ret < 0) {
+		list_del(&t->list);
+		kfree(t->flags);
+		kfree(t);
+	}
+
+	return ret;
+}
+
 static struct dentry *
 create_trace_option_core_file(struct trace_array *tr,
 			      const char *option, long index)
@@ -10111,13 +10200,27 @@ static void init_trace_flags_index(struct trace_array *tr)
 		tr->trace_flags_index[i] = i;
 }
 
-static int __update_tracer_options(struct trace_array *tr)
+static int __update_tracer(struct trace_array *tr)
 {
 	struct tracer *t;
 	int ret = 0;
 
 	for (t = trace_types; t && !ret; t = t->next)
+		ret = add_tracer(tr, t);
+
+	return ret;
+}
+
+static __init int __update_tracer_options(struct trace_array *tr)
+{
+	struct tracers *t;
+	int ret = 0;
+
+	list_for_each_entry(t, &tr->tracers, list) {
 		ret = add_tracer_options(tr, t);
+		if (ret < 0)
+			break;
+	}
 
 	return ret;
 }
@@ -10171,7 +10274,7 @@ static int trace_array_create_dir(struct trace_array *tr)
 	}
 
 	init_tracer_tracefs(tr, tr->dir);
-	ret = __update_tracer_options(tr);
+	ret = __update_tracer(tr);
 	if (ret) {
 		event_trace_del_tracer(tr);
 		tracefs_remove(tr->dir);
@@ -10226,11 +10329,13 @@ trace_array_create_systems(const char *name, const char *systems,
 	spin_lock_init(&tr->snapshot_trigger_lock);
 #endif
 	tr->current_trace = &nop_trace;
+	tr->current_trace_flags = nop_trace.flags;
 
 	INIT_LIST_HEAD(&tr->systems);
 	INIT_LIST_HEAD(&tr->events);
 	INIT_LIST_HEAD(&tr->hist_vars);
 	INIT_LIST_HEAD(&tr->err_log);
+	INIT_LIST_HEAD(&tr->tracers);
 	INIT_LIST_HEAD(&tr->marker_list);
 
 #ifdef CONFIG_MODULES
@@ -10403,6 +10508,7 @@ static int __remove_instance(struct trace_array *tr)
 	free_percpu(tr->last_func_repeats);
 	free_trace_buffers(tr);
 	clear_tracing_err_log(tr);
+	free_tracers(tr);
 
 	if (tr->range_name) {
 		reserve_mem_release_by_name(tr->range_name);
@@ -11437,6 +11543,7 @@ __init static int tracer_alloc_buffers(void)
 	 * just a bootstrap of current_trace anyway.
 	 */
 	global_trace.current_trace = &nop_trace;
+	global_trace.current_trace_flags = nop_trace.flags;
 
 	global_trace.max_lock = (arch_spinlock_t)__ARCH_SPIN_LOCK_UNLOCKED;
 #ifdef CONFIG_TRACER_MAX_TRACE
@@ -11450,10 +11557,7 @@ __init static int tracer_alloc_buffers(void)
 
 	init_trace_flags_index(&global_trace);
 
-	register_tracer(&nop_trace);
-
-	/* Function tracing may start here (via kernel command line) */
-	init_function_trace();
+	INIT_LIST_HEAD(&global_trace.tracers);
 
 	/* All seems OK, enable tracing */
 	tracing_disabled = 0;
@@ -11474,6 +11578,11 @@ __init static int tracer_alloc_buffers(void)
 	list_add(&global_trace.marker_list, &marker_copies);
 	list_add(&global_trace.list, &ftrace_trace_arrays);
 
+	register_tracer(&nop_trace);
+
+	/* Function tracing may start here (via kernel command line) */
+	init_function_trace();
+
 	apply_trace_boot_options();
 
 	register_snapshot_cmd();
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 8ecaf91ca823..299862aad66c 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -392,6 +392,7 @@ struct trace_array {
 	int			buffer_percent;
 	unsigned int		n_err_log_entries;
 	struct tracer		*current_trace;
+	struct tracer_flags	*current_trace_flags;
 	u64			trace_flags;
 	unsigned char		trace_flags_index[TRACE_FLAGS_MAX_SIZE];
 	unsigned int		flags;
@@ -406,6 +407,7 @@ struct trace_array {
 	struct list_head	systems;
 	struct list_head	events;
 	struct list_head	marker_list;
+	struct list_head	tracers;
 	struct trace_event_file *trace_marker_file;
 	cpumask_var_t		tracing_cpumask; /* only trace on set CPUs */
 	/* one per_cpu trace_pipe can be opened by only one user */
@@ -637,6 +639,7 @@ struct tracer {
 						u64 mask, int set);
 	struct tracer		*next;
 	struct tracer_flags	*flags;
+	struct tracer_flags	*default_flags;
 	int			enabled;
 	bool			print_max;
 	bool			allow_instances;
-- 
2.51.0



^ permalink raw reply related

* [PATCH v4 3/3] tracing: Have function graph tracer define options per instance
From: Steven Rostedt @ 2025-11-11 23:24 UTC (permalink / raw)
  To: linux-kernel, linux-trace-kernel
  Cc: Masami Hiramatsu, Mark Rutland, Mathieu Desnoyers, Andrew Morton
In-Reply-To: <20251111232406.183056289@kernel.org>

From: Steven Rostedt <rostedt@goodmis.org>

Currently the function graph tracer's options are saved via a global mask
when it should be per instance. Use the new infrastructure to define a
"default_flags" field in the tracer structure that is used for the top
level instance as well as new ones.

Currently the global mask causes confusion:

  # cd /sys/kernel/tracing
  # mkdir instances/foo
  # echo function_graph > instances/foo/current_tracer
  # echo 1 > options/funcgraph-args
  # echo function_graph > current_tracer
  # cat trace
[..]
 2)               |          _raw_spin_lock_irq(lock=0xffff96b97dea16c0) {
 2)   0.422 us    |            do_raw_spin_lock(lock=0xffff96b97dea16c0);
 7)               |              rcu_sched_clock_irq(user=0) {
 2)   1.478 us    |          }
 7)   0.758 us    |                rcu_is_cpu_rrupt_from_idle();
 2)   0.647 us    |          enqueue_hrtimer(timer=0xffff96b97dea2058, base=0xffff96b97dea1740, mode=0);
 # cat instances/foo/options/funcgraph-args
 1
 # cat instances/foo/trace
[..]
 4)               |  __x64_sys_read() {
 4)               |    ksys_read() {
 4)   0.755 us    |      fdget_pos();
 4)               |      vfs_read() {
 4)               |        rw_verify_area() {
 4)               |          security_file_permission() {
 4)               |            apparmor_file_permission() {
 4)               |              common_file_perm() {
 4)               |                aa_file_perm() {
 4)               |                  rcu_read_lock_held() {
[..]

The above shows that updating the "funcgraph-args" option at the top level
instance also updates the "funcgraph-args" option in the instance but
because the update is only done by the instance that gets changed (as it
should), it's confusing to see that the option is already set in the other
instance.

Link: https://patch.msgid.link/20251110234342.105763200@kernel.org
Fixes: c132be2c4fcc1 ("function_graph: Have the instances use their own ftrace_ops for filtering")
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
---
 kernel/trace/trace_functions_graph.c | 18 +++++++++++-------
 1 file changed, 11 insertions(+), 7 deletions(-)

diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c
index fe9607edc8f9..4e86adf6dd4d 100644
--- a/kernel/trace/trace_functions_graph.c
+++ b/kernel/trace/trace_functions_graph.c
@@ -101,9 +101,9 @@ static struct tracer_flags tracer_flags = {
 	.opts = trace_opts
 };
 
-static bool tracer_flags_is_set(u32 flags)
+static bool tracer_flags_is_set(struct trace_array *tr, u32 flags)
 {
-	return (tracer_flags.val & flags) == flags;
+	return (tr->current_trace_flags->val & flags) == flags;
 }
 
 /*
@@ -263,7 +263,7 @@ static int graph_entry(struct ftrace_graph_ent *trace,
 
 	trace_ctx = tracing_gen_ctx();
 	if (IS_ENABLED(CONFIG_FUNCTION_GRAPH_RETADDR) &&
-	    tracer_flags_is_set(TRACE_GRAPH_PRINT_RETADDR)) {
+	    tracer_flags_is_set(tr, TRACE_GRAPH_PRINT_RETADDR)) {
 		unsigned long retaddr = ftrace_graph_top_ret_addr(current);
 		ret = __trace_graph_retaddr_entry(tr, trace, trace_ctx, retaddr);
 	} else {
@@ -441,7 +441,7 @@ static int graph_trace_init(struct trace_array *tr)
 {
 	int ret;
 
-	if (tracer_flags_is_set(TRACE_GRAPH_ARGS))
+	if (tracer_flags_is_set(tr, TRACE_GRAPH_ARGS))
 		tr->gops->entryfunc = trace_graph_entry_args;
 	else
 		tr->gops->entryfunc = trace_graph_entry;
@@ -1459,7 +1459,8 @@ print_graph_function_flags(struct trace_iterator *iter, u32 flags)
 static enum print_line_t
 print_graph_function(struct trace_iterator *iter)
 {
-	return print_graph_function_flags(iter, tracer_flags.val);
+	struct trace_array *tr = iter->tr;
+	return print_graph_function_flags(iter, tr->current_trace_flags->val);
 }
 
 static enum print_line_t
@@ -1535,7 +1536,10 @@ static void __print_graph_headers_flags(struct trace_array *tr,
 
 static void print_graph_headers(struct seq_file *s)
 {
-	print_graph_headers_flags(s, tracer_flags.val);
+	struct trace_iterator *iter = s->private;
+	struct trace_array *tr = iter->tr;
+
+	print_graph_headers_flags(s, tr->current_trace_flags->val);
 }
 
 void print_graph_headers_flags(struct seq_file *s, u32 flags)
@@ -1660,7 +1664,7 @@ static struct tracer graph_trace __tracer_data = {
 	.reset		= graph_trace_reset,
 	.print_line	= print_graph_function,
 	.print_header	= print_graph_headers,
-	.flags		= &tracer_flags,
+	.default_flags	= &tracer_flags,
 	.set_flag	= func_graph_set_flag,
 	.allow_instances = true,
 #ifdef CONFIG_FTRACE_SELFTEST
-- 
2.51.0



^ permalink raw reply related

* Re: [PATCH v2] function_graph: Enable funcgraph-args and funcgraph-retaddr to work simultaneously
From: Steven Rostedt @ 2025-11-11 23:28 UTC (permalink / raw)
  To: Donglin Peng
  Cc: linux-trace-kernel, linux-kernel, Sven Schnelle, Masami Hiramatsu,
	Donglin Peng
In-Reply-To: <20251111135432.2143993-1-dolinux.peng@gmail.com>

On Tue, 11 Nov 2025 21:54:32 +0800
Donglin Peng <dolinux.peng@gmail.com> wrote:

> Signed-off-by: Donglin Peng <pengdonglin@xiaomi.com>
> Signed-off-by: Donglin Peng <dolinux.peng@gmail.com>

BTW, are you two people?

You only need one signed-off-by. Which one do you want to keep?

-- Steve

^ permalink raw reply

* Re: [PATCH v2] function_graph: Enable funcgraph-args and funcgraph-retaddr to work simultaneously
From: Steven Rostedt @ 2025-11-11 23:37 UTC (permalink / raw)
  To: Donglin Peng
  Cc: linux-trace-kernel, linux-kernel, Sven Schnelle, Masami Hiramatsu,
	Donglin Peng
In-Reply-To: <20251111135432.2143993-1-dolinux.peng@gmail.com>

On Tue, 11 Nov 2025 21:54:32 +0800
Donglin Peng <dolinux.peng@gmail.com> wrote:

> +	/* Store the retaddr in args[0] */
> +	if (type == TRACE_GRAPH_RETADDR_ENT)
> +		entry->args[i++] = retaddr;
> +
>  #ifdef CONFIG_HAVE_FUNCTION_ARG_ACCESS_API
> -	if (fregs) {
> -		for (int i = 0; i < FTRACE_REGS_MAX_ARGS; i++)
> -			entry->args[i] = ftrace_regs_get_argument(fregs, i);
> +	if (store_args) {
> +		while (i < nr_args) {

Nit, this could stay as a for loop. You just don't initialize the 'i':

		for (; i < nr_args; i++) {

> +			entry->args[i] = ftrace_regs_get_argument(fregs,
> +						i - (type == TRACE_GRAPH_RETADDR_ENT ? 1 : 0));
> +			i++;

Then you don't need the "i++" here.

-- Steve

> +		}
>  	}

^ permalink raw reply

* Re: [PATCH] mm/migrate_device: Add tracepoints for debugging
From: Andrew Morton @ 2025-11-11 23:50 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: Balbir Singh, linux-mm, linux-trace-kernel, linux-kernel,
	Masami Hiramatsu, Mathieu Desnoyers, David Hildenbrand, Zi Yan,
	Joshua Hahn, Rakie Kim, Byungchul Park, Gregory Price, Ying Huang,
	Alistair Popple
In-Reply-To: <20251110161954.47d88433@gandalf.local.home>

On Mon, 10 Nov 2025 16:19:54 -0500 Steven Rostedt <rostedt@goodmis.org> wrote:

> On Thu, 16 Oct 2025 16:46:19 +1100
> Balbir Singh <balbirs@nvidia.com> wrote:
> 
> > Add tracepoints for debugging device migration flow in migrate_device.c.
> > This is helpful in debugging how long migration took (time can be
> > tracked backwards from migrate_device_finalize to migrate_vma_setup).
> > 
> > A combination of these events along with existing thp:*, exceptions:*
> > and migrate:* is very useful for debugging issues related to
> > migration.
> > 
>
> ...
>
> >        hmm-tests-855   [002]    50.042800: set_migration_pmd:    addr=7f2908a00000, pmd=dfffffffd39ffe00
> >        hmm-tests-855   [002]    50.062345: remove_migration_pmd: addr=7f2908a00000, pmd=efffffe00403fe00
> 
> Each TRACE_EVENT() is equivalent to:
> 
> DECLARE_EVENT_CLASS(event, ...)
> DEFINE_EVENT(event, event, ...)
> 
> Where a class is around 4-5K in size, and the DEFINE_EVENT is between
> 500 and 1k in size.
> 
> By using a single DECLARE_EVENT_CLASS() for multiple events, you can save
> several thousands of bytes of memory.

Thanks for the detailed review.  I'll drop this version of the patch.

^ permalink raw reply

* Re: [PATCH] mm/migrate_device: Add tracepoints for debugging
From: Balbir Singh @ 2025-11-11 23:55 UTC (permalink / raw)
  To: Andrew Morton, Steven Rostedt
  Cc: linux-mm, linux-trace-kernel, linux-kernel, Masami Hiramatsu,
	Mathieu Desnoyers, David Hildenbrand, Zi Yan, Joshua Hahn,
	Rakie Kim, Byungchul Park, Gregory Price, Ying Huang,
	Alistair Popple
In-Reply-To: <20251111155042.b07ecb045c978fe4c457b1d0@linux-foundation.org>

On 11/12/25 10:50, Andrew Morton wrote:
> On Mon, 10 Nov 2025 16:19:54 -0500 Steven Rostedt <rostedt@goodmis.org> wrote:
> 
>> On Thu, 16 Oct 2025 16:46:19 +1100
>> Balbir Singh <balbirs@nvidia.com> wrote:
>>
>>> Add tracepoints for debugging device migration flow in migrate_device.c.
>>> This is helpful in debugging how long migration took (time can be
>>> tracked backwards from migrate_device_finalize to migrate_vma_setup).
>>>
>>> A combination of these events along with existing thp:*, exceptions:*
>>> and migrate:* is very useful for debugging issues related to
>>> migration.
>>>
>>
>> ...
>>
>>>        hmm-tests-855   [002]    50.042800: set_migration_pmd:    addr=7f2908a00000, pmd=dfffffffd39ffe00
>>>        hmm-tests-855   [002]    50.062345: remove_migration_pmd: addr=7f2908a00000, pmd=efffffe00403fe00
>>
>> Each TRACE_EVENT() is equivalent to:
>>
>> DECLARE_EVENT_CLASS(event, ...)
>> DEFINE_EVENT(event, event, ...)
>>
>> Where a class is around 4-5K in size, and the DEFINE_EVENT is between
>> 500 and 1k in size.
>>
>> By using a single DECLARE_EVENT_CLASS() for multiple events, you can save
>> several thousands of bytes of memory.
> 
> Thanks for the detailed review.  I'll drop this version of the patch.

Thanks Steve and Andrew!

I've been looking at EVENT_CLASSES and looking for the savings you mentioned. I've not yet
finished my patch, I will resend it as soon as I have a new version

Balbir

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox