Linux Trace Kernel
 help / color / mirror / Atom feed
* Re: [PATCH v2 0/4] tools/rtla: Consolidate nr_cpus usage
From: Crystal Wood @ 2026-02-10 21:07 UTC (permalink / raw)
  To: Costa Shulyupin, Steven Rostedt, Tomas Glozar,
	Wander Lairson Costa, Ivan Pravdin, John Kacur, Tiezhu Yang,
	linux-trace-kernel, linux-kernel, bpf
In-Reply-To: <20260209092436.2899888-1-costa.shul@redhat.com>

On Mon, 2026-02-09 at 11:24 +0200, Costa Shulyupin wrote:
> sysconf(_SC_NPROCESSORS_CONF) (via get_nprocs_conf) reflects
> cpu_possible_mask, which is fixed at boot time, so querying it
> repeatedly is unnecessary.
> 
> Replace multiple calls to sysconf(_SC_NPROCESSORS_CONF) with a single
> global nr_cpus variable initialized once at startup.
> 
> v2:
> - Add `#pragma once` in timerlat_u.h to avoid redefinition errors with
>   pre-C23 compilers.
> 
> Costa Shulyupin (4):
>   tools/rtla: Consolidate nr_cpus usage across all tools
>   tools/rtla: Remove unneeded nr_cpus arguments
>   tools/rtla: Remove unneeded nr_cpus members
>   tools/rtla: Remove unneeded nr_cpus from for_each_monitored_cpu
> 
>  tools/tracing/rtla/src/common.c        |  7 ++-
>  tools/tracing/rtla/src/common.h        |  4 +-
>  tools/tracing/rtla/src/osnoise_hist.c  | 26 +++++------
>  tools/tracing/rtla/src/osnoise_top.c   | 16 ++-----
>  tools/tracing/rtla/src/timerlat.c      |  9 ++--
>  tools/tracing/rtla/src/timerlat_aa.c   | 11 ++---
>  tools/tracing/rtla/src/timerlat_bpf.c  |  5 +--
>  tools/tracing/rtla/src/timerlat_bpf.h  |  6 +--
>  tools/tracing/rtla/src/timerlat_hist.c | 62 +++++++++++---------------
>  tools/tracing/rtla/src/timerlat_top.c  | 47 +++++++------------
>  tools/tracing/rtla/src/timerlat_u.c    |  9 ++--
>  tools/tracing/rtla/src/timerlat_u.h    |  1 +
>  tools/tracing/rtla/src/utils.c         | 10 +----
>  13 files changed, 80 insertions(+), 133 deletions(-)

Reviewed-by: Crystal Wood <crwood@redhat.com>

-Crystal


^ permalink raw reply

* Re: [PATCH 1/5] tracing: Fix checking of freed trace_event_file for hist files
From: kernel test robot @ 2026-02-10 18:57 UTC (permalink / raw)
  To: Petr Pavlu, Steven Rostedt, Masami Hiramatsu
  Cc: llvm, oe-kbuild-all, Mathieu Desnoyers, Tom Zanussi, linux-kernel,
	linux-trace-kernel, Petr Pavlu
In-Reply-To: <20260210113427.1068932-2-petr.pavlu@suse.com>

Hi Petr,

kernel test robot noticed the following build errors:

[auto build test ERROR on 05f7e89ab9731565d8a62e3b5d1ec206485eeb0b]

url:    https://github.com/intel-lab-lkp/linux/commits/Petr-Pavlu/tracing-Fix-checking-of-freed-trace_event_file-for-hist-files/20260210-194023
base:   05f7e89ab9731565d8a62e3b5d1ec206485eeb0b
patch link:    https://lore.kernel.org/r/20260210113427.1068932-2-petr.pavlu%40suse.com
patch subject: [PATCH 1/5] tracing: Fix checking of freed trace_event_file for hist files
config: sparc64-defconfig (https://download.01.org/0day-ci/archive/20260211/202602110247.8HeuKXss-lkp@intel.com/config)
compiler: clang version 20.1.8 (https://github.com/llvm/llvm-project 87f0227cb60147a26a1eeb4fb06e3b505e9c7261)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260211/202602110247.8HeuKXss-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202602110247.8HeuKXss-lkp@intel.com/

All errors (new ones prefixed by >>):

>> kernel/trace/trace_events.c:1300:2: error: call to undeclared function 'hist_poll_wakeup'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
    1300 |         hist_poll_wakeup();
         |         ^
   1 error generated.


vim +/hist_poll_wakeup +1300 kernel/trace/trace_events.c

  1289	
  1290	static void remove_event_file_dir(struct trace_event_file *file)
  1291	{
  1292		eventfs_remove_dir(file->ei);
  1293		list_del(&file->list);
  1294		remove_subsystem(file->system);
  1295		free_event_filter(file->filter);
  1296		file->flags |= EVENT_FILE_FL_FREED;
  1297		event_file_put(file);
  1298	
  1299		/* Wake up hist poll waiters to notice the EVENT_FILE_FL_FREED flag. */
> 1300		hist_poll_wakeup();
  1301	}
  1302	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply

* Re: [PATCH v8 6/6] x86/vdso: Enable sframe generation in VDSO
From: H. Peter Anvin @ 2026-02-10 18:49 UTC (permalink / raw)
  To: Jens Remus, linux-kernel, linux-trace-kernel, bpf, x86, linux-mm,
	Josh Poimboeuf, Steven Rostedt
  Cc: Masami Hiramatsu, Mathieu Desnoyers, Peter Zijlstra, Ingo Molnar,
	Jiri Olsa, Arnaldo Carvalho de Melo, Namhyung Kim,
	Thomas Gleixner, Andrii Nakryiko, Indu Bhagat, Jose E. Marchesi,
	Beau Belgrave, Linus Torvalds, Andrew Morton, Florian Weimer,
	Kees Cook, Carlos O'Donell, Sam James, Dylan Hatch,
	Borislav Petkov, Dave Hansen, David Hildenbrand, Liam R. Howlett,
	Lorenzo Stoakes, Michal Hocko, Mike Rapoport, Suren Baghdasaryan,
	Vlastimil Babka, Heiko Carstens, Vasily Gorbik,
	Steven Rostedt (Google)
In-Reply-To: <15f2af3b-be33-46fc-b972-6b8e7e0aa52e@linux.ibm.com>

On February 10, 2026 8:46:33 AM PST, Jens Remus <jremus@linux.ibm.com> wrote:
>On 2/6/2026 8:36 PM, Jens Remus wrote:
>> From: Josh Poimboeuf <jpoimboe@kernel.org>
>> 
>> Enable sframe generation in the VDSO library so kernel and user space
>> can unwind through it.
>> 
>> SFrame isn't supported for x32 or x86-32.  Discard .sframe sections for
>> those VDSOs.
>> 
>> [ Jens Remus: Add support for SFrame V3.  Prevent GNU_SFRAME program
>> table entry to empty .sframe section. ]
>> 
>> Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
>> Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
>> Signed-off-by: Jens Remus <jremus@linux.ibm.com>
>
>> diff --git a/arch/Kconfig b/arch/Kconfig
>
>> @@ -479,6 +479,13 @@ config HAVE_HARDLOCKUP_DETECTOR_ARCH
>>  	  It uses the same command line parameters, and sysctl interface,
>>  	  as the generic hardlockup detectors.
>>  
>> +config AS_SFRAME
>> +	bool
>> +
>> +config AS_SFRAME3
>> +	def_bool $(as-instr,.cfi_startproc\n.cfi_endproc,-Wa$(comma)--gsframe-3)
>
>Above tests whether the assembler supports --gsframe-3 to generate
>.sframe in SFrame V3 format.  GNU assembler only supports to generate
>SFrame for x86-64.  If the assembler is built for i386 (x86-32) the test
>will fail unless option --64 is specified.  I wonder whether that could
>happen in (the rather hypothetical?) case, when the kernel is cross built
>for x86-64 on i386?  Should this therefore be changed to the following?
>
>config AS_SFRAME_64
>	def_bool $(as-instr,.cfi_startproc\n.cfi_endproc,$(m64-flag) -Wa$(comma)--gsframe)
>
>An alternative would be to enable as-instr64 to accept an optional flag
>operand, similar to as-instr, and use as-instr64 instead of as-instr.
>
>Or is this not required, as in a cross build for 64-bit on a 32-bit
>platform (or inverse) a respective cross toolchain is a prerequisite and
>the m64-flag (or m32-flag) is not used?
>
>I tried to simulate this using docker and an i386 image and then using
>the i386 tool in the container to switch "uname -m" to "i686".  But both
>of my following attempts to build for x86-64 on i386 fail with fixdep
>not found:
>
>$ docker run -it --rm -v "$HOME/linux:$HOME/linux" --platform i386 public.ecr.aws/docker/library/debian:13.3
># sed -i -s 's/^Types: deb/& deb-src/' /etc/apt/sources.list.d/debian.sources
># apt update
># apt -y build-dep linux
>
># make mrproper
># i386 make ARCH=x86_64 defconfig
># i386 make ARCH=x86_64 arch/x86/entry/vdso/
>
># make mrproper
># apt -y install gcc-x86-64-linux-gnu
># i386 make ARCH=x86_64 CROSS_COMPILE=x86_64-linux-gnu- defconfig
># i386 make ARCH=x86_64 CROSS_COMPILE=x86_64-linux-gnu- arch/x86/entry/vdso/
>
>> +	select AS_SFRAME
>> +
>>  config UNWIND_USER
>>  	bool
>
>> diff --git a/arch/x86/entry/vdso/vdso64/Makefile b/arch/x86/entry/vdso/vdso64/Makefile
>
>> @@ -14,6 +14,7 @@ vobjs-$(CONFIG_X86_SGX)		+= vsgx.o
>>  
>>  # Compilation flags
>>  flags-y				:= -DBUILD_VDSO64 -m64 -mcmodel=small
>> +flags-$(CONFIG_AS_SFRAME3)	+= -Wa,--gsframe-3
>
>flags-$(CONFIG_AS_SFRAME3_64)	+= -Wa,--gsframe-3
>
>>  
>>  # The location of this include matters!
>>  include $(src)/../common/Makefile.include
>Thanks and regards,
>Jens

I think we can worry about that later.

^ permalink raw reply

* Re: [PATCH v8 6/6] x86/vdso: Enable sframe generation in VDSO
From: Josh Poimboeuf @ 2026-02-10 18:50 UTC (permalink / raw)
  To: Jens Remus
  Cc: H. Peter Anvin, linux-kernel, linux-trace-kernel, bpf, x86,
	linux-mm, Steven Rostedt, Masami Hiramatsu, Mathieu Desnoyers,
	Peter Zijlstra, Ingo Molnar, Jiri Olsa, Arnaldo Carvalho de Melo,
	Namhyung Kim, Thomas Gleixner, Andrii Nakryiko, Indu Bhagat,
	Jose E. Marchesi, Beau Belgrave, Linus Torvalds, Andrew Morton,
	Florian Weimer, Kees Cook, Carlos O'Donell, Sam James,
	Dylan Hatch, Borislav Petkov, Dave Hansen, David Hildenbrand,
	Liam R. Howlett, Lorenzo Stoakes, Michal Hocko, Mike Rapoport,
	Suren Baghdasaryan, Vlastimil Babka, Heiko Carstens,
	Vasily Gorbik, Steven Rostedt (Google)
In-Reply-To: <15f2af3b-be33-46fc-b972-6b8e7e0aa52e@linux.ibm.com>

On Tue, Feb 10, 2026 at 05:46:33PM +0100, Jens Remus wrote:
> On 2/6/2026 8:36 PM, Jens Remus wrote:
> > From: Josh Poimboeuf <jpoimboe@kernel.org>
> > 
> > Enable sframe generation in the VDSO library so kernel and user space
> > can unwind through it.
> > 
> > SFrame isn't supported for x32 or x86-32.  Discard .sframe sections for
> > those VDSOs.
> > 
> > [ Jens Remus: Add support for SFrame V3.  Prevent GNU_SFRAME program
> > table entry to empty .sframe section. ]
> > 
> > Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
> > Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
> > Signed-off-by: Jens Remus <jremus@linux.ibm.com>
> 
> > diff --git a/arch/Kconfig b/arch/Kconfig
> 
> > @@ -479,6 +479,13 @@ config HAVE_HARDLOCKUP_DETECTOR_ARCH
> >  	  It uses the same command line parameters, and sysctl interface,
> >  	  as the generic hardlockup detectors.
> >  
> > +config AS_SFRAME
> > +	bool
> > +
> > +config AS_SFRAME3
> > +	def_bool $(as-instr,.cfi_startproc\n.cfi_endproc,-Wa$(comma)--gsframe-3)
> 
> Above tests whether the assembler supports --gsframe-3 to generate
> .sframe in SFrame V3 format.  GNU assembler only supports to generate
> SFrame for x86-64.  If the assembler is built for i386 (x86-32) the test
> will fail unless option --64 is specified.  I wonder whether that could
> happen in (the rather hypothetical?) case, when the kernel is cross built
> for x86-64 on i386?  Should this therefore be changed to the following?
> 
> config AS_SFRAME_64
> 	def_bool $(as-instr,.cfi_startproc\n.cfi_endproc,$(m64-flag) -Wa$(comma)--gsframe)
> 
> An alternative would be to enable as-instr64 to accept an optional flag
> operand, similar to as-instr, and use as-instr64 instead of as-instr.
> 
> Or is this not required, as in a cross build for 64-bit on a 32-bit
> platform (or inverse) a respective cross toolchain is a prerequisite and
> the m64-flag (or m32-flag) is not used?
> 
> I tried to simulate this using docker and an i386 image and then using
> the i386 tool in the container to switch "uname -m" to "i686".  But both
> of my following attempts to build for x86-64 on i386 fail with fixdep
> not found:
> 
> $ docker run -it --rm -v "$HOME/linux:$HOME/linux" --platform i386 public.ecr.aws/docker/library/debian:13.3
> # sed -i -s 's/^Types: deb/& deb-src/' /etc/apt/sources.list.d/debian.sources
> # apt update
> # apt -y build-dep linux
> 
> # make mrproper
> # i386 make ARCH=x86_64 defconfig
> # i386 make ARCH=x86_64 arch/x86/entry/vdso/
> 
> # make mrproper
> # apt -y install gcc-x86-64-linux-gnu
> # i386 make ARCH=x86_64 CROSS_COMPILE=x86_64-linux-gnu- defconfig
> # i386 make ARCH=x86_64 CROSS_COMPILE=x86_64-linux-gnu- arch/x86/entry/vdso/

Hm, I think I broke that with

  a808a2b35f66 ("tools build: Fix fixdep dependencies")

... though it's been broken almost a year, maybe nobody cares.

Regardless, we do need to fix "make clean" and "make mrproper" for
objtool, which would be something like so:

diff --git a/Makefile b/Makefile
index d3a8482bdbd0..ed850044491d 100644
--- a/Makefile
+++ b/Makefile
@@ -1474,6 +1474,15 @@ ifneq ($(wildcard $(resolve_btfids_O)),)
 	$(Q)$(MAKE) -sC $(srctree)/tools/bpf/resolve_btfids O=$(resolve_btfids_O) clean
 endif
 
+PHONY += objtool_clean
+
+objtool_O = $(abspath $(objtree))/tools/objtool
+
+objtool_clean:
+ifneq ($(wildcard $(objtool_O)),)
+	$(Q)$(MAKE) -sC $(abs_srctree)/tools/objtool O=$(objtool_O) srctree=$(abs_srctree) clean
+endif
+
 tools/: FORCE
 	$(Q)mkdir -p $(objtree)/tools
 	$(Q)$(MAKE) O=$(abspath $(objtree)) subdir=tools -C $(srctree)/tools/
@@ -1637,7 +1646,7 @@ vmlinuxclean:
 	$(Q)$(CONFIG_SHELL) $(srctree)/scripts/link-vmlinux.sh clean
 	$(Q)$(if $(ARCH_POSTLINK), $(MAKE) -f $(ARCH_POSTLINK) clean)
 
-clean: archclean vmlinuxclean resolve_btfids_clean
+clean: archclean vmlinuxclean resolve_btfids_clean objtool_clean
 
 # mrproper - Delete all generated files, including .config
 #
diff --git a/tools/objtool/Makefile b/tools/objtool/Makefile
index a40f30232929..6964175abdfd 100644
--- a/tools/objtool/Makefile
+++ b/tools/objtool/Makefile
@@ -29,6 +29,8 @@ srctree := $(patsubst %/,%,$(dir $(CURDIR)))
 srctree := $(patsubst %/,%,$(dir $(srctree)))
 endif
 
+RM ?= rm -f
+
 LIBSUBCMD_DIR = $(srctree)/tools/lib/subcmd/
 ifneq ($(OUTPUT),)
   LIBSUBCMD_OUTPUT = $(abspath $(OUTPUT))/libsubcmd

^ permalink raw reply related

* Re: [PATCH 1/5] tracing: Fix checking of freed trace_event_file for hist files
From: kernel test robot @ 2026-02-10 17:40 UTC (permalink / raw)
  To: Petr Pavlu, Steven Rostedt, Masami Hiramatsu
  Cc: oe-kbuild-all, Mathieu Desnoyers, Tom Zanussi, linux-kernel,
	linux-trace-kernel, Petr Pavlu
In-Reply-To: <20260210113427.1068932-2-petr.pavlu@suse.com>

Hi Petr,

kernel test robot noticed the following build errors:

[auto build test ERROR on 05f7e89ab9731565d8a62e3b5d1ec206485eeb0b]

url:    https://github.com/intel-lab-lkp/linux/commits/Petr-Pavlu/tracing-Fix-checking-of-freed-trace_event_file-for-hist-files/20260210-194023
base:   05f7e89ab9731565d8a62e3b5d1ec206485eeb0b
patch link:    https://lore.kernel.org/r/20260210113427.1068932-2-petr.pavlu%40suse.com
patch subject: [PATCH 1/5] tracing: Fix checking of freed trace_event_file for hist files
config: x86_64-buildonly-randconfig-004-20260210 (https://download.01.org/0day-ci/archive/20260211/202602110125.71oIfNm0-lkp@intel.com/config)
compiler: gcc-14 (Debian 14.2.0-19) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260211/202602110125.71oIfNm0-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202602110125.71oIfNm0-lkp@intel.com/

All errors (new ones prefixed by >>):

   kernel/trace/trace_events.c: In function 'remove_event_file_dir':
>> kernel/trace/trace_events.c:1300:9: error: implicit declaration of function 'hist_poll_wakeup' [-Wimplicit-function-declaration]
    1300 |         hist_poll_wakeup();
         |         ^~~~~~~~~~~~~~~~


vim +/hist_poll_wakeup +1300 kernel/trace/trace_events.c

  1289	
  1290	static void remove_event_file_dir(struct trace_event_file *file)
  1291	{
  1292		eventfs_remove_dir(file->ei);
  1293		list_del(&file->list);
  1294		remove_subsystem(file->system);
  1295		free_event_filter(file->filter);
  1296		file->flags |= EVENT_FILE_FL_FREED;
  1297		event_file_put(file);
  1298	
  1299		/* Wake up hist poll waiters to notice the EVENT_FILE_FL_FREED flag. */
> 1300		hist_poll_wakeup();
  1301	}
  1302	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply

* Re: [PATCH v8 6/6] x86/vdso: Enable sframe generation in VDSO
From: Jens Remus @ 2026-02-10 16:46 UTC (permalink / raw)
  To: H. Peter Anvin, linux-kernel, linux-trace-kernel, bpf, x86,
	linux-mm, Josh Poimboeuf, Steven Rostedt
  Cc: Masami Hiramatsu, Mathieu Desnoyers, Peter Zijlstra, Ingo Molnar,
	Jiri Olsa, Arnaldo Carvalho de Melo, Namhyung Kim,
	Thomas Gleixner, Andrii Nakryiko, Indu Bhagat, Jose E. Marchesi,
	Beau Belgrave, Linus Torvalds, Andrew Morton, Florian Weimer,
	Kees Cook, Carlos O'Donell, Sam James, Dylan Hatch,
	Borislav Petkov, Dave Hansen, David Hildenbrand, Liam R. Howlett,
	Lorenzo Stoakes, Michal Hocko, Mike Rapoport, Suren Baghdasaryan,
	Vlastimil Babka, Heiko Carstens, Vasily Gorbik,
	Steven Rostedt (Google)
In-Reply-To: <20260206193642.1580787-7-jremus@linux.ibm.com>

On 2/6/2026 8:36 PM, Jens Remus wrote:
> From: Josh Poimboeuf <jpoimboe@kernel.org>
> 
> Enable sframe generation in the VDSO library so kernel and user space
> can unwind through it.
> 
> SFrame isn't supported for x32 or x86-32.  Discard .sframe sections for
> those VDSOs.
> 
> [ Jens Remus: Add support for SFrame V3.  Prevent GNU_SFRAME program
> table entry to empty .sframe section. ]
> 
> Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
> Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
> Signed-off-by: Jens Remus <jremus@linux.ibm.com>

> diff --git a/arch/Kconfig b/arch/Kconfig

> @@ -479,6 +479,13 @@ config HAVE_HARDLOCKUP_DETECTOR_ARCH
>  	  It uses the same command line parameters, and sysctl interface,
>  	  as the generic hardlockup detectors.
>  
> +config AS_SFRAME
> +	bool
> +
> +config AS_SFRAME3
> +	def_bool $(as-instr,.cfi_startproc\n.cfi_endproc,-Wa$(comma)--gsframe-3)

Above tests whether the assembler supports --gsframe-3 to generate
.sframe in SFrame V3 format.  GNU assembler only supports to generate
SFrame for x86-64.  If the assembler is built for i386 (x86-32) the test
will fail unless option --64 is specified.  I wonder whether that could
happen in (the rather hypothetical?) case, when the kernel is cross built
for x86-64 on i386?  Should this therefore be changed to the following?

config AS_SFRAME_64
	def_bool $(as-instr,.cfi_startproc\n.cfi_endproc,$(m64-flag) -Wa$(comma)--gsframe)

An alternative would be to enable as-instr64 to accept an optional flag
operand, similar to as-instr, and use as-instr64 instead of as-instr.

Or is this not required, as in a cross build for 64-bit on a 32-bit
platform (or inverse) a respective cross toolchain is a prerequisite and
the m64-flag (or m32-flag) is not used?

I tried to simulate this using docker and an i386 image and then using
the i386 tool in the container to switch "uname -m" to "i686".  But both
of my following attempts to build for x86-64 on i386 fail with fixdep
not found:

$ docker run -it --rm -v "$HOME/linux:$HOME/linux" --platform i386 public.ecr.aws/docker/library/debian:13.3
# sed -i -s 's/^Types: deb/& deb-src/' /etc/apt/sources.list.d/debian.sources
# apt update
# apt -y build-dep linux

# make mrproper
# i386 make ARCH=x86_64 defconfig
# i386 make ARCH=x86_64 arch/x86/entry/vdso/

# make mrproper
# apt -y install gcc-x86-64-linux-gnu
# i386 make ARCH=x86_64 CROSS_COMPILE=x86_64-linux-gnu- defconfig
# i386 make ARCH=x86_64 CROSS_COMPILE=x86_64-linux-gnu- arch/x86/entry/vdso/

> +	select AS_SFRAME
> +
>  config UNWIND_USER
>  	bool

> diff --git a/arch/x86/entry/vdso/vdso64/Makefile b/arch/x86/entry/vdso/vdso64/Makefile

> @@ -14,6 +14,7 @@ vobjs-$(CONFIG_X86_SGX)		+= vsgx.o
>  
>  # Compilation flags
>  flags-y				:= -DBUILD_VDSO64 -m64 -mcmodel=small
> +flags-$(CONFIG_AS_SFRAME3)	+= -Wa,--gsframe-3

flags-$(CONFIG_AS_SFRAME3_64)	+= -Wa,--gsframe-3

>  
>  # The location of this include matters!
>  include $(src)/../common/Makefile.include
Thanks and regards,
Jens
-- 
Jens Remus
Linux on Z Development (D3303)
jremus@de.ibm.com / jremus@linux.ibm.com

IBM Deutschland Research & Development GmbH; Vorsitzender des Aufsichtsrats: Wolfgang Wendt; Geschäftsführung: David Faller; Sitz der Gesellschaft: Ehningen; Registergericht: Amtsgericht Stuttgart, HRB 243294
IBM Data Privacy Statement: https://www.ibm.com/privacy/


^ permalink raw reply

* Re: [PATCH 1/5] tracing: Fix checking of freed trace_event_file for hist files
From: Masami Hiramatsu @ 2026-02-10 15:59 UTC (permalink / raw)
  To: Petr Pavlu
  Cc: Steven Rostedt, Mathieu Desnoyers, Tom Zanussi, linux-kernel,
	linux-trace-kernel
In-Reply-To: <20260210113427.1068932-2-petr.pavlu@suse.com>

On Tue, 10 Feb 2026 12:28:16 +0100
Petr Pavlu <petr.pavlu@suse.com> wrote:

> The event_hist_open() and event_hist_poll() functions currently retrieve
> a trace_event_file pointer from a file struct by invoking
> event_file_data(), which simply returns file->f_inode->i_private. The
> functions then check if the pointer is NULL to determine whether the event
> is still valid. This approach is flawed because i_private is assigned when
> an eventfs inode is allocated and remains set throughout its lifetime.
> Instead, the code should call event_file_file(), which checks for
> EVENT_FILE_FL_FREED. Using the incorrect access function may result in the
> code potentially opening a hist file for an event that is being removed or
> becoming stuck while polling on this file.
> 
> A related issue is that although event_hist_poll() attempts to verify
> whether an event file is being removed, this check may not occur or could
> be unnecessarily delayed. This happens because hist_poll_wakeup() is
> currently invoked only from event_hist_trigger() when a hist command is
> triggered. If the event file is being removed, no associated hist command
> will be triggered and a waiter will be woken up only after an unrelated
> hist command is triggered.
> 
> Fix these issues by changing the access method to event_file_file() and
> adding a call to hist_poll_wakeup() in remove_event_file_dir() after
> setting the EVENT_FILE_FL_FREED flag. This ensures that a task polling on
> a hist file is woken up and receives EPOLLERR.
> 

Thanks for fixing!

Acked-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>


> Fixes: 1bd13edbbed6 ("tracing/hist: Add poll(POLLIN) support on hist file")
> Signed-off-by: Petr Pavlu <petr.pavlu@suse.com>
> ---
>  kernel/trace/trace_events.c      | 3 +++
>  kernel/trace/trace_events_hist.c | 4 ++--
>  2 files changed, 5 insertions(+), 2 deletions(-)
> 
> diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
> index 137b4d9bb116..e8ed6ba155cf 100644
> --- a/kernel/trace/trace_events.c
> +++ b/kernel/trace/trace_events.c
> @@ -1295,6 +1295,9 @@ static void remove_event_file_dir(struct trace_event_file *file)
>  	free_event_filter(file->filter);
>  	file->flags |= EVENT_FILE_FL_FREED;
>  	event_file_put(file);
> +
> +	/* Wake up hist poll waiters to notice the EVENT_FILE_FL_FREED flag. */
> +	hist_poll_wakeup();
>  }
>  
>  /*
> diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c
> index c97bb2fda5c0..744c2aa3d668 100644
> --- a/kernel/trace/trace_events_hist.c
> +++ b/kernel/trace/trace_events_hist.c
> @@ -5778,7 +5778,7 @@ static __poll_t event_hist_poll(struct file *file, struct poll_table_struct *wai
>  
>  	guard(mutex)(&event_mutex);
>  
> -	event_file = event_file_data(file);
> +	event_file = event_file_file(file);
>  	if (!event_file)
>  		return EPOLLERR;
>  
> @@ -5816,7 +5816,7 @@ static int event_hist_open(struct inode *inode, struct file *file)
>  
>  	guard(mutex)(&event_mutex);
>  
> -	event_file = event_file_data(file);
> +	event_file = event_file_file(file);
>  	if (!event_file) {
>  		ret = -ENODEV;
>  		goto err;
> -- 
> 2.52.0
> 


-- 
Masami Hiramatsu (Google) <mhiramat@kernel.org>

^ permalink raw reply

* Re: [PATCH v11 15/30] tracing: selftests: Add trace remote tests
From: Vincent Donnefort @ 2026-02-10 15:54 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: mhiramat, mathieu.desnoyers, linux-trace-kernel, maz,
	oliver.upton, joey.gouly, suzuki.poulose, yuzenghui, kvmarm,
	linux-arm-kernel, jstultz, qperret, will, aneesh.kumar,
	kernel-team, linux-kernel, Shuah Khan, linux-kselftest
In-Reply-To: <20260205124208.2ed7cff8@gandalf.local.home>

On Thu, Feb 05, 2026 at 12:42:08PM -0500, Steven Rostedt wrote:
> On Sat, 31 Jan 2026 13:28:33 +0000
> Vincent Donnefort <vdonnefort@google.com> wrote:
> 
> > Exercise the tracefs interface for trace remote with a set of tests to
> > check:
> > 
> >   * loading/unloading (unloading.tc)
> >   * reset (reset.tc)
> >   * size changes (buffer_size.tc)
> >   * consuming read (trace_pipe.tc)
> >   * non-consuming read (trace.tc)
> > 
> > Cc: Shuah Khan <skhan@linuxfoundation.org>
> > Cc: linux-kselftest@vger.kernel.org
> > Signed-off-by: Vincent Donnefort <vdonnefort@google.com>
> 
> This still fails:
> 
> === Ftrace unit tests ===
> [1] Test trace remote buffer size	[PASS]
> [2] Test hypervisor trace buffer size	[UNSUPPORTED]
> [3] Test hypervisor trace buffer reset	[UNSUPPORTED]
> [4] Test hypervisor consuming trace read	[UNSUPPORTED]
> [5] Test hypervisor non-consuming trace read	[UNSUPPORTED]
> [6] Test hypervisor trace buffer unloading	[UNSUPPORTED]
> [7] Test trace remote reset	[PASS]
> [8] Test trace remote consuming read	[FAIL]
> [9] Test trace remote non-consuming read	[FAIL]
> [10] Test trace remote unloading	[PASS]
> 
> I added this patch and the two failed tests now pass:
> 
> diff --git a/tools/testing/selftests/ftrace/test.d/remotes/trace.tc b/tools/testing/selftests/ftrace/test.d/remotes/trace.tc
> index 081133ec45ff..dfc954a6a380 100644
> --- a/tools/testing/selftests/ftrace/test.d/remotes/trace.tc
> +++ b/tools/testing/selftests/ftrace/test.d/remotes/trace.tc
> @@ -106,8 +106,10 @@ test_trace()
>      echo 0 > trace
>  
>      for cpu in $(get_cpu_ids); do
> -        echo 0 > /sys/devices/system/cpu/cpu$cpu/online
> -        break
> +        if [ -f /sys/devices/system/cpu/cpu$cpu/online ]; then
> +            echo 0 > /sys/devices/system/cpu/cpu$cpu/online
> +            break
> +        fi

Hum weird, I have changed it in v11 to 

echo 0 > /sys/devices/system/cpu/cpu$cpu/online || return 0

That doesn't work? Because I would simply stop the test there if we can't
offline the CPU.


>      done
>  
>      for i in $(seq 1 8); do
> diff --git a/tools/testing/selftests/ftrace/test.d/remotes/trace_pipe.tc b/tools/testing/selftests/ftrace/test.d/remotes/trace_pipe.tc
> index d28eaee10c7c..146f0a9fe311 100644
> --- a/tools/testing/selftests/ftrace/test.d/remotes/trace_pipe.tc
> +++ b/tools/testing/selftests/ftrace/test.d/remotes/trace_pipe.tc
> @@ -102,8 +102,10 @@ test_trace_pipe()
>      echo 0 > trace
>  
>      for cpu in $(get_cpu_ids); do
> -        echo 0 > /sys/devices/system/cpu/cpu$cpu/online
> -        break
> +        if [ -f /sys/devices/system/cpu/cpu$cpu/online ]; then
> +            echo 0 > /sys/devices/system/cpu/cpu$cpu/online
> +            break
> +        fi
>      done
>  
>      for i in $(seq 1 8); do
> 
> -- Steve

^ permalink raw reply

* [PATCH] tracing: Fix indentation of return statement in print_trace_fmt()
From: Haoyang LIU @ 2026-02-10 15:39 UTC (permalink / raw)
  To: Steven Rostedt, Masami Hiramatsu, Mathieu Desnoyers,
	open list:TRACING, open list:TRACING
  Cc: tttturtleruss, open list:TRACING, open list:TRACING

The return statement inside the nested if block in print_trace_fmt()
is not properly indented, making the code structure unclear. This was
flagged by smatch as a warning.

Add proper indentation to the return statement to match the kernel
coding style and improve readability.

Signed-off-by: Haoyang LIU <tttturtleruss@gmail.com>
Acked-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
---
 kernel/trace/trace.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 8bd4ec08fb36..bf0ce2aac177 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -4286,7 +4286,7 @@ static enum print_line_t print_trace_fmt(struct trace_iterator *iter)
 			/* ftrace and system call events are still OK */
 			if ((event->type > __TRACE_LAST_TYPE) &&
 			    !is_syscall_event(event))
-			return print_event_fields(iter, event);
+				return print_event_fields(iter, event);
 		}
 		return event->funcs->trace(iter, sym_flags, event);
 	}
-- 
2.25.1


^ permalink raw reply related

* Re: [PATCH v11 07/30] tracing: Add non-consuming read to trace remotes
From: Vincent Donnefort @ 2026-02-10 15:32 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: mhiramat, mathieu.desnoyers, linux-trace-kernel, maz,
	oliver.upton, joey.gouly, suzuki.poulose, yuzenghui, kvmarm,
	linux-arm-kernel, jstultz, qperret, will, aneesh.kumar,
	kernel-team, linux-kernel
In-Reply-To: <20260204185208.646a6d26@gandalf.local.home>

On Wed, Feb 04, 2026 at 06:52:08PM -0500, Steven Rostedt wrote:
> On Sat, 31 Jan 2026 13:28:25 +0000
> Vincent Donnefort <vdonnefort@google.com> wrote:
> 
> > -static struct trace_remote_iterator *trace_remote_iter(struct trace_remote *remote, int cpu)
> > +static void __free_ring_buffer_iter(struct trace_remote_iterator *iter, int cpu)
> > +{
> > +	if (!iter->rb_iter)
> > +		return;
> 
> Hmm, can't iter->rb_iter be NULL when iter->rb_iters[] is used?

Arg yes, I missed that when I removed the union. And actually I don't think this
can be called with iter->rb_iter or iter->rb_iter NULL anymore.

> 
> > +
> > +	if (cpu != RING_BUFFER_ALL_CPUS) {
> > +		ring_buffer_read_finish(iter->rb_iter);
> > +		return;
> > +	}
> > +
> > +	for_each_possible_cpu(cpu) {
> > +		if (iter->rb_iters[cpu])
> > +			ring_buffer_read_finish(iter->rb_iters[cpu]);
> > +	}
> > +
> > +	kfree(iter->rb_iters);
> > +}
> > +
> > +static int __alloc_ring_buffer_iter(struct trace_remote_iterator *iter, int cpu)
> > +{
> > +	if (cpu != RING_BUFFER_ALL_CPUS) {
> > +		iter->rb_iter = ring_buffer_read_start(iter->remote->trace_buffer, cpu, GFP_KERNEL);
> > +
> > +		return iter->rb_iter ? 0 : -ENOMEM;
> > +	}
> > +
> > +	iter->rb_iters = kcalloc(nr_cpu_ids, sizeof(*iter->rb_iters), GFP_KERNEL);
> > +	if (!iter->rb_iters)
> > +		return -ENOMEM;
> > +
> > +	for_each_possible_cpu(cpu) {
> > +		iter->rb_iters[cpu] = ring_buffer_read_start(iter->remote->trace_buffer, cpu,
> > +							     GFP_KERNEL);
> > +		if (!iter->rb_iters[cpu]) {
> > +			__free_ring_buffer_iter(iter, RING_BUFFER_ALL_CPUS);
> 
> For instance, we call __free_ring_buffer_iter() here, but I don't see
> iter->rb_iter being set.
> 
> -- Steve
> 
> 
> > +			return -ENOMEM;
> > +		}
> > +	}
> > +
> > +	return 0;
> > +}
> > +

[...]

> > +static void *trace_next(struct seq_file *m, void *v, loff_t *pos)
> > +{
> > +	struct trace_remote_iterator *iter = m->private;
> > +
> > +	++*pos;
> > +
> > +	if (!iter || !trace_remote_iter_read_event(iter))
> > +		return NULL;
> > +
> > +	trace_remote_iter_move(iter);
> > +	iter->pos++;
> > +
> > +	return iter;
> > +}
> > +
> > +static void *trace_start(struct seq_file *m, loff_t *pos)
> > +{
> > +	struct trace_remote_iterator *iter = m->private;
> > +	loff_t i;
> > +
> 
> FYI, this is where you take locks for iteration of files.
> 
> > +	if (!iter)
> > +		return NULL;
> > +
> > +	if (!*pos) {
> > +		iter->pos = -1;
> > +		return trace_next(m, NULL, &i);
> > +	}
> > +
> > +	i = iter->pos;
> > +	while (i < *pos) {
> > +		iter = trace_next(m, NULL, &i);
> > +		if (!iter)
> > +			return NULL;
> > +	}
> > +
> > +	return iter;
> > +}
> > +
> > +static int trace_show(struct seq_file *m, void *v)
> > +{
> > +	struct trace_remote_iterator *iter = v;
> > +
> > +	trace_seq_init(&iter->seq);
> > +
> > +	if (trace_remote_iter_print_event(iter)) {
> > +		seq_printf(m, "[EVENT %d PRINT TOO BIG]\n", iter->evt->id);
> > +		return 0;
> > +	}
> > +
> > +	return trace_print_seq(m, &iter->seq);
> > +}
> > +
> > +static void trace_stop(struct seq_file *s, void *v) { }
> 
> And stop is where you release the locks.
> 
> > +
> > +static const struct seq_operations trace_sops = {
> > +	.start		= trace_start,
> > +	.next		= trace_next,
> > +	.show		= trace_show,
> > +	.stop		= trace_stop,
> > +};
> > +
> > +static int trace_open(struct inode *inode, struct file *filp)
> > +{
> > +	struct trace_remote *remote = inode->i_private;
> > +	struct trace_remote_iterator *iter = NULL;
> > +	int cpu = tracing_get_cpu(inode);
> > +	int ret;
> > +
> > +	if (!(filp->f_mode & FMODE_READ))
> > +		return 0;
> > +
> > +	guard(mutex)(&remote->lock);
> > +
> > +	iter = trace_remote_iter(remote, cpu, TRI_NONCONSUMING);
> > +	if (IS_ERR(iter))
> > +		return PTR_ERR(iter);
> 
> So if iter is bad we exit out here.
> 
> > +
> > +	ret = seq_open(filp, &trace_sops);
> > +	if (ret) {
> > +		trace_remote_iter_free(iter);
> > +		return ret;
> > +	}
> > +
> > +	if (iter)
> 
> Why test if iter exists here?

We only test IS_ERR. iter will be NULL if the buffer isn't loaded and the
userspace output would be empty. But anyway if I move the locking into
start/stop this line will go away!

> 
> > +		trace_remote_iter_read_start(iter);
> 
> But still, the above grabs locks in the open, where it can return to user
> space while still holding the locks? That's a no-no.
> 
> You can use the seq file start and stop for locking.
> 
> -- Steve
>
[...]

^ permalink raw reply

* Re: [PATCH v8 6/6] x86/vdso: Enable sframe generation in VDSO
From: Jens Remus @ 2026-02-10 14:36 UTC (permalink / raw)
  To: H. Peter Anvin, linux-kernel, linux-trace-kernel, bpf, x86,
	linux-mm, Josh Poimboeuf, Steven Rostedt, Indu Bhagat
  Cc: Masami Hiramatsu, Mathieu Desnoyers, Peter Zijlstra, Ingo Molnar,
	Jiri Olsa, Arnaldo Carvalho de Melo, Namhyung Kim,
	Thomas Gleixner, Andrii Nakryiko, Jose E. Marchesi, Beau Belgrave,
	Linus Torvalds, Andrew Morton, Florian Weimer, Kees Cook,
	Carlos O'Donell, Sam James, Dylan Hatch, Borislav Petkov,
	Dave Hansen, David Hildenbrand, Liam R. Howlett, Lorenzo Stoakes,
	Michal Hocko, Mike Rapoport, Suren Baghdasaryan, Vlastimil Babka,
	Heiko Carstens, Vasily Gorbik, Steven Rostedt (Google)
In-Reply-To: <b074b10e-6b3e-4c69-a986-6b2eb665e535@zytor.com>

On 2/9/2026 8:13 PM, H. Peter Anvin wrote:
> On 2026-02-09 08:45, Jens Remus wrote:
>> On 2/7/2026 12:08 AM, H. Peter Anvin wrote:
>>> On 2026-02-06 11:36, Jens Remus wrote:
>>>> From: Josh Poimboeuf <jpoimboe@kernel.org>
>>>>
>>>> Enable sframe generation in the VDSO library so kernel and user space
>>>> can unwind through it.
>>>>
>>>> SFrame isn't supported for x32 or x86-32.  Discard .sframe sections for
>>>> those VDSOs.
>>>>
>>>> [ Jens Remus: Add support for SFrame V3.  Prevent GNU_SFRAME program
>>>> table entry to empty .sframe section. ]
>>>>
>>>
>>> This will not break the x86-32 build if the assembler encounters .sframe?
>>
>> I cannot follow.  Assembler option --gsframe-3 is only specified in
>> vdso64/Makefile if CONFIG_AS_SFRAME3, which affects the x86-64 and x32
>> VDSOs.  The latter as the x32 VDSO is built from x86-64 objects
>> converted to x86-32 objects using the X32 build step.  Assembler
>> directive ".cfi_sections .sframe" is no longer used in dwarf2.h, which
>> affected the x86-32 VDSO if cross build on x86-64 (so that
>> CONFIG_AS_SFRAME3=y).
>>
>> The reason to discard .sframe in the common VDSO linker script if
>> !KEEP_SFRAME is to remove it from x32 VDSO (built from x86-64 objects
>> having .sframe).  It should also prevent linker errors from linkers that
>> do not support R_X86_64_PC64 in x32 mode, such as the meanwhile fixed
>> GNU linker:
>> https://www.sourceware.org/bugzilla/show_bug.cgi?id=33807
>>
> 
> OK, the linker not handing R_X86_64_PC64 is probably a good enough reason to
> discard .sframe.

For clarification:

Binutils < 2.46 assembler generates SFrame V2, which uses PC32
relocations.
Binutils 2.46+ assembler will generate SFrame V3, which uses PC64
relocations, which the GNU linker will also support for x32.

The intent is to only support SFrame V3 in unwind user sframe and
therefore also only enable .sframe generation in VDSO using SFrame V3.

> The x32 ABI and object format is explicitly intended to be as close to the
> x86-64 as possible; it even uses the same architectural identifier. That's
> pretty much the reason we don't even bother recompiling the objects in the
> first place; the 64-bit objects can simply be downconverted from ELF64 to
> ELF32. This also means that the compiler doesn't need to support x32, although
> objcopy and ld does.
> 
> This also means the DWARF data is the one generated for 64 bits.
> 
> This works because the following is true for all vdso entrypoints:
> 	- No vdso entry point access pointers or explicit "long"s *in memory*.
> 	  (The latter formally violates POSIX for struct timespec, but that
> 	   was a deliberate decision imposed by Linus at the time the x32 API
> 	   was defined: "no 32-bit time_t in a new ABI.")
> 	- No vdso entry point calls system calls that do, either.
> 	- No vdso entry point takes a *signed* long as an argument.
> 	- No vdso entry point calls system calls that differ in behavior
> 	  between x86-64 and x32, making it OK to call the 64-bit system call
> 	  from an x32 process.
> 
> "unsigned long" and pointers *can* be safely passed in argument registers
> (because the architecture will zero-extend those registers), and in addition
> "signed long" *can* be safely passed as returns.
> 
> If ANY of the constraints above were ever violated, OR the binary format would
> start diverging to the point that objcopy can't properly convert it, then we
> would need to start compiling the x32 binaries separately.

Thank you for the detailed explanation!

>> The following works and indeed looks nicer with #if KEEP_SFRAME.  Will
>> wait for further feedback on whether or not to discard .sframe in x32
>> VDSO before sending a v9.
> 
> I think ld tripping over a bug justifies dropping .sframe at this point. *Make
> sure* to document that in the checkin, and add a comment to vdso32.lds.S that
> that is the motivation, so that if x32 gains support for .sframe in the future
> (which should be simple enough, since the formats are so similar) we don't get
> stuck in some kind of cargo cult programming problem.
> 
> It also will avoid issues on the off chance .sframe ends up being defined
> differently for x32 for some reason, perhaps for consistency with other 32-bit
> platforms.
> 
> 
> Include the version of binutils which fixed the problem in your comments.

Ok, will do.

>> diff --git a/arch/x86/entry/vdso/vdso64/vdso64.lds.S b/arch/x86/entry/vdso/vdso64/vdso64.lds.S
>> @@ -8,10 +8,7 @@
>>   */
>>  
>>  #define BUILD_VDSO64
>> -
>> -#ifdef CONFIG_AS_SFRAME
>> -# define KEEP_SFRAME
>> -#endif
>> +#define KEEP_SFRAME	(CONFIG_AS_SFRAME)
> 
> This needs to be IS_ENABLED(CONFIG_AS_SFRAME). Otherwise you get either "y" or
> "CONFIG_AS_SFRAME", neither of which are what you want.

Good catch!  Will fix.

> 
>>  #include "common/vdso-layout.lds.S"
>>  
>> diff --git a/arch/x86/entry/vdso/vdso64/vdsox32.lds.S b/arch/x86/entry/vdso/vdso64/vdsox32.lds.S
>> @@ -8,6 +8,7 @@
>>   */
>>  
>>  #define BUILD_VDSOX32
>> +#define KEEP_SFRAME	false
> 
> Is "false" supported by all appropriate cpp versions? "0" is probably a safer
> choice, and matches the IS_ENABLED() output anyway.

Will do.  I assumed "true" / "false" would be supported, given there are
a few instances:

  $ git grep "#define.*\(false\|true\)" -- arch/x86/

Regards,
Jens
-- 
Jens Remus
Linux on Z Development (D3303)
jremus@de.ibm.com / jremus@linux.ibm.com

IBM Deutschland Research & Development GmbH; Vorsitzender des Aufsichtsrats: Wolfgang Wendt; Geschäftsführung: David Faller; Sitz der Gesellschaft: Ehningen; Registergericht: Amtsgericht Stuttgart, HRB 243294
IBM Data Privacy Statement: https://www.ibm.com/privacy/


^ permalink raw reply

* [PATCH] tracing: make tr->d_max_latency accessible without CONFIG_FSNOTIFY
From: Arnd Bergmann @ 2026-02-10 14:13 UTC (permalink / raw)
  To: Steven Rostedt, Masami Hiramatsu
  Cc: Arnd Bergmann, Mathieu Desnoyers, Tom Zanussi, pengdonglin,
	Shengming Hu, linux-kernel, linux-trace-kernel

From: Arnd Bergmann <arnd@arndb.de>

A recent change attempted to make the tracing_max_latency file visible
unconditionally, but this lead to a build failure:

kernel/trace/trace.c: In function 'trace_create_maxlat_file':
kernel/trace/trace.c:1543:13: error: 'struct trace_array' has no member named 'd_max_latency'; did you mean 'max_latency'?
 1543 |         tr->d_max_latency = trace_create_file("tracing_max_latency",
      |             ^~~~~~~~~~~~~

Make the corresponding change in the header file.

Fixes: ba73713da50e ("tracing: Clean up use of trace_create_maxlat_file()")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 kernel/trace/trace.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 3ebff304fe36..b8f3804586a0 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -351,8 +351,8 @@ struct trace_array {
 	unsigned int		snapshot;
 #ifdef CONFIG_TRACER_MAX_TRACE
 	unsigned long		max_latency;
-#ifdef CONFIG_FSNOTIFY
 	struct dentry		*d_max_latency;
+#ifdef CONFIG_FSNOTIFY
 	struct work_struct	fsnotify_work;
 	struct irq_work		fsnotify_irqwork;
 #endif /* CONFIG_FSNOTIFY */
-- 
2.39.5


^ permalink raw reply related

* [PATCH 5/5] tracing: Free up file->private_data for use by individual events
From: Petr Pavlu @ 2026-02-10 11:28 UTC (permalink / raw)
  To: Steven Rostedt, Masami Hiramatsu
  Cc: Mathieu Desnoyers, Tom Zanussi, linux-kernel, linux-trace-kernel,
	Petr Pavlu
In-Reply-To: <20260210113427.1068932-1-petr.pavlu@suse.com>

The tracing_open_file_tr() function currently copies the trace_event_file
pointer from inode->i_private to file->private_data when the file is
successfully opened. This duplication is not particularly useful, as all
event code should utilize event_file_file() or event_file_data() to
retrieve a trace_event_file pointer from a file struct and these access
functions read file->f_inode->i_private. Moreover, this setup requires the
code for opening hist files to explicitly clear file->private_data before
calling single_open(), since this function expects the private_data member
to be set to NULL and uses it to store a pointer to a seq_file.

Remove the unnecessary setting of file->private_data in
tracing_open_file_tr() and simplify the hist code.

Signed-off-by: Petr Pavlu <petr.pavlu@suse.com>
---
 kernel/trace/trace.c             | 2 --
 kernel/trace/trace_events_hist.c | 4 ----
 2 files changed, 6 deletions(-)

diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 8bd4ec08fb36..7c9882e5ba22 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -4805,8 +4805,6 @@ int tracing_open_file_tr(struct inode *inode, struct file *filp)
 		event_file_get(file);
 	}
 
-	filp->private_data = inode->i_private;
-
 	return 0;
 }
 
diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c
index 744c2aa3d668..1ca3e14d7531 100644
--- a/kernel/trace/trace_events_hist.c
+++ b/kernel/trace/trace_events_hist.c
@@ -5831,8 +5831,6 @@ static int event_hist_open(struct inode *inode, struct file *file)
 	hist_file->file = file;
 	hist_file->last_act = get_hist_hit_count(event_file);
 
-	/* Clear private_data to avoid warning in single_open() */
-	file->private_data = NULL;
 	ret = single_open(file, hist_show, hist_file);
 	if (ret) {
 		kfree(hist_file);
@@ -6114,8 +6112,6 @@ static int event_hist_debug_open(struct inode *inode, struct file *file)
 	if (ret)
 		return ret;
 
-	/* Clear private_data to avoid warning in single_open() */
-	file->private_data = NULL;
 	ret = single_open(file, hist_debug_show, file);
 	if (ret)
 		tracing_release_file_tr(inode, file);
-- 
2.52.0


^ permalink raw reply related

* [PATCH 4/5] tracing: Clean up access to trace_event_file from a file pointer
From: Petr Pavlu @ 2026-02-10 11:28 UTC (permalink / raw)
  To: Steven Rostedt, Masami Hiramatsu
  Cc: Mathieu Desnoyers, Tom Zanussi, linux-kernel, linux-trace-kernel,
	Petr Pavlu
In-Reply-To: <20260210113427.1068932-1-petr.pavlu@suse.com>

The tracing code provides two functions event_file_file() and
event_file_data() to obtain a trace_event_file pointer from a file struct.
The primary method to use is event_file_file(), as it checks for the
EVENT_FILE_FL_FREED flag to determine whether the event is being removed.
The second function event_file_data() is an optimization for retrieving the
same data when the event_mutex is still held.

In the past, when removing an event directory in remove_event_file_dir(),
the code set i_private to NULL for all event files and readers were
expected to check for this state to recognize that the event is being
removed. In the case of event_id_read(), the value was read using
event_file_data() without acquiring the event_mutex. This required
event_file_data() to use READ_ONCE() when retrieving the i_private data.

With the introduction of eventfs, i_private is assigned when an eventfs
inode is allocated and remains set throughout its lifetime. A previous fix
also modified event_id_read() to read i_private while holding the
event_mutex.

Remove the now unnecessary READ_ONCE() access to i_private in both
event_file_file() and event_file_data(). Add a check in event_file_data()
to ensure that the event_mutex is held and that file->flags doesn't have
the EVENT_FILE_FL_FREED flag set. Finally, move event_file_data()
immediately after event_file_code() since the latter provides a comment
explaining how both functions should be used together.

Signed-off-by: Petr Pavlu <petr.pavlu@suse.com>
---
 kernel/trace/trace.h | 17 +++++++++++------
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index c11edec5d8f5..c6b450de93bc 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -1739,11 +1739,6 @@ extern struct trace_event_file *find_event_file(struct trace_array *tr,
 						const char *system,
 						const char *event);
 
-static inline void *event_file_data(struct file *filp)
-{
-	return READ_ONCE(file_inode(filp)->i_private);
-}
-
 extern struct mutex event_mutex;
 extern struct list_head ftrace_events;
 
@@ -1764,12 +1759,22 @@ static inline struct trace_event_file *event_file_file(struct file *filp)
 	struct trace_event_file *file;
 
 	lockdep_assert_held(&event_mutex);
-	file = READ_ONCE(file_inode(filp)->i_private);
+	file = file_inode(filp)->i_private;
 	if (!file || file->flags & EVENT_FILE_FL_FREED)
 		return NULL;
 	return file;
 }
 
+static inline void *event_file_data(struct file *filp)
+{
+	struct trace_event_file *file;
+
+	lockdep_assert_held(&event_mutex);
+	file = file_inode(filp)->i_private;
+	WARN_ON(!file || file->flags & EVENT_FILE_FL_FREED);
+	return file;
+}
+
 extern const struct file_operations event_trigger_fops;
 extern const struct file_operations event_hist_fops;
 extern const struct file_operations event_hist_debug_fops;
-- 
2.52.0


^ permalink raw reply related

* [PATCH 3/5] tracing: Remove unnecessary check for EVENT_FILE_FL_FREED
From: Petr Pavlu @ 2026-02-10 11:28 UTC (permalink / raw)
  To: Steven Rostedt, Masami Hiramatsu
  Cc: Mathieu Desnoyers, Tom Zanussi, linux-kernel, linux-trace-kernel,
	Petr Pavlu
In-Reply-To: <20260210113427.1068932-1-petr.pavlu@suse.com>

The event_filter_write() function calls event_file_file() to retrieve
a trace_event_file associated with a given file struct. If a non-NULL
pointer is returned, the function then checks whether the trace_event_file
instance has the EVENT_FILE_FL_FREED flag set. This check is redundant
because event_file_file() already performs this validation and returns NULL
if the flag is set. The err value is also already initialized to -ENODEV.

Remove the unnecessary check for EVENT_FILE_FL_FREED in
event_filter_write().

Signed-off-by: Petr Pavlu <petr.pavlu@suse.com>
---
 kernel/trace/trace_events.c | 8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index 3d272b3cd688..401ab7ed869b 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -2160,12 +2160,8 @@ event_filter_write(struct file *filp, const char __user *ubuf, size_t cnt,
 
 	mutex_lock(&event_mutex);
 	file = event_file_file(filp);
-	if (file) {
-		if (file->flags & EVENT_FILE_FL_FREED)
-			err = -ENODEV;
-		else
-			err = apply_event_filter(file, buf);
-	}
+	if (file)
+		err = apply_event_filter(file, buf);
 	mutex_unlock(&event_mutex);
 
 	kfree(buf);
-- 
2.52.0


^ permalink raw reply related

* [PATCH 2/5] tracing: Fix checking of freed trace_event_file for id files
From: Petr Pavlu @ 2026-02-10 11:28 UTC (permalink / raw)
  To: Steven Rostedt, Masami Hiramatsu
  Cc: Mathieu Desnoyers, Tom Zanussi, linux-kernel, linux-trace-kernel,
	Petr Pavlu
In-Reply-To: <20260210113427.1068932-1-petr.pavlu@suse.com>

The code for reading an event id currently uses file->f_inode->i_private to
store the value of trace_event_file->event_call->event.type, unlike all
other event files which use it to store a pointer to the associated
trace_event_file data. The event_id_read() function retrieves this id value
from i_private and checks if it is non-0/NULL to determine whether the
event is still valid. This approach worked in the past when
remove_event_file_dir() would set i_private to NULL for all files in an
event directory upon removal. However, with the introduction of eventfs,
i_private is assigned when an eventfs inode is allocated and remains set
throughout its lifetime. As a result, event_id_read() may fail to detect
that an event is being removed.

Fix this issue by changing the event id file to use i_private to store
a trace_event_file pointer and utilize event_file_file() to check for the
EVENT_FILE_FL_FREED flag.

Fixes: 6fdac58c560e ("tracing: Remove unused trace_event_file dir field")
Signed-off-by: Petr Pavlu <petr.pavlu@suse.com>
---
 kernel/trace/trace_events.c | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index e8ed6ba155cf..3d272b3cd688 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -2090,11 +2090,18 @@ static int trace_format_open(struct inode *inode, struct file *file)
 static ssize_t
 event_id_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
 {
-	int id = (long)event_file_data(filp);
+	struct trace_event_file *file;
+	int id;
 	char buf[32];
 	int len;
 
-	if (unlikely(!id))
+	mutex_lock(&event_mutex);
+	file = event_file_file(filp);
+	if (likely(file))
+		id = file->event_call->event.type;
+	mutex_unlock(&event_mutex);
+
+	if (!file)
 		return -ENODEV;
 
 	len = sprintf(buf, "%d\n", id);
@@ -2572,7 +2579,9 @@ static const struct file_operations ftrace_event_format_fops = {
 
 #ifdef CONFIG_PERF_EVENTS
 static const struct file_operations ftrace_event_id_fops = {
+	.open = tracing_open_file_tr,
 	.read = event_id_read,
+	.release = tracing_release_file_tr,
 	.llseek = default_llseek,
 };
 #endif
@@ -2936,7 +2945,6 @@ static int event_callback(const char *name, umode_t *mode, void **data,
 	if (call->event.type && call->class->reg &&
 	    strcmp(name, "id") == 0) {
 		*mode = TRACE_MODE_READ;
-		*data = (void *)(long)call->event.type;
 		*fops = &ftrace_event_id_fops;
 		return 1;
 	}
-- 
2.52.0


^ permalink raw reply related

* [PATCH 1/5] tracing: Fix checking of freed trace_event_file for hist files
From: Petr Pavlu @ 2026-02-10 11:28 UTC (permalink / raw)
  To: Steven Rostedt, Masami Hiramatsu
  Cc: Mathieu Desnoyers, Tom Zanussi, linux-kernel, linux-trace-kernel,
	Petr Pavlu
In-Reply-To: <20260210113427.1068932-1-petr.pavlu@suse.com>

The event_hist_open() and event_hist_poll() functions currently retrieve
a trace_event_file pointer from a file struct by invoking
event_file_data(), which simply returns file->f_inode->i_private. The
functions then check if the pointer is NULL to determine whether the event
is still valid. This approach is flawed because i_private is assigned when
an eventfs inode is allocated and remains set throughout its lifetime.
Instead, the code should call event_file_file(), which checks for
EVENT_FILE_FL_FREED. Using the incorrect access function may result in the
code potentially opening a hist file for an event that is being removed or
becoming stuck while polling on this file.

A related issue is that although event_hist_poll() attempts to verify
whether an event file is being removed, this check may not occur or could
be unnecessarily delayed. This happens because hist_poll_wakeup() is
currently invoked only from event_hist_trigger() when a hist command is
triggered. If the event file is being removed, no associated hist command
will be triggered and a waiter will be woken up only after an unrelated
hist command is triggered.

Fix these issues by changing the access method to event_file_file() and
adding a call to hist_poll_wakeup() in remove_event_file_dir() after
setting the EVENT_FILE_FL_FREED flag. This ensures that a task polling on
a hist file is woken up and receives EPOLLERR.

Fixes: 1bd13edbbed6 ("tracing/hist: Add poll(POLLIN) support on hist file")
Signed-off-by: Petr Pavlu <petr.pavlu@suse.com>
---
 kernel/trace/trace_events.c      | 3 +++
 kernel/trace/trace_events_hist.c | 4 ++--
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index 137b4d9bb116..e8ed6ba155cf 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -1295,6 +1295,9 @@ static void remove_event_file_dir(struct trace_event_file *file)
 	free_event_filter(file->filter);
 	file->flags |= EVENT_FILE_FL_FREED;
 	event_file_put(file);
+
+	/* Wake up hist poll waiters to notice the EVENT_FILE_FL_FREED flag. */
+	hist_poll_wakeup();
 }
 
 /*
diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c
index c97bb2fda5c0..744c2aa3d668 100644
--- a/kernel/trace/trace_events_hist.c
+++ b/kernel/trace/trace_events_hist.c
@@ -5778,7 +5778,7 @@ static __poll_t event_hist_poll(struct file *file, struct poll_table_struct *wai
 
 	guard(mutex)(&event_mutex);
 
-	event_file = event_file_data(file);
+	event_file = event_file_file(file);
 	if (!event_file)
 		return EPOLLERR;
 
@@ -5816,7 +5816,7 @@ static int event_hist_open(struct inode *inode, struct file *file)
 
 	guard(mutex)(&event_mutex);
 
-	event_file = event_file_data(file);
+	event_file = event_file_file(file);
 	if (!event_file) {
 		ret = -ENODEV;
 		goto err;
-- 
2.52.0


^ permalink raw reply related

* [PATCH 0/5] Clean up access to trace_event_file from a file struct
From: Petr Pavlu @ 2026-02-10 11:28 UTC (permalink / raw)
  To: Steven Rostedt, Masami Hiramatsu
  Cc: Mathieu Desnoyers, Tom Zanussi, linux-kernel, linux-trace-kernel,
	Petr Pavlu

This series includes several patches related to accessing
trace_event_file from a file struct. The first two patches are fixes for
edge cases, the remaining patches are minor cleanups.

Petr Pavlu (5):
  tracing: Fix checking of freed trace_event_file for hist files
  tracing: Fix checking of freed trace_event_file for id files
  tracing: Remove unnecessary check for EVENT_FILE_FL_FREED
  tracing: Clean up access to trace_event_file from a file pointer
  tracing: Free up file->private_data for use by individual events

 kernel/trace/trace.c             |  2 --
 kernel/trace/trace.h             | 17 +++++++++++------
 kernel/trace/trace_events.c      | 25 ++++++++++++++++---------
 kernel/trace/trace_events_hist.c |  8 ++------
 4 files changed, 29 insertions(+), 23 deletions(-)


base-commit: 05f7e89ab9731565d8a62e3b5d1ec206485eeb0b
-- 
2.52.0


^ permalink raw reply

* [PATCH 2/2] selftests/tracing: Fix to check awk supports non POSIX strtonum()
From: Masami Hiramatsu (Google) @ 2026-02-10  9:54 UTC (permalink / raw)
  To: Steven Rostedt, Shuah Khan, Gabriele Monaco
  Cc: Mathieu Desnoyers, Masami Hiramatsu, linux-kernel,
	linux-trace-kernel, linux-kselftest
In-Reply-To: <177071725191.2369897.14781037901532893911.stgit@mhiramat.tok.corp.google.com>

From: Masami Hiramatsu (Google) <mhiramat@kernel.org>

Check the awk command supports non POSIX strtonum() function in
the trace_marker_raw test case.

Fixes: 37f46601383a ("selftests/tracing: Add basic test for trace_marker_raw file")
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
---
 .../ftrace/test.d/00basic/trace_marker_raw.tc      |    2 ++
 tools/testing/selftests/ftrace/test.d/functions    |    4 ++++
 2 files changed, 6 insertions(+)

diff --git a/tools/testing/selftests/ftrace/test.d/00basic/trace_marker_raw.tc b/tools/testing/selftests/ftrace/test.d/00basic/trace_marker_raw.tc
index a2c42e13f614..8e905d4fe6dd 100644
--- a/tools/testing/selftests/ftrace/test.d/00basic/trace_marker_raw.tc
+++ b/tools/testing/selftests/ftrace/test.d/00basic/trace_marker_raw.tc
@@ -4,6 +4,8 @@
 # requires: trace_marker_raw
 # flags: instance
 
+check_awk_strtonum || exit_unresolved
+
 is_little_endian() {
 	if lscpu | grep -q 'Little Endian'; then
 		echo 1;
diff --git a/tools/testing/selftests/ftrace/test.d/functions b/tools/testing/selftests/ftrace/test.d/functions
index e8e718139294..41325f387ee7 100644
--- a/tools/testing/selftests/ftrace/test.d/functions
+++ b/tools/testing/selftests/ftrace/test.d/functions
@@ -173,6 +173,10 @@ check_requires() { # Check required files and tracers
     done
 }
 
+check_awk_strtonum() { # strtonum is GNU awk extension
+    awk 'BEGIN{strtonum("0x1")}'
+}
+
 LOCALHOST=127.0.0.1
 
 yield() {


^ permalink raw reply related

* [PATCH 1/2] selftests/tracing: Fix to make --logdir option work again
From: Masami Hiramatsu (Google) @ 2026-02-10  9:54 UTC (permalink / raw)
  To: Steven Rostedt, Shuah Khan, Gabriele Monaco
  Cc: Mathieu Desnoyers, Masami Hiramatsu, linux-kernel,
	linux-trace-kernel, linux-kselftest

From: Masami Hiramatsu (Google) <mhiramat@kernel.org>

Since commit a0aa283c53a7 ("selftest/ftrace: Generalise ftracetest to
use with RV") moved the default LOG_DIR setting after --logdir option
parser, it overwrites the user given LOG_DIR.
This fixes it to check the --logdir option parameter when setting new
default LOG_DIR with a new TOP_DIR.

Fixes: a0aa283c53a7 ("selftest/ftrace: Generalise ftracetest to use with RV")
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
---
 tools/testing/selftests/ftrace/ftracetest |   18 ++++++++++++------
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/tools/testing/selftests/ftrace/ftracetest b/tools/testing/selftests/ftrace/ftracetest
index 3230bd54dba8..0a56bf209f6c 100755
--- a/tools/testing/selftests/ftrace/ftracetest
+++ b/tools/testing/selftests/ftrace/ftracetest
@@ -130,8 +130,7 @@ parse_opts() { # opts
       shift 1
     ;;
     --logdir|-l)
-      LOG_DIR=$2
-      LINK_PTR=
+      USER_LOG_DIR=$2
       shift 2
     ;;
     --rv)
@@ -199,6 +198,7 @@ fi
 TOP_DIR=`absdir $0`
 TEST_DIR=$TOP_DIR/test.d
 TEST_CASES=`find_testcases $TEST_DIR`
+USER_LOG_DIR=
 KEEP_LOG=0
 KTAP=0
 DEBUG=0
@@ -210,12 +210,18 @@ RV_TEST=0
 # Parse command-line options
 parse_opts $*
 
+[ $DEBUG -ne 0 ] && set -x
+
+# TOP_DIR can be changed for rv. Setting log directory.
 LOG_TOP_DIR=$TOP_DIR/logs
 LOG_DATE=`date +%Y%m%d-%H%M%S`
-LOG_DIR=$LOG_TOP_DIR/$LOG_DATE/
-LINK_PTR=$LOG_TOP_DIR/latest
-
-[ $DEBUG -ne 0 ] && set -x
+if [ -n "$USER_LOG_DIR" ]; then
+  LOG_DIR=$USER_LOG_DIR
+  LINK_PTR=
+else
+  LOG_DIR=$LOG_TOP_DIR/$LOG_DATE/
+  LINK_PTR=$LOG_TOP_DIR/latest
+fi
 
 if [ $RV_TEST -ne 0 ]; then
 	TRACING_DIR=$TRACING_DIR/rv


^ permalink raw reply related

* [PATCH v8 6/6] tracing/Documentation: Add a section about backup instance
From: Masami Hiramatsu (Google) @ 2026-02-10  8:44 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: Masami Hiramatsu, Mathieu Desnoyers, linux-kernel,
	linux-trace-kernel
In-Reply-To: <177071300558.2293046.12057922262682243630.stgit@mhiramat.tok.corp.google.com>

From: Masami Hiramatsu (Google) <mhiramat@kernel.org>

Add a section about backup instance to the debugging.rst.

Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
---
  Changes in v6:
   - Fix typos.
---
 Documentation/trace/debugging.rst |   19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/Documentation/trace/debugging.rst b/Documentation/trace/debugging.rst
index 4d88c346fc38..15857951b506 100644
--- a/Documentation/trace/debugging.rst
+++ b/Documentation/trace/debugging.rst
@@ -159,3 +159,22 @@ If setting it from the kernel command line, it is recommended to also
 disable tracing with the "traceoff" flag, and enable tracing after boot up.
 Otherwise the trace from the most recent boot will be mixed with the trace
 from the previous boot, and may make it confusing to read.
+
+Using a backup instance for keeping previous boot data
+------------------------------------------------------
+
+It is also possible to record trace data at system boot time by specifying
+events with the persistent ring buffer, but in this case the data before the
+reboot will be lost before it can be read. This problem can be solved by a
+backup instance. From the kernel command line::
+
+  reserve_mem=12M:4096:trace trace_instance=boot_map@trace,sched,irq trace_instance=backup=boot_map
+
+On boot up, the previous data in the "boot_map" is copied to the "backup"
+instance, and the "sched:*" and "irq:*" events for the current boot are traced
+in the "boot_map". Thus the user can read the previous boot data from the "backup"
+instance without stopping the trace.
+
+Note that this "backup" instance is readonly, and will be removed automatically
+if you clear the trace data or read out all trace data from the "trace_pipe"
+or the "trace_pipe_raw" files.
\ No newline at end of file


^ permalink raw reply related

* [PATCH v8 5/6] tracing: Remove the backup instance automatically after read
From: Masami Hiramatsu (Google) @ 2026-02-10  8:44 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: Masami Hiramatsu, Mathieu Desnoyers, linux-kernel,
	linux-trace-kernel
In-Reply-To: <177071300558.2293046.12057922262682243630.stgit@mhiramat.tok.corp.google.com>

From: Masami Hiramatsu (Google) <mhiramat@kernel.org>

Since the backup instance is readonly, after reading all data
via pipe, no data is left on the instance. Thus it can be
removed safely after closing all files.
This also removes it if user resets the ring buffer manually
via 'trace' file.

Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
---
 Changes in v6:
   - Fix typo in comment.
   - Only when there is a readonly trace array, initialize autoremove_wq.
   - Fix to exit loop in trace_array_get() if tr is found in the list.
 Changes in v4:
   - Update description.
---
 kernel/trace/trace.c |   61 +++++++++++++++++++++++++++++++++++++++++++++++++-
 kernel/trace/trace.h |    6 +++++
 2 files changed, 66 insertions(+), 1 deletion(-)

diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 566d1e824360..c746cb4c6e38 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -578,6 +578,51 @@ void trace_set_ring_buffer_expanded(struct trace_array *tr)
 	tr->ring_buffer_expanded = true;
 }
 
+static int __remove_instance(struct trace_array *tr);
+
+static void trace_array_autoremove(struct work_struct *work)
+{
+	struct trace_array *tr = container_of(work, struct trace_array, autoremove_work);
+
+	guard(mutex)(&event_mutex);
+	guard(mutex)(&trace_types_lock);
+
+	/*
+	 * This can be fail if someone gets @tr before starting this
+	 * function, but in that case, this will be kicked again when
+	 * putting it. So we don't care about the result.
+	 */
+	__remove_instance(tr);
+}
+
+static struct workqueue_struct *autoremove_wq;
+
+static void trace_array_kick_autoremove(struct trace_array *tr)
+{
+	if (autoremove_wq && !work_pending(&tr->autoremove_work))
+		queue_work(autoremove_wq, &tr->autoremove_work);
+}
+
+static void trace_array_cancel_autoremove(struct trace_array *tr)
+{
+	if (autoremove_wq && work_pending(&tr->autoremove_work))
+		cancel_work(&tr->autoremove_work);
+}
+
+static void trace_array_init_autoremove(struct trace_array *tr)
+{
+	INIT_WORK(&tr->autoremove_work, trace_array_autoremove);
+
+	/* Only readonly trace_array can kick the autoremove. */
+	if (!trace_array_is_readonly(tr) || autoremove_wq)
+		return;
+
+	autoremove_wq = alloc_workqueue("tr_autoremove_wq",
+					WQ_UNBOUND | WQ_HIGHPRI, 0);
+	if (!autoremove_wq)
+		pr_warn("Unable to allocate tr_autoremove_wq. autoremove disabled.\n");
+}
+
 LIST_HEAD(ftrace_trace_arrays);
 
 int trace_array_get(struct trace_array *this_tr)
@@ -587,7 +632,8 @@ int trace_array_get(struct trace_array *this_tr)
 	guard(mutex)(&trace_types_lock);
 	list_for_each_entry(tr, &ftrace_trace_arrays, list) {
 		if (tr == this_tr) {
-			tr->ref++;
+			if (!tr->free_on_close)
+				tr->ref++;
 			return 0;
 		}
 	}
@@ -599,6 +645,12 @@ static void __trace_array_put(struct trace_array *this_tr)
 {
 	WARN_ON(!this_tr->ref);
 	this_tr->ref--;
+	/*
+	 * When free_on_close is set, prepare removing the array
+	 * when the last reference is released.
+	 */
+	if (this_tr->ref == 1 && this_tr->free_on_close)
+		trace_array_kick_autoremove(this_tr);
 }
 
 /**
@@ -5463,6 +5515,10 @@ static void update_last_data(struct trace_array *tr)
 	/* Only if the buffer has previous boot data clear and update it. */
 	tr->flags &= ~TRACE_ARRAY_FL_LAST_BOOT;
 
+	/* If this is a backup instance, mark it for autoremove. */
+	if (tr->flags & TRACE_ARRAY_FL_VMALLOC)
+		tr->free_on_close = true;
+
 	/* Reset the module list and reload them */
 	if (tr->scratch) {
 		struct trace_scratch *tscratch = tr->scratch;
@@ -9596,6 +9652,8 @@ trace_array_create_systems(const char *name, const char *systems,
 	if (ftrace_allocate_ftrace_ops(tr) < 0)
 		goto out_free_tr;
 
+	trace_array_init_autoremove(tr);
+
 	ftrace_init_trace_array(tr);
 
 	init_trace_flags_index(tr);
@@ -9744,6 +9802,7 @@ static int __remove_instance(struct trace_array *tr)
 	if (update_marker_trace(tr, 0))
 		synchronize_rcu();
 
+	trace_array_cancel_autoremove(tr);
 	tracing_set_nop(tr);
 	clear_ftrace_function_probes(tr);
 	event_trace_del_tracer(tr);
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 393be92768f1..48b94759ba1c 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -450,6 +450,12 @@ struct trace_array {
 	 * we do not waste memory on systems that are not using tracing.
 	 */
 	bool ring_buffer_expanded;
+	/*
+	 * If the ring buffer is a read only backup instance, it will be
+	 * removed after dumping all data via pipe, because no readable data.
+	 */
+	bool free_on_close;
+	struct work_struct	autoremove_work;
 };
 
 enum {


^ permalink raw reply related

* [PATCH v8 4/6] tracing: Make the backup instance non-reusable
From: Masami Hiramatsu (Google) @ 2026-02-10  8:43 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: Masami Hiramatsu, Mathieu Desnoyers, linux-kernel,
	linux-trace-kernel
In-Reply-To: <177071300558.2293046.12057922262682243630.stgit@mhiramat.tok.corp.google.com>

From: Masami Hiramatsu (Google) <mhiramat@kernel.org>

Since there is no reason to reuse the backup instance, make it
readonly (but erasable).
Note that only backup instances are readonly, because
other trace instances will be empty unless it is writable.
Only backup instances have copy entries from the original.

With this change, most of the trace control files are removed
from the backup instance, including eventfs enable/filter etc.

 # find /sys/kernel/tracing/instances/backup/events/ | wc -l
 4093
 # find /sys/kernel/tracing/instances/boot_map/events/ | wc -l
 9573

Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
---
 Changes in v8:
   - Remove read-only checks in read() operation.
 Changes in v7:
   - Return -EACCES instead of -EPERM.
 Changes in v6:
   - Remove tracing_on file from readonly instances.
   - Remove unused writable_mode from tracing_init_tracefs_percpu().
   - Cleanup init_tracer_tracefs() and create_event_toplevel_files().
   - Remove TRACE_MODE_WRITE_MASK.
   - Add TRACE_ARRAY_FL_RDONLY.
 Changes in v5:
   - Rebased on the latest for-next (and hide show_event_filters/triggers
     if the instance is readonly.
 Changes in v4:
  - Make trace data erasable. (not reusable)
 Changes in v3:
  - Resuse the beginning part of event_entries for readonly files.
  - Remove readonly file_operations and checking readonly flag in
    each write operation.
 Changes in v2:
  - Use readonly file_operations to prohibit writing instead of
    checking flags in write() callbacks.
  - Remove writable files from eventfs.
---
 kernel/trace/trace.c        |   71 +++++++++++++++++++++++-----------------
 kernel/trace/trace.h        |    7 ++++
 kernel/trace/trace_boot.c   |    5 ++-
 kernel/trace/trace_events.c |   76 +++++++++++++++++++++++++------------------
 4 files changed, 94 insertions(+), 65 deletions(-)

diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index e884d32b7895..566d1e824360 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -9836,17 +9836,22 @@ static __init void create_trace_instances(struct dentry *d_tracer)
 static void
 init_tracer_tracefs(struct trace_array *tr, struct dentry *d_tracer)
 {
+	umode_t writable_mode = TRACE_MODE_WRITE;
 	int cpu;
 
+	if (trace_array_is_readonly(tr))
+		writable_mode = TRACE_MODE_READ;
+
 	trace_create_file("available_tracers", TRACE_MODE_READ, d_tracer,
-			tr, &show_traces_fops);
+			  tr, &show_traces_fops);
 
-	trace_create_file("current_tracer", TRACE_MODE_WRITE, d_tracer,
-			tr, &set_tracer_fops);
+	trace_create_file("current_tracer", writable_mode, d_tracer,
+			  tr, &set_tracer_fops);
 
-	trace_create_file("tracing_cpumask", TRACE_MODE_WRITE, d_tracer,
+	trace_create_file("tracing_cpumask", writable_mode, d_tracer,
 			  tr, &tracing_cpumask_fops);
 
+	/* Options are used for changing print-format even for readonly instance. */
 	trace_create_file("trace_options", TRACE_MODE_WRITE, d_tracer,
 			  tr, &tracing_iter_fops);
 
@@ -9856,12 +9861,36 @@ init_tracer_tracefs(struct trace_array *tr, struct dentry *d_tracer)
 	trace_create_file("trace_pipe", TRACE_MODE_READ, d_tracer,
 			  tr, &tracing_pipe_fops);
 
-	trace_create_file("buffer_size_kb", TRACE_MODE_WRITE, d_tracer,
+	trace_create_file("buffer_size_kb", writable_mode, d_tracer,
 			  tr, &tracing_entries_fops);
 
 	trace_create_file("buffer_total_size_kb", TRACE_MODE_READ, d_tracer,
 			  tr, &tracing_total_entries_fops);
 
+	trace_create_file("trace_clock", writable_mode, d_tracer, tr,
+			  &trace_clock_fops);
+
+	trace_create_file("timestamp_mode", TRACE_MODE_READ, d_tracer, tr,
+			  &trace_time_stamp_mode_fops);
+
+	tr->buffer_percent = 50;
+
+	trace_create_file("buffer_subbuf_size_kb", writable_mode, d_tracer,
+			  tr, &buffer_subbuf_size_fops);
+
+	create_trace_options_dir(tr);
+
+	if (tr->range_addr_start)
+		trace_create_file("last_boot_info", TRACE_MODE_READ, d_tracer,
+				  tr, &last_boot_fops);
+
+	for_each_tracing_cpu(cpu)
+		tracing_init_tracefs_percpu(tr, cpu);
+
+	/* Read-only instance has above files only. */
+	if (trace_array_is_readonly(tr))
+		return;
+
 	trace_create_file("free_buffer", 0200, d_tracer,
 			  tr, &tracing_free_buffer_fops);
 
@@ -9873,49 +9902,29 @@ init_tracer_tracefs(struct trace_array *tr, struct dentry *d_tracer)
 	trace_create_file("trace_marker_raw", 0220, d_tracer,
 			  tr, &tracing_mark_raw_fops);
 
-	trace_create_file("trace_clock", TRACE_MODE_WRITE, d_tracer, tr,
-			  &trace_clock_fops);
-
-	trace_create_file("tracing_on", TRACE_MODE_WRITE, d_tracer,
-			  tr, &rb_simple_fops);
-
-	trace_create_file("timestamp_mode", TRACE_MODE_READ, d_tracer, tr,
-			  &trace_time_stamp_mode_fops);
-
-	tr->buffer_percent = 50;
-
 	trace_create_file("buffer_percent", TRACE_MODE_WRITE, d_tracer,
-			tr, &buffer_percent_fops);
-
-	trace_create_file("buffer_subbuf_size_kb", TRACE_MODE_WRITE, d_tracer,
-			  tr, &buffer_subbuf_size_fops);
+			  tr, &buffer_percent_fops);
 
 	trace_create_file("syscall_user_buf_size", TRACE_MODE_WRITE, d_tracer,
-			 tr, &tracing_syscall_buf_fops);
+			  tr, &tracing_syscall_buf_fops);
 
-	create_trace_options_dir(tr);
+	trace_create_file("tracing_on", TRACE_MODE_WRITE, d_tracer,
+			  tr, &rb_simple_fops);
 
 	trace_create_maxlat_file(tr, d_tracer);
 
 	if (ftrace_create_function_files(tr, d_tracer))
 		MEM_FAIL(1, "Could not allocate function filter files");
 
-	if (tr->range_addr_start) {
-		trace_create_file("last_boot_info", TRACE_MODE_READ, d_tracer,
-				  tr, &last_boot_fops);
 #ifdef CONFIG_TRACER_SNAPSHOT
-	} else {
+	if (!tr->range_addr_start)
 		trace_create_file("snapshot", TRACE_MODE_WRITE, d_tracer,
 				  tr, &snapshot_fops);
 #endif
-	}
 
 	trace_create_file("error_log", TRACE_MODE_WRITE, d_tracer,
 			  tr, &tracing_err_log_fops);
 
-	for_each_tracing_cpu(cpu)
-		tracing_init_tracefs_percpu(tr, cpu);
-
 	ftrace_init_tracefs(tr, d_tracer);
 }
 
@@ -10742,7 +10751,7 @@ __init static void enable_instances(void)
 		 * Backup buffers can be freed but need vfree().
 		 */
 		if (backup)
-			tr->flags |= TRACE_ARRAY_FL_VMALLOC;
+			tr->flags |= TRACE_ARRAY_FL_VMALLOC | TRACE_ARRAY_FL_RDONLY;
 
 		if (start || backup) {
 			tr->flags |= TRACE_ARRAY_FL_BOOT | TRACE_ARRAY_FL_LAST_BOOT;
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 649fdd20fc91..393be92768f1 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -459,6 +459,7 @@ enum {
 	TRACE_ARRAY_FL_MOD_INIT		= BIT(3),
 	TRACE_ARRAY_FL_MEMMAP		= BIT(4),
 	TRACE_ARRAY_FL_VMALLOC		= BIT(5),
+	TRACE_ARRAY_FL_RDONLY		= BIT(6),
 };
 
 #ifdef CONFIG_MODULES
@@ -488,6 +489,12 @@ extern unsigned long trace_adjust_address(struct trace_array *tr, unsigned long
 
 extern struct trace_array *printk_trace;
 
+static inline bool trace_array_is_readonly(struct trace_array *tr)
+{
+	/* backup instance is read only. */
+	return tr->flags & TRACE_ARRAY_FL_RDONLY;
+}
+
 /*
  * The global tracer (top) should be the first trace array added,
  * but we check the flag anyway.
diff --git a/kernel/trace/trace_boot.c b/kernel/trace/trace_boot.c
index dbe29b4c6a7a..2ca2541c8a58 100644
--- a/kernel/trace/trace_boot.c
+++ b/kernel/trace/trace_boot.c
@@ -61,7 +61,8 @@ trace_boot_set_instance_options(struct trace_array *tr, struct xbc_node *node)
 		v = memparse(p, NULL);
 		if (v < PAGE_SIZE)
 			pr_err("Buffer size is too small: %s\n", p);
-		if (tracing_resize_ring_buffer(tr, v, RING_BUFFER_ALL_CPUS) < 0)
+		if (trace_array_is_readonly(tr) ||
+		    tracing_resize_ring_buffer(tr, v, RING_BUFFER_ALL_CPUS) < 0)
 			pr_err("Failed to resize trace buffer to %s\n", p);
 	}
 
@@ -597,7 +598,7 @@ trace_boot_enable_tracer(struct trace_array *tr, struct xbc_node *node)
 
 	p = xbc_node_find_value(node, "tracer", NULL);
 	if (p && *p != '\0') {
-		if (tracing_set_tracer(tr, p) < 0)
+		if (trace_array_is_readonly(tr) || tracing_set_tracer(tr, p) < 0)
 			pr_err("Failed to set given tracer: %s\n", p);
 	}
 
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index 61fe01dce7a6..b493cbdf0ea0 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -1396,6 +1396,9 @@ static int __ftrace_set_clr_event(struct trace_array *tr, const char *match,
 {
 	int ret;
 
+	if (trace_array_is_readonly(tr))
+		return -EACCES;
+
 	mutex_lock(&event_mutex);
 	ret = __ftrace_set_clr_event_nolock(tr, match, sub, event, set, mod);
 	mutex_unlock(&event_mutex);
@@ -2968,8 +2971,8 @@ event_subsystem_dir(struct trace_array *tr, const char *name,
 	} else
 		__get_system(system);
 
-	/* ftrace only has directories no files */
-	if (strcmp(name, "ftrace") == 0)
+	/* ftrace only has directories no files, readonly instance too. */
+	if (strcmp(name, "ftrace") == 0 || trace_array_is_readonly(tr))
 		nr_entries = 0;
 	else
 		nr_entries = ARRAY_SIZE(system_entries);
@@ -3134,28 +3137,30 @@ event_create_dir(struct eventfs_inode *parent, struct trace_event_file *file)
 	int ret;
 	static struct eventfs_entry event_entries[] = {
 		{
-			.name		= "enable",
+			.name		= "format",
 			.callback	= event_callback,
-			.release	= event_release,
 		},
+#ifdef CONFIG_PERF_EVENTS
 		{
-			.name		= "filter",
+			.name		= "id",
 			.callback	= event_callback,
 		},
+#endif
+#define NR_RO_EVENT_ENTRIES	(1 + IS_ENABLED(CONFIG_PERF_EVENTS))
+/* Readonly files must be above this line and counted by NR_RO_EVENT_ENTRIES. */
 		{
-			.name		= "trigger",
+			.name		= "enable",
 			.callback	= event_callback,
+			.release	= event_release,
 		},
 		{
-			.name		= "format",
+			.name		= "filter",
 			.callback	= event_callback,
 		},
-#ifdef CONFIG_PERF_EVENTS
 		{
-			.name		= "id",
+			.name		= "trigger",
 			.callback	= event_callback,
 		},
-#endif
 #ifdef CONFIG_HIST_TRIGGERS
 		{
 			.name		= "hist",
@@ -3188,7 +3193,10 @@ event_create_dir(struct eventfs_inode *parent, struct trace_event_file *file)
 	if (!e_events)
 		return -ENOMEM;
 
-	nr_entries = ARRAY_SIZE(event_entries);
+	if (trace_array_is_readonly(tr))
+		nr_entries = NR_RO_EVENT_ENTRIES;
+	else
+		nr_entries = ARRAY_SIZE(event_entries);
 
 	name = trace_event_name(call);
 	ei = eventfs_create_dir(name, e_events, event_entries, nr_entries, file);
@@ -4527,31 +4535,44 @@ create_event_toplevel_files(struct dentry *parent, struct trace_array *tr)
 	int nr_entries;
 	static struct eventfs_entry events_entries[] = {
 		{
-			.name		= "enable",
+			.name		= "header_page",
 			.callback	= events_callback,
 		},
 		{
-			.name		= "header_page",
+			.name		= "header_event",
 			.callback	= events_callback,
 		},
+#define NR_RO_TOP_ENTRIES	2
+/* Readonly files must be above this line and counted by NR_RO_TOP_ENTRIES. */
 		{
-			.name		= "header_event",
+			.name		= "enable",
 			.callback	= events_callback,
 		},
 	};
 
-	entry = trace_create_file("set_event", TRACE_MODE_WRITE, parent,
-				  tr, &ftrace_set_event_fops);
-	if (!entry)
-		return -ENOMEM;
+	if (!trace_array_is_readonly(tr)) {
+		entry = trace_create_file("set_event", TRACE_MODE_WRITE, parent,
+					tr, &ftrace_set_event_fops);
+		if (!entry)
+			return -ENOMEM;
 
-	trace_create_file("show_event_filters", TRACE_MODE_READ, parent, tr,
-			  &ftrace_show_event_filters_fops);
+		/* There are not as crucial, just warn if they are not created */
+		trace_create_file("show_event_filters", TRACE_MODE_READ, parent, tr,
+				&ftrace_show_event_filters_fops);
 
-	trace_create_file("show_event_triggers", TRACE_MODE_READ, parent, tr,
-			  &ftrace_show_event_triggers_fops);
+		trace_create_file("show_event_triggers", TRACE_MODE_READ, parent, tr,
+				&ftrace_show_event_triggers_fops);
 
-	nr_entries = ARRAY_SIZE(events_entries);
+		trace_create_file("set_event_pid", TRACE_MODE_WRITE, parent,
+				tr, &ftrace_set_event_pid_fops);
+
+		trace_create_file("set_event_notrace_pid",
+				TRACE_MODE_WRITE, parent, tr,
+				&ftrace_set_event_notrace_pid_fops);
+		nr_entries = ARRAY_SIZE(events_entries);
+	} else {
+		nr_entries = NR_RO_TOP_ENTRIES;
+	}
 
 	e_events = eventfs_create_events_dir("events", parent, events_entries,
 					     nr_entries, tr);
@@ -4560,15 +4581,6 @@ create_event_toplevel_files(struct dentry *parent, struct trace_array *tr)
 		return -ENOMEM;
 	}
 
-	/* There are not as crucial, just warn if they are not created */
-
-	trace_create_file("set_event_pid", TRACE_MODE_WRITE, parent,
-			  tr, &ftrace_set_event_pid_fops);
-
-	trace_create_file("set_event_notrace_pid",
-			  TRACE_MODE_WRITE, parent, tr,
-			  &ftrace_set_event_notrace_pid_fops);
-
 	tr->event_dir = e_events;
 
 	return 0;


^ permalink raw reply related

* [PATCH v8 3/6] tracefs: Check file permission even if user has CAP_DAC_OVERRIDE
From: Masami Hiramatsu (Google) @ 2026-02-10  8:43 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: Masami Hiramatsu, Mathieu Desnoyers, linux-kernel,
	linux-trace-kernel
In-Reply-To: <177071300558.2293046.12057922262682243630.stgit@mhiramat.tok.corp.google.com>

From: Masami Hiramatsu (Google) <mhiramat@kernel.org>

Strictly checking the file read/write permission even if the owner has
CAP_DAC_OVERRIDE on tracefs as same as sysfs.
Tracefs is a pseudo filesystem, just like sysfs, so any file that the
system defines as unwritable should actually be unwritable by anyone.

Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
---
 fs/tracefs/event_inode.c |    2 ++
 fs/tracefs/inode.c       |   36 +++++++++++++++++++++++++++++++++---
 fs/tracefs/internal.h    |    3 +++
 3 files changed, 38 insertions(+), 3 deletions(-)

diff --git a/fs/tracefs/event_inode.c b/fs/tracefs/event_inode.c
index 61cbdafa2411..65e8be761e79 100644
--- a/fs/tracefs/event_inode.c
+++ b/fs/tracefs/event_inode.c
@@ -233,10 +233,12 @@ static int eventfs_set_attr(struct mnt_idmap *idmap, struct dentry *dentry,
 static const struct inode_operations eventfs_dir_inode_operations = {
 	.lookup		= eventfs_root_lookup,
 	.setattr	= eventfs_set_attr,
+	.permission	= tracefs_permission,
 };
 
 static const struct inode_operations eventfs_file_inode_operations = {
 	.setattr	= eventfs_set_attr,
+	.permission	= tracefs_permission,
 };
 
 static const struct file_operations eventfs_file_operations = {
diff --git a/fs/tracefs/inode.c b/fs/tracefs/inode.c
index d9d8932a7b9c..eb1ddc0cc13a 100644
--- a/fs/tracefs/inode.c
+++ b/fs/tracefs/inode.c
@@ -212,10 +212,40 @@ static void set_tracefs_inode_owner(struct inode *inode)
 		inode->i_gid = gid;
 }
 
-static int tracefs_permission(struct mnt_idmap *idmap,
-			      struct inode *inode, int mask)
+int tracefs_permission(struct mnt_idmap *idmap,
+		       struct inode *inode, int mask)
 {
-	set_tracefs_inode_owner(inode);
+	struct tracefs_inode *ti = get_tracefs(inode);
+	const struct file_operations *fops;
+
+	if (!(ti->flags & TRACEFS_EVENT_INODE))
+		set_tracefs_inode_owner(inode);
+
+	/*
+	 * Like sysfs, file permission checks are performed even for superuser
+	 * with CAP_DAC_OVERRIDE. See the KERNFS_ROOT_EXTRA_OPEN_PERM_CHECK
+	 * definition in linux/kernfs.h.
+	 */
+	if (mask & MAY_OPEN) {
+		fops = inode->i_fop;
+
+		if (mask & MAY_WRITE) {
+			if (!(inode->i_mode & 0222))
+				return -EACCES;
+			if (!fops || (!fops->write && !fops->write_iter &&
+				      !fops->mmap))
+				return -EACCES;
+		}
+
+		if (mask & MAY_READ) {
+			if (!(inode->i_mode & 0444))
+				return -EACCES;
+			if (!fops || (!fops->read && !fops->read_iter &&
+				      !fops->mmap && !fops->splice_read))
+				return -EACCES;
+		}
+	}
+
 	return generic_permission(idmap, inode, mask);
 }
 
diff --git a/fs/tracefs/internal.h b/fs/tracefs/internal.h
index d83c2a25f288..1e49ba445ba3 100644
--- a/fs/tracefs/internal.h
+++ b/fs/tracefs/internal.h
@@ -76,4 +76,7 @@ struct inode *tracefs_get_inode(struct super_block *sb);
 void eventfs_remount(struct tracefs_inode *ti, bool update_uid, bool update_gid);
 void eventfs_d_release(struct dentry *dentry);
 
+int tracefs_permission(struct mnt_idmap *idmap,
+		       struct inode *inode, int mask);
+
 #endif /* _TRACEFS_INTERNAL_H */


^ permalink raw reply related

* [PATCH v8 2/6] tracing: Reset last_boot_info if ring buffer is reset
From: Masami Hiramatsu (Google) @ 2026-02-10  8:43 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: Masami Hiramatsu, Mathieu Desnoyers, linux-kernel,
	linux-trace-kernel
In-Reply-To: <177071300558.2293046.12057922262682243630.stgit@mhiramat.tok.corp.google.com>

From: Masami Hiramatsu (Google) <mhiramat@kernel.org>

Commit 32dc0042528d ("tracing: Reset last-boot buffers when reading
out all cpu buffers") resets the last_boot_info when user read out
all data via trace_pipe* files. But it is not reset when user
resets the buffer from other files. (e.g. write `trace` file)

Reset it when the corresponding ring buffer is reset too.

Fixes: 32dc0042528d ("tracing: Reset last-boot buffers when reading out all cpu buffers")
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
---
Changes in v7:
 - Remove unneeded update_last_data_if_empty() call from
   tracing_snapshot_write() because snapshot is disabled on
   persistent instances.
---
 kernel/trace/trace.c |    6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index fd470675809b..e884d32b7895 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -4127,6 +4127,8 @@ static int tracing_single_release_tr(struct inode *inode, struct file *file)
 	return single_release(inode, file);
 }
 
+static bool update_last_data_if_empty(struct trace_array *tr);
+
 static int tracing_open(struct inode *inode, struct file *file)
 {
 	struct trace_array *tr = inode->i_private;
@@ -4151,6 +4153,8 @@ static int tracing_open(struct inode *inode, struct file *file)
 			tracing_reset_online_cpus(trace_buf);
 		else
 			tracing_reset_cpu(trace_buf, cpu);
+
+		update_last_data_if_empty(tr);
 	}
 
 	if (file->f_mode & FMODE_READ) {
@@ -5215,6 +5219,7 @@ tracing_set_trace_read(struct file *filp, char __user *ubuf,
 int tracer_init(struct tracer *t, struct trace_array *tr)
 {
 	tracing_reset_online_cpus(&tr->array_buffer);
+	update_last_data_if_empty(tr);
 	return t->init(tr);
 }
 
@@ -7028,6 +7033,7 @@ int tracing_set_clock(struct trace_array *tr, const char *clockstr)
 		ring_buffer_set_clock(tr->snapshot_buffer.buffer, trace_clocks[i].func);
 	tracing_reset_online_cpus(&tr->snapshot_buffer);
 #endif
+	update_last_data_if_empty(tr);
 
 	if (tr->scratch && !(tr->flags & TRACE_ARRAY_FL_LAST_BOOT)) {
 		struct trace_scratch *tscratch = tr->scratch;


^ permalink raw reply related


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