Linux Trace Kernel
 help / color / mirror / Atom feed
* Re: [PATCH v2 01/20] rv/rvgen: introduce AutomataError exception class
From: Gabriele Monaco @ 2026-02-05 12:08 UTC (permalink / raw)
  To: Wander Lairson Costa
  Cc: Steven Rostedt, Nam Cao, open list:RUNTIME VERIFICATION (RV),
	open list
In-Reply-To: <20260204144914.104028-2-wander@redhat.com>

On Wed, 2026-02-04 at 11:42 -0300, Wander Lairson Costa wrote:
> Replace the generic except Exception block with a custom AutomataError
> class that inherits from Exception. This provides more precise exception
> handling for automata parsing and validation errors while avoiding
> overly broad exception catches that could mask programming errors like
> SyntaxError or TypeError.
> 
> The AutomataError class is raised when DOT file processing fails due to
> invalid format, I/O errors, or malformed automaton definitions. The
> main entry point catches this specific exception and provides a
> user-friendly error message to stderr before exiting.
> 
> Signed-off-by: Wander Lairson Costa <wander@redhat.com>
[...]
> ---
> @@ -45,8 +52,8 @@ class Automata:
>          dot_lines = []
>          try:
>              dot_file = open(self.__dot_path)
> -        except:
> -            raise Exception("Cannot open the file: %s" % self.__dot_path)
> +        except OSError as exc:
> +            raise AutomataError(f"Cannot open the file: {self.__dot_path}")
> from exc
> 

You probably don't want to mask all OSError in main.py and allow only this one.
I think it's alright to keep a simpler message for wrong model file (also LTL!),
while throwing a splat in other cases (e.g. missing templates).

But wouldn't it be better to show the error message of the OSError? 99% of the
time it's going to be ENOENT, but could also be some EPERM or who knows what.
I'm fine keeping AutomataError here but would at least propagate the error
message.

Or keep it simple and catch all OSError as well, this one included.

Thanks,
Gabriele

>  
>          dot_lines = dot_file.read().splitlines()
>          dot_file.close()
> @@ -55,7 +62,7 @@ class Automata:
>          line = dot_lines[cursor].split()
>  
>          if (line[0] != "digraph") and (line[1] != "state_automaton"):
> -            raise Exception("Not a valid .dot format: %s" % self.__dot_path)
> +            raise AutomataError("Not a valid .dot format: %s" %
> self.__dot_path)
>          else:
>              cursor += 1
>          return dot_lines
> diff --git a/tools/verification/rvgen/rvgen/dot2c.py
> b/tools/verification/rvgen/rvgen/dot2c.py
> index 06a26bf15a7e9..74147ae2942f9 100644
> --- a/tools/verification/rvgen/rvgen/dot2c.py
> +++ b/tools/verification/rvgen/rvgen/dot2c.py
> @@ -13,7 +13,7 @@
>  # For further information, see:
>  #   Documentation/trace/rv/deterministic_automata.rst
>  
> -from .automata import Automata
> +from .automata import Automata, AutomataError
>  
>  class Dot2c(Automata):
>      enum_suffix = ""
> @@ -71,7 +71,7 @@ class Dot2c(Automata):
>              min_type = "unsigned int"
>  
>          if self.states.__len__() > 1000000:
> -            raise Exception("Too many states: %d" % self.states.__len__())
> +            raise AutomataError("Too many states: %d" %
> self.states.__len__())
>  
>          return min_type
>  
> diff --git a/tools/verification/rvgen/rvgen/generator.py
> b/tools/verification/rvgen/rvgen/generator.py
> index 3441385c11770..a7bee6b1ea70c 100644
> --- a/tools/verification/rvgen/rvgen/generator.py
> +++ b/tools/verification/rvgen/rvgen/generator.py
> @@ -51,10 +51,7 @@ class RVGenerator:
>          raise FileNotFoundError("Could not find the rv directory, do you have
> the kernel source installed?")
>  
>      def _read_file(self, path):
> -        try:
> -            fd = open(path, 'r')
> -        except OSError:
> -            raise Exception("Cannot open the file: %s" % path)
> +        fd = open(path, 'r')
>  
>          content = fd.read()
>  
> @@ -65,7 +62,7 @@ class RVGenerator:
>          try:
>              path = os.path.join(self.abs_template_dir, file)
>              return self._read_file(path)
> -        except Exception:
> +        except OSError:
>              # Specific template file not found. Try the generic template file
> in the template/
>              # directory, which is one level up
>              path = os.path.join(self.abs_template_dir, "..", file)


^ permalink raw reply

* Re: [PATCH v2 16/20] rv/rvgen: extract node marker string to class constant
From: Gabriele Monaco @ 2026-02-05 11:47 UTC (permalink / raw)
  To: Wander Lairson Costa
  Cc: Steven Rostedt, Nam Cao, open list:RUNTIME VERIFICATION (RV),
	open list
In-Reply-To: <20260204144914.104028-17-wander@redhat.com>

On Wed, 2026-02-04 at 11:42 -0300, Wander Lairson Costa wrote:
> Add a node_marker class constant to the Automata class to replace the
> hardcoded "{node" string literal used throughout the DOT file parsing
> logic. This follows the existing pattern established by the init_marker
> and invalid_state_str class constants in the same class.
> 
> The "{node" string is used as a marker to identify node declaration
> lines in DOT files during state variable extraction and cursor
> positioning. Extracting it to a named constant improves code
> maintainability and makes the marker's purpose explicit.
> 
> Signed-off-by: Wander Lairson Costa <wander@redhat.com>

Reviewed-by: Gabriele Monaco <gmonaco@redhat.com>

> ---
>  tools/verification/rvgen/rvgen/automata.py | 9 +++++----
>  1 file changed, 5 insertions(+), 4 deletions(-)
> 
> diff --git a/tools/verification/rvgen/rvgen/automata.py
> b/tools/verification/rvgen/rvgen/automata.py
> index 17b012b868531..270a3d0bf4ce7 100644
> --- a/tools/verification/rvgen/rvgen/automata.py
> +++ b/tools/verification/rvgen/rvgen/automata.py
> @@ -27,6 +27,7 @@ class Automata:
>  
>      invalid_state_str = "INVALID_STATE"
>      init_marker = "__init_"
> +    node_marker = "{node"
>  
>      def __init__(self, file_path, model_name=None):
>          self.__dot_path = file_path
> @@ -72,7 +73,7 @@ class Automata:
>          for cursor, line in enumerate(self.__dot_lines):
>              split_line = line.split()
>  
> -            if len(split_line) and split_line[0] == "{node":
> +            if len(split_line) and split_line[0] == self.node_marker:
>                  return cursor
>  
>          raise AutomataError("Could not find a beginning state")
> @@ -87,9 +88,9 @@ class Automata:
>                  continue
>  
>              if state == 0:
> -                if line[0] == "{node":
> +                if line[0] == self.node_marker:
>                      state = 1
> -            elif line[0] != "{node":
> +            elif line[0] != self.node_marker:
>                  break
>          else:
>              raise AutomataError("Could not find beginning event")
> @@ -111,7 +112,7 @@ class Automata:
>          # process nodes
>          for line in islice(self.__dot_lines, cursor, None):
>              split_line = line.split()
> -            if not split_line or split_line[0] != "{node":
> +            if not split_line or split_line[0] != self.node_marker:
>                  break
>  
>              raw_state = split_line[-1]

^ permalink raw reply

* Re: [PATCH v2 17/20] rv/rvgen: enforce presence of initial state
From: Gabriele Monaco @ 2026-02-05 11:44 UTC (permalink / raw)
  To: Wander Lairson Costa
  Cc: Steven Rostedt, Nam Cao, open list:RUNTIME VERIFICATION (RV),
	open list
In-Reply-To: <20260204144914.104028-18-wander@redhat.com>

On Wed, 2026-02-04 at 11:42 -0300, Wander Lairson Costa wrote:
> The __get_state_variables() method parses DOT files to identify the
> automaton's initial state. If the input file lacks a node with the
> required initialization prefix, the initial_state variable is referenced
> before assignment, causing an UnboundLocalError or a generic error
> during the state removal step.
> 
> Initialize the variable explicitly and validate that a start node was
> found after parsing. Raise a descriptive AutomataError if the definition
> is missing to improve debugging and ensure the automaton is valid.
> 
> Signed-off-by: Wander Lairson Costa <wander@redhat.com>

Reviewed-by: Gabriele Monaco <gmonaco@redhat.com>

> ---
>  tools/verification/rvgen/rvgen/automata.py | 4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/tools/verification/rvgen/rvgen/automata.py
> b/tools/verification/rvgen/rvgen/automata.py
> index 270a3d0bf4ce7..cf82f04dbc661 100644
> --- a/tools/verification/rvgen/rvgen/automata.py
> +++ b/tools/verification/rvgen/rvgen/automata.py
> @@ -105,6 +105,7 @@ class Automata:
>          # wait for node declaration
>          states = []
>          final_states = []
> +        initial_state = ""
>  
>          has_final_states = False
>          cursor = self.__get_cursor_begin_states()
> @@ -131,6 +132,9 @@ class Automata:
>                      final_states.append(state)
>                      has_final_states = True
>  
> +        if not initial_state:
> +            raise AutomataError("The automaton doesn't have an initial
> state")
> +
>          states = sorted(set(states))
>          states.remove(initial_state)
>  


^ permalink raw reply

* Re: [PATCH v2 18/20] rv/rvgen: fix unbound loop variable warning
From: Gabriele Monaco @ 2026-02-05 11:38 UTC (permalink / raw)
  To: Wander Lairson Costa
  Cc: Steven Rostedt, Nam Cao, open list:RUNTIME VERIFICATION (RV),
	open list
In-Reply-To: <20260204144914.104028-19-wander@redhat.com>

On Wed, 2026-02-04 at 11:42 -0300, Wander Lairson Costa wrote:
> Pyright static analysis reports a "possibly unbound variable" warning
> for the loop variable `i` in the `abbreviate_atoms` function. The
> variable is accessed after the inner loop terminates to slice the atom
> string. While the loop logic currently ensures execution, the analyzer
> flags the reliance on the loop variable persisting outside its scope.
> 
> Refactor the prefix length calculation into a nested `find_share_length`
> helper function. This encapsulates the search logic and uses explicit
> return statements, ensuring the length value is strictly defined. This
> satisfies the type checker and improves code readability without
> altering the runtime behavior.
> 
> Signed-off-by: Wander Lairson Costa <wander@redhat.com>

Looks good, that's probably the pythonic way then!

Reviewed-by: Gabriele Monaco <gmonaco@redhat.com>

> ---
>  tools/verification/rvgen/rvgen/ltl2k.py | 14 +++++++++-----
>  1 file changed, 9 insertions(+), 5 deletions(-)
> 
> diff --git a/tools/verification/rvgen/rvgen/ltl2k.py
> b/tools/verification/rvgen/rvgen/ltl2k.py
> index fa9ea6d597095..2c564cc937235 100644
> --- a/tools/verification/rvgen/rvgen/ltl2k.py
> +++ b/tools/verification/rvgen/rvgen/ltl2k.py
> @@ -43,13 +43,17 @@ def abbreviate_atoms(atoms: list[str]) -> list[str]:
>          skip = ["is", "by", "or", "and"]
>          return '_'.join([x[:2] for x in s.lower().split('_') if x not in
> skip])
>  
> -    abbrs = []
> -    for atom in atoms:
> +    def find_share_length(atom: str) -> int:
>          for i in range(len(atom), -1, -1):
>              if sum(a.startswith(atom[:i]) for a in atoms) > 1:
> -                break
> -        share = atom[:i]
> -        unique = atom[i:]
> +                return i
> +        return 0
> +
> +    abbrs = []
> +    for atom in atoms:
> +        share_len = find_share_length(atom)
> +        share = atom[:share_len]
> +        unique = atom[share_len:]
>          abbrs.append((shorten(share) + shorten(unique)))
>      return abbrs
>  


^ permalink raw reply

* Re: [PATCH v2 03/20] rv/rvgen: replace % string formatting with f-strings
From: Gabriele Monaco @ 2026-02-05 11:37 UTC (permalink / raw)
  To: Wander Lairson Costa
  Cc: Steven Rostedt, Nam Cao, open list:RUNTIME VERIFICATION (RV),
	open list
In-Reply-To: <20260204144914.104028-4-wander@redhat.com>

On Wed, 2026-02-04 at 11:42 -0300, Wander Lairson Costa wrote:
> Replace all instances of percent-style string formatting with
> f-strings across the rvgen codebase. This modernizes the string
> formatting to use Python 3.6+ features, providing clearer and more
> maintainable code while improving runtime performance.
> 
> The conversion handles all formatting cases including simple variable
> substitution, multi-variable formatting, and complex format specifiers.
> Dynamic width formatting is converted from "%*s" to "{var:>{width}}"
> using proper alignment syntax. Template strings for generated C code
> properly escape braces using double-brace syntax to produce literal
> braces in the output.
> 
> F-strings provide approximately 2x performance improvement over percent
> formatting and are the recommended approach in modern Python.
> 
> Signed-off-by: Wander Lairson Costa <wander@redhat.com>
> Reviewed-by: Nam Cao <namcao@linutronix.de>
> Reviewed-by: Gabriele Monaco <gmonaco@redhat.com>
> ---

There's a new one after the rebase, you may want to add this hunk:

diff --git a/tools/verification/rvgen/rvgen/dot2k.py
b/tools/verification/rvgen/rvgen/dot2k.py
index 4bf0db52e626..0d2cdfdf25eb 100644
--- a/tools/verification/rvgen/rvgen/dot2k.py
+++ b/tools/verification/rvgen/rvgen/dot2k.py
@@ -66,7 +66,7 @@ class dot2k(Monitor, Dot2c):
         buff.append(" *   Documentation/trace/rv/deterministic_automata.rst")
         buff.append(" */")
         buff.append("")
-        buff.append("#define MONITOR_NAME %s" % (self.name))
+        buff.append(f"#define MONITOR_NAME {self.name}")
         buff.append("")
 
         return buff

---

Thanks,
Gabriele

>  tools/verification/rvgen/__main__.py        |  6 +--
>  tools/verification/rvgen/rvgen/automata.py  |  6 +--
>  tools/verification/rvgen/rvgen/dot2c.py     | 38 ++++++-------
>  tools/verification/rvgen/rvgen/dot2k.py     | 26 ++++-----
>  tools/verification/rvgen/rvgen/generator.py | 59 ++++++++++-----------
>  tools/verification/rvgen/rvgen/ltl2k.py     | 30 +++++------
>  6 files changed, 81 insertions(+), 84 deletions(-)
> 
> diff --git a/tools/verification/rvgen/__main__.py
> b/tools/verification/rvgen/__main__.py
> index 3bd438f8476ed..50b7d4227fb16 100644
> --- a/tools/verification/rvgen/__main__.py
> +++ b/tools/verification/rvgen/__main__.py
> @@ -45,7 +45,7 @@ if __name__ == '__main__':
>  
>      try:
>          if params.subcmd == "monitor":
> -            print("Opening and parsing the specification file %s" %
> params.spec)
> +            print(f"Opening and parsing the specification file
> {params.spec}")
>              if params.monitor_class == "da":
>                  monitor = dot2k(params.spec, params.monitor_type,
> vars(params))
>              elif params.monitor_class == "ltl":
> @@ -59,11 +59,11 @@ if __name__ == '__main__':
>          print(f"There was an error processing {params.spec}: {e}",
> file=sys.stderr)
>          sys.exit(1)
>  
> -    print("Writing the monitor into the directory %s" % monitor.name)
> +    print(f"Writing the monitor into the directory {monitor.name}")
>      monitor.print_files()
>      print("Almost done, checklist")
>      if params.subcmd == "monitor":
> -        print("  - Edit the %s/%s.c to add the instrumentation" %
> (monitor.name, monitor.name))
> +        print(f"  - Edit the {monitor.name}/{monitor.name}.c to add the
> instrumentation")
>          print(monitor.fill_tracepoint_tooltip())
>      print(monitor.fill_makefile_tooltip())
>      print(monitor.fill_kconfig_tooltip())
> diff --git a/tools/verification/rvgen/rvgen/automata.py
> b/tools/verification/rvgen/rvgen/automata.py
> index 6ecd5ccd8f3d3..bd8c04526be3a 100644
> --- a/tools/verification/rvgen/rvgen/automata.py
> +++ b/tools/verification/rvgen/rvgen/automata.py
> @@ -39,11 +39,11 @@ class Automata:
>          basename = ntpath.basename(self.__dot_path)
>          if not basename.endswith(".dot") and not basename.endswith(".gv"):
>              print("not a dot file")
> -            raise AutomataError("not a dot file: %s" % self.__dot_path)
> +            raise AutomataError(f"not a dot file: {self.__dot_path}")
>  
>          model_name = ntpath.splitext(basename)[0]
>          if model_name.__len__() == 0:
> -            raise AutomataError("not a dot file: %s" % self.__dot_path)
> +            raise AutomataError(f"not a dot file: {self.__dot_path}")
>  
>          return model_name
>  
> @@ -62,7 +62,7 @@ class Automata:
>          line = dot_lines[cursor].split()
>  
>          if (line[0] != "digraph") and (line[1] != "state_automaton"):
> -            raise AutomataError("Not a valid .dot format: %s" %
> self.__dot_path)
> +            raise AutomataError(f"Not a valid .dot format:
> {self.__dot_path}")
>          else:
>              cursor += 1
>          return dot_lines
> diff --git a/tools/verification/rvgen/rvgen/dot2c.py
> b/tools/verification/rvgen/rvgen/dot2c.py
> index 74147ae2942f9..6a2ad4fbf7824 100644
> --- a/tools/verification/rvgen/rvgen/dot2c.py
> +++ b/tools/verification/rvgen/rvgen/dot2c.py
> @@ -28,17 +28,17 @@ class Dot2c(Automata):
>  
>      def __get_enum_states_content(self) -> list[str]:
>          buff = []
> -        buff.append("\t%s%s," % (self.initial_state, self.enum_suffix))
> +        buff.append(f"\t{self.initial_state}{self.enum_suffix},")
>          for state in self.states:
>              if state != self.initial_state:
> -                buff.append("\t%s%s," % (state, self.enum_suffix))
> -        buff.append("\tstate_max%s," % (self.enum_suffix))
> +                buff.append(f"\t{state}{self.enum_suffix},")
> +        buff.append(f"\tstate_max{self.enum_suffix},")
>  
>          return buff
>  
>      def format_states_enum(self) -> list[str]:
>          buff = []
> -        buff.append("enum %s {" % self.enum_states_def)
> +        buff.append(f"enum {self.enum_states_def} {{")
>          buff += self.__get_enum_states_content()
>          buff.append("};\n")
>  
> @@ -47,15 +47,15 @@ class Dot2c(Automata):
>      def __get_enum_events_content(self) -> list[str]:
>          buff = []
>          for event in self.events:
> -            buff.append("\t%s%s," % (event, self.enum_suffix))
> +            buff.append(f"\t{event}{self.enum_suffix},")
>  
> -        buff.append("\tevent_max%s," % self.enum_suffix)
> +        buff.append(f"\tevent_max{self.enum_suffix},")
>  
>          return buff
>  
>      def format_events_enum(self) -> list[str]:
>          buff = []
> -        buff.append("enum %s {" % self.enum_events_def)
> +        buff.append(f"enum {self.enum_events_def} {{")
>          buff += self.__get_enum_events_content()
>          buff.append("};\n")
>  
> @@ -71,25 +71,25 @@ class Dot2c(Automata):
>              min_type = "unsigned int"
>  
>          if self.states.__len__() > 1000000:
> -            raise AutomataError("Too many states: %d" %
> self.states.__len__())
> +            raise AutomataError(f"Too many states: {self.states.__len__()}")
>  
>          return min_type
>  
>      def format_automaton_definition(self) -> list[str]:
>          min_type = self.get_minimun_type()
>          buff = []
> -        buff.append("struct %s {" % self.struct_automaton_def)
> -        buff.append("\tchar *state_names[state_max%s];" % (self.enum_suffix))
> -        buff.append("\tchar *event_names[event_max%s];" % (self.enum_suffix))
> -        buff.append("\t%s function[state_max%s][event_max%s];" % (min_type,
> self.enum_suffix, self.enum_suffix))
> -        buff.append("\t%s initial_state;" % min_type)
> -        buff.append("\tbool final_states[state_max%s];" % (self.enum_suffix))
> +        buff.append(f"struct {self.struct_automaton_def} {{")
> +        buff.append(f"\tchar *state_names[state_max{self.enum_suffix}];")
> +        buff.append(f"\tchar *event_names[event_max{self.enum_suffix}];")
> +        buff.append(f"\t{min_type}
> function[state_max{self.enum_suffix}][event_max{self.enum_suffix}];")
> +        buff.append(f"\t{min_type} initial_state;")
> +        buff.append(f"\tbool final_states[state_max{self.enum_suffix}];")
>          buff.append("};\n")
>          return buff
>  
>      def format_aut_init_header(self) -> list[str]:
>          buff = []
> -        buff.append("static const struct %s %s = {" %
> (self.struct_automaton_def, self.var_automaton_def))
> +        buff.append(f"static const struct {self.struct_automaton_def}
> {self.var_automaton_def} = {{")
>          return buff
>  
>      def __get_string_vector_per_line_content(self, entries: list[str]) ->
> str:
> @@ -134,9 +134,9 @@ class Dot2c(Automata):
>                      next_state = self.function[x][y] + self.enum_suffix
>  
>                  if linetoolong:
> -                    line += "\t\t\t%s" % next_state
> +                    line += f"\t\t\t{next_state}"
>                  else:
> -                    line += "%*s" % (maxlen, next_state)
> +                    line += f"{next_state:>{maxlen}}"
>                  if y != nr_events-1:
>                      line += ",\n" if linetoolong else ", "
>                  else:
> @@ -180,7 +180,7 @@ class Dot2c(Automata):
>  
>      def format_aut_init_final_states(self) -> list[str]:
>         buff = []
> -       buff.append("\t.final_states = { %s }," %
> self.get_aut_init_final_states())
> +       buff.append(f"\t.final_states = {{ {self.get_aut_init_final_states()}
> }},")
>  
>         return buff
>  
> @@ -196,7 +196,7 @@ class Dot2c(Automata):
>  
>      def format_invalid_state(self) -> list[str]:
>          buff = []
> -        buff.append("#define %s state_max%s\n" % (self.invalid_state_str,
> self.enum_suffix))
> +        buff.append(f"#define {self.invalid_state_str}
> state_max{self.enum_suffix}\n")
>  
>          return buff
>  
> diff --git a/tools/verification/rvgen/rvgen/dot2k.py
> b/tools/verification/rvgen/rvgen/dot2k.py
> index 6128fe2384308..6d4151acc9fe3 100644
> --- a/tools/verification/rvgen/rvgen/dot2k.py
> +++ b/tools/verification/rvgen/rvgen/dot2k.py
> @@ -19,7 +19,7 @@ class dot2k(Monitor, Dot2c):
>          self.monitor_type = MonitorType
>          Monitor.__init__(self, extra_params)
>          Dot2c.__init__(self, file_path, extra_params.get("model_name"))
> -        self.enum_suffix = "_%s" % self.name
> +        self.enum_suffix = f"_{self.name}"
>  
>      def fill_monitor_type(self) -> str:
>          return self.monitor_type.upper()
> @@ -27,7 +27,7 @@ class dot2k(Monitor, Dot2c):
>      def fill_tracepoint_handlers_skel(self) -> str:
>          buff = []
>          for event in self.events:
> -            buff.append("static void handle_%s(void *data, /* XXX: fill
> header */)" % event)
> +            buff.append(f"static void handle_{event}(void *data, /* XXX: fill
> header */)")
>              buff.append("{")
>              handle = "handle_event"
>              if self.is_start_event(event):
> @@ -38,9 +38,9 @@ class dot2k(Monitor, Dot2c):
>                  handle = "handle_start_run_event"
>              if self.monitor_type == "per_task":
>                  buff.append("\tstruct task_struct *p = /* XXX: how do I get
> p? */;");
> -                buff.append("\tda_%s(p, %s%s);" % (handle, event,
> self.enum_suffix));
> +                buff.append(f"\tda_{handle}(p, {event}{self.enum_suffix});");
>              else:
> -                buff.append("\tda_%s(%s%s);" % (handle, event,
> self.enum_suffix));
> +                buff.append(f"\tda_{handle}({event}{self.enum_suffix});");
>              buff.append("}")
>              buff.append("")
>          return '\n'.join(buff)
> @@ -48,20 +48,20 @@ class dot2k(Monitor, Dot2c):
>      def fill_tracepoint_attach_probe(self) -> str:
>          buff = []
>          for event in self.events:
> -            buff.append("\trv_attach_trace_probe(\"%s\", /* XXX: tracepoint
> */, handle_%s);" % (self.name, event))
> +            buff.append(f"\trv_attach_trace_probe(\"{self.name}\", /* XXX:
> tracepoint */, handle_{event});")
>          return '\n'.join(buff)
>  
>      def fill_tracepoint_detach_helper(self) -> str:
>          buff = []
>          for event in self.events:
> -            buff.append("\trv_detach_trace_probe(\"%s\", /* XXX: tracepoint
> */, handle_%s);" % (self.name, event))
> +            buff.append(f"\trv_detach_trace_probe(\"{self.name}\", /* XXX:
> tracepoint */, handle_{event});")
>          return '\n'.join(buff)
>  
>      def fill_model_h_header(self) -> list[str]:
>          buff = []
>          buff.append("/* SPDX-License-Identifier: GPL-2.0 */")
>          buff.append("/*")
> -        buff.append(" * Automatically generated C representation of %s
> automaton" % (self.name))
> +        buff.append(f" * Automatically generated C representation of
> {self.name} automaton")
>          buff.append(" * For further information about this format, see kernel
> documentation:")
>          buff.append(" *   Documentation/trace/rv/deterministic_automata.rst")
>          buff.append(" */")
> @@ -75,10 +75,10 @@ class dot2k(Monitor, Dot2c):
>          #
>          # Adjust the definition names
>          #
> -        self.enum_states_def = "states_%s" % self.name
> -        self.enum_events_def = "events_%s" % self.name
> -        self.struct_automaton_def = "automaton_%s" % self.name
> -        self.var_automaton_def = "automaton_%s" % self.name
> +        self.enum_states_def = f"states_{self.name}"
> +        self.enum_events_def = f"events_{self.name}"
> +        self.struct_automaton_def = f"automaton_{self.name}"
> +        self.var_automaton_def = f"automaton_{self.name}"
>  
>          buff = self.fill_model_h_header()
>          buff += self.format_model()
> @@ -113,8 +113,8 @@ class dot2k(Monitor, Dot2c):
>              tp_args.insert(0, tp_args_id)
>          tp_proto_c = ", ".join([a+b for a,b in tp_args])
>          tp_args_c = ", ".join([b for a,b in tp_args])
> -        buff.append("	     TP_PROTO(%s)," % tp_proto_c)
> -        buff.append("	     TP_ARGS(%s)" % tp_args_c)
> +        buff.append(f"	     TP_PROTO({tp_proto_c}),")
> +        buff.append(f"	     TP_ARGS({tp_args_c})")
>          return '\n'.join(buff)
>  
>      def fill_main_c(self) -> str:
> diff --git a/tools/verification/rvgen/rvgen/generator.py
> b/tools/verification/rvgen/rvgen/generator.py
> index af1662e2c20a7..6d16fb68798a7 100644
> --- a/tools/verification/rvgen/rvgen/generator.py
> +++ b/tools/verification/rvgen/rvgen/generator.py
> @@ -40,7 +40,7 @@ class RVGenerator:
>          if platform.system() != "Linux":
>              raise OSError("I can only run on Linux.")
>  
> -        kernel_path = os.path.join("/lib/modules/%s/build" %
> platform.release(), self.rv_dir)
> +        kernel_path =
> os.path.join(f"/lib/modules/{platform.release()}/build", self.rv_dir)
>  
>          # if the current kernel is from a distro this may not be a full
> kernel tree
>          # verify that one of the files we are going to modify is available
> @@ -69,11 +69,11 @@ class RVGenerator:
>              return self._read_file(path)
>  
>      def fill_parent(self):
> -        return "&rv_%s" % self.parent if self.parent else "NULL"
> +        return f"&rv_{self.parent}" if self.parent else "NULL"
>  
>      def fill_include_parent(self):
>          if self.parent:
> -            return "#include <monitors/%s/%s.h>\n" % (self.parent,
> self.parent)
> +            return f"#include <monitors/{self.parent}/{self.parent}.h>\n"
>          return ""
>  
>      def fill_tracepoint_handlers_skel(self):
> @@ -119,7 +119,7 @@ class RVGenerator:
>          buff = []
>          buff.append("	# XXX: add dependencies if there")
>          if self.parent:
> -            buff.append("	depends on RV_MON_%s" % self.parent.upper())
> +            buff.append(f"	depends on RV_MON_{self.parent.upper()}")
>              buff.append("	default y")
>          return '\n'.join(buff)
>  
> @@ -145,31 +145,30 @@ class RVGenerator:
>          monitor_class_type = self.fill_monitor_class_type()
>          if self.auto_patch:
>              self._patch_file("rv_trace.h",
> -                            "// Add new monitors based on CONFIG_%s here" %
> monitor_class_type,
> -                            "#include <monitors/%s/%s_trace.h>" % (self.name,
> self.name))
> -            return "  - Patching %s/rv_trace.h, double check the result" %
> self.rv_dir
> +                            f"// Add new monitors based on
> CONFIG_{monitor_class_type} here",
> +                            f"#include
> <monitors/{self.name}/{self.name}_trace.h>")
> +            return f"  - Patching {self.rv_dir}/rv_trace.h, double check the
> result"
>  
> -        return """  - Edit %s/rv_trace.h:
> -Add this line where other tracepoints are included and %s is defined:
> -#include <monitors/%s/%s_trace.h>
> -""" % (self.rv_dir, monitor_class_type, self.name, self.name)
> +        return f"""  - Edit {self.rv_dir}/rv_trace.h:
> +Add this line where other tracepoints are included and {monitor_class_type}
> is defined:
> +#include <monitors/{self.name}/{self.name}_trace.h>
> +"""
>  
>      def _kconfig_marker(self, container=None) -> str:
> -        return "# Add new %smonitors here" % (container + " "
> -                                              if container else "")
> +        return f"# Add new {container + ' ' if container else ''}monitors
> here"
>  
>      def fill_kconfig_tooltip(self):
>          if self.auto_patch:
>              # monitors with a container should stay together in the Kconfig
>              self._patch_file("Kconfig",
>                               self._kconfig_marker(self.parent),
> -                            "source \"kernel/trace/rv/monitors/%s/Kconfig\""
> % (self.name))
> -            return "  - Patching %s/Kconfig, double check the result" %
> self.rv_dir
> +                            f"source
> \"kernel/trace/rv/monitors/{self.name}/Kconfig\"")
> +            return f"  - Patching {self.rv_dir}/Kconfig, double check the
> result"
>  
> -        return """  - Edit %s/Kconfig:
> +        return f"""  - Edit {self.rv_dir}/Kconfig:
>  Add this line where other monitors are included:
> -source \"kernel/trace/rv/monitors/%s/Kconfig\"
> -""" % (self.rv_dir, self.name)
> +source \"kernel/trace/rv/monitors/{self.name}/Kconfig\"
> +"""
>  
>      def fill_makefile_tooltip(self):
>          name = self.name
> @@ -177,18 +176,18 @@ source \"kernel/trace/rv/monitors/%s/Kconfig\"
>          if self.auto_patch:
>              self._patch_file("Makefile",
>                              "# Add new monitors here",
> -                            "obj-$(CONFIG_RV_MON_%s) += monitors/%s/%s.o" %
> (name_up, name, name))
> -            return "  - Patching %s/Makefile, double check the result" %
> self.rv_dir
> +                            f"obj-$(CONFIG_RV_MON_{name_up}) +=
> monitors/{name}/{name}.o")
> +            return f"  - Patching {self.rv_dir}/Makefile, double check the
> result"
>  
> -        return """  - Edit %s/Makefile:
> +        return f"""  - Edit {self.rv_dir}/Makefile:
>  Add this line where other monitors are included:
> -obj-$(CONFIG_RV_MON_%s) += monitors/%s/%s.o
> -""" % (self.rv_dir, name_up, name, name)
> +obj-$(CONFIG_RV_MON_{name_up}) += monitors/{name}/{name}.o
> +"""
>  
>      def fill_monitor_tooltip(self):
>          if self.auto_patch:
> -            return "  - Monitor created in %s/monitors/%s" % (self.rv_dir,
> self. name)
> -        return "  - Move %s/ to the kernel's monitor directory (%s/monitors)"
> % (self.name, self.rv_dir)
> +            return f"  - Monitor created in
> {self.rv_dir}/monitors/{self.name}"
> +        return f"  - Move {self.name}/ to the kernel's monitor directory
> ({self.rv_dir}/monitors)"
>  
>      def __create_directory(self):
>          path = self.name
> @@ -205,13 +204,13 @@ obj-$(CONFIG_RV_MON_%s) += monitors/%s/%s.o
>          file.close()
>  
>      def _create_file(self, file_name, content):
> -        path = "%s/%s" % (self.name, file_name)
> +        path = f"{self.name}/{file_name}"
>          if self.auto_patch:
>              path = os.path.join(self.rv_dir, "monitors", path)
>          self.__write_file(path, content)
>  
>      def __get_main_name(self):
> -        path = "%s/%s" % (self.name, "main.c")
> +        path = f"{self.name}/main.c"
>          if not os.path.exists(path):
>              return "main.c"
>          return "__main.c"
> @@ -221,11 +220,11 @@ obj-$(CONFIG_RV_MON_%s) += monitors/%s/%s.o
>  
>          self.__create_directory()
>  
> -        path = "%s.c" % self.name
> +        path = f"{self.name}.c"
>          self._create_file(path, main_c)
>  
>          model_h = self.fill_model_h()
> -        path = "%s.h" % self.name
> +        path = f"{self.name}.h"
>          self._create_file(path, model_h)
>  
>          kconfig = self.fill_kconfig()
> @@ -256,5 +255,5 @@ class Monitor(RVGenerator):
>      def print_files(self):
>          super().print_files()
>          trace_h = self.fill_trace_h()
> -        path = "%s_trace.h" % self.name
> +        path = f"{self.name}_trace.h"
>          self._create_file(path, trace_h)
> diff --git a/tools/verification/rvgen/rvgen/ltl2k.py
> b/tools/verification/rvgen/rvgen/ltl2k.py
> index b075f98d50c47..fa9ea6d597095 100644
> --- a/tools/verification/rvgen/rvgen/ltl2k.py
> +++ b/tools/verification/rvgen/rvgen/ltl2k.py
> @@ -73,7 +73,7 @@ class ltl2k(generator.Monitor):
>          ]
>  
>          for node in self.ba:
> -            buf.append("\tS%i," % node.id)
> +            buf.append(f"\tS{node.id},")
>          buf.append("\tRV_NUM_BA_STATES")
>          buf.append("};")
>          buf.append("static_assert(RV_NUM_BA_STATES <= RV_MAX_BA_STATES);")
> @@ -82,7 +82,7 @@ class ltl2k(generator.Monitor):
>      def _fill_atoms(self):
>          buf = ["enum ltl_atom {"]
>          for a in sorted(self.atoms):
> -            buf.append("\tLTL_%s," % a)
> +            buf.append(f"\tLTL_{a},")
>          buf.append("\tLTL_NUM_ATOM")
>          buf.append("};")
>          buf.append("static_assert(LTL_NUM_ATOM <= RV_MAX_LTL_ATOM);")
> @@ -96,7 +96,7 @@ class ltl2k(generator.Monitor):
>          ]
>  
>          for name in self.atoms_abbr:
> -            buf.append("\t\t\"%s\"," % name)
> +            buf.append(f"\t\t\"{name}\",")
>  
>          buf.extend([
>              "\t};",
> @@ -113,19 +113,19 @@ class ltl2k(generator.Monitor):
>                  continue
>  
>              if isinstance(node.op, ltl2ba.AndOp):
> -                buf.append("\tbool %s = %s && %s;" % (node, node.op.left,
> node.op.right))
> +                buf.append(f"\tbool {node} = {node.op.left} &&
> {node.op.right};")
>                  required_values |= {str(node.op.left), str(node.op.right)}
>              elif isinstance(node.op, ltl2ba.OrOp):
> -                buf.append("\tbool %s = %s || %s;" % (node, node.op.left,
> node.op.right))
> +                buf.append(f"\tbool {node} = {node.op.left} ||
> {node.op.right};")
>                  required_values |= {str(node.op.left), str(node.op.right)}
>              elif isinstance(node.op, ltl2ba.NotOp):
> -                buf.append("\tbool %s = !%s;" % (node, node.op.child))
> +                buf.append(f"\tbool {node} = !{node.op.child};")
>                  required_values.add(str(node.op.child))
>  
>          for atom in self.atoms:
>              if atom.lower() not in required_values:
>                  continue
> -            buf.append("\tbool %s = test_bit(LTL_%s, mon->atoms);" %
> (atom.lower(), atom))
> +            buf.append(f"\tbool {atom.lower()} = test_bit(LTL_{atom}, mon-
> >atoms);")
>  
>          buf.reverse()
>  
> @@ -153,7 +153,7 @@ class ltl2k(generator.Monitor):
>          ])
>  
>          for node in self.ba:
> -            buf.append("\tcase S%i:" % node.id)
> +            buf.append(f"\tcase S{node.id}:")
>  
>              for o in sorted(node.outgoing):
>                  line   = "\t\tif "
> @@ -163,7 +163,7 @@ class ltl2k(generator.Monitor):
>                  lines = break_long_line(line, indent)
>                  buf.extend(lines)
>  
> -                buf.append("\t\t\t__set_bit(S%i, next);" % o.id)
> +                buf.append(f"\t\t\t__set_bit(S{o.id}, next);")
>              buf.append("\t\tbreak;")
>          buf.extend([
>              "\t}",
> @@ -197,7 +197,7 @@ class ltl2k(generator.Monitor):
>              lines = break_long_line(line, indent)
>              buf.extend(lines)
>  
> -            buf.append("\t\t__set_bit(S%i, mon->states);" % node.id)
> +            buf.append(f"\t\t__set_bit(S{node.id}, mon->states);")
>          buf.append("}")
>          return buf
>  
> @@ -205,23 +205,21 @@ class ltl2k(generator.Monitor):
>          buff = []
>          buff.append("static void handle_example_event(void *data, /* XXX:
> fill header */)")
>          buff.append("{")
> -        buff.append("\tltl_atom_update(task, LTL_%s, true/false);" %
> self.atoms[0])
> +        buff.append(f"\tltl_atom_update(task, LTL_{self.atoms[0]},
> true/false);")
>          buff.append("}")
>          buff.append("")
>          return '\n'.join(buff)
>  
>      def fill_tracepoint_attach_probe(self):
> -        return "\trv_attach_trace_probe(\"%s\", /* XXX: tracepoint */,
> handle_example_event);" \
> -                % self.name
> +        return f"\trv_attach_trace_probe(\"{self.name}\", /* XXX: tracepoint
> */, handle_example_event);"
>  
>      def fill_tracepoint_detach_helper(self):
> -        return "\trv_detach_trace_probe(\"%s\", /* XXX: tracepoint */,
> handle_sample_event);" \
> -                % self.name
> +        return f"\trv_detach_trace_probe(\"{self.name}\", /* XXX: tracepoint
> */, handle_sample_event);"
>  
>      def fill_atoms_init(self):
>          buff = []
>          for a in self.atoms:
> -            buff.append("\tltl_atom_set(mon, LTL_%s, true/false);" % a)
> +            buff.append(f"\tltl_atom_set(mon, LTL_{a}, true/false);")
>          return '\n'.join(buff)
>  
>      def fill_model_h(self):

^ permalink raw reply related

* Re: [PATCH] uprobes: replace deprecated kmap_atomic() with kmap_local_page()
From: Carlos López @ 2026-02-05 11:27 UTC (permalink / raw)
  To: Oleg Nesterov
  Cc: linux-trace-kernel, linux-perf-users, Masami Hiramatsu,
	Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Namhyung Kim, Mark Rutland, Alexander Shishkin, Jiri Olsa,
	Ian Rogers, Adrian Hunter, James Clark, open list:UPROBES
In-Reply-To: <aYR-OM41gqRbEnKk@redhat.com>

On 2/5/26 12:25 PM, Oleg Nesterov wrote:
> Hi Carlos,
> 
> see
> 
> 	[PATCH 0/5] uprobes: transition from kmap_atomic to kmap_local_page
> 	https://lore.kernel.org/all/20260103084243.195125-1-ming.jvle@gmail.com/
> 
> already in tip/perf/core

Ah, looks like I was looking at the wrong tree, sorry for the noise.

^ permalink raw reply

* Re: [PATCH] uprobes: replace deprecated kmap_atomic() with kmap_local_page()
From: Oleg Nesterov @ 2026-02-05 11:25 UTC (permalink / raw)
  To: Carlos López
  Cc: linux-trace-kernel, linux-perf-users, Masami Hiramatsu,
	Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Namhyung Kim, Mark Rutland, Alexander Shishkin, Jiri Olsa,
	Ian Rogers, Adrian Hunter, James Clark, open list:UPROBES
In-Reply-To: <20260205105725.298340-1-clopez@suse.de>

Hi Carlos,

see

	[PATCH 0/5] uprobes: transition from kmap_atomic to kmap_local_page
	https://lore.kernel.org/all/20260103084243.195125-1-ming.jvle@gmail.com/

already in tip/perf/core

Oleg.

On 02/05, Carlos López wrote:
>
> kmap_atomic() has been deprecated for a few years, and kmap_local_page()
> should be used instead, so replace it. Since the uprobes code relied on
> kmap_atomic() disabling page faults to access user pages, add the
> required calls to keep the existing behavior.
>
> Signed-off-by: Carlos López <clopez@suse.de>
> ---
>  kernel/events/uprobes.c | 22 ++++++++++++++++------
>  1 file changed, 16 insertions(+), 6 deletions(-)
>
> diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
> index d546d32390a8..38898435acfe 100644
> --- a/kernel/events/uprobes.c
> +++ b/kernel/events/uprobes.c
> @@ -179,16 +179,24 @@ bool __weak is_trap_insn(uprobe_opcode_t *insn)
>
>  void uprobe_copy_from_page(struct page *page, unsigned long vaddr, void *dst, int len)
>  {
> -	void *kaddr = kmap_atomic(page);
> +	void *kaddr = kmap_local_page(page);
> +
> +	pagefault_disable();
>  	memcpy(dst, kaddr + (vaddr & ~PAGE_MASK), len);
> -	kunmap_atomic(kaddr);
> +	pagefault_enable();
> +
> +	kunmap_local(kaddr);
>  }
>
>  static void copy_to_page(struct page *page, unsigned long vaddr, const void *src, int len)
>  {
> -	void *kaddr = kmap_atomic(page);
> +	void *kaddr = kmap_local_page(page);
> +
> +	pagefault_disable();
>  	memcpy(kaddr + (vaddr & ~PAGE_MASK), src, len);
> -	kunmap_atomic(kaddr);
> +	pagefault_enable();
> +
> +	kunmap_local(kaddr);
>  }
>
>  static int verify_opcode(struct page *page, unsigned long vaddr, uprobe_opcode_t *insn,
> @@ -323,9 +331,10 @@ __update_ref_ctr(struct mm_struct *mm, unsigned long vaddr, short d)
>  		return ret == 0 ? -EBUSY : ret;
>  	}
>
> -	kaddr = kmap_atomic(page);
> +	kaddr = kmap_local_page(page);
>  	ptr = kaddr + (vaddr & ~PAGE_MASK);
>
> +	pagefault_disable();
>  	if (unlikely(*ptr + d < 0)) {
>  		pr_warn("ref_ctr going negative. vaddr: 0x%lx, "
>  			"curr val: %d, delta: %d\n", vaddr, *ptr, d);
> @@ -336,7 +345,8 @@ __update_ref_ctr(struct mm_struct *mm, unsigned long vaddr, short d)
>  	*ptr += d;
>  	ret = 0;
>  out:
> -	kunmap_atomic(kaddr);
> +	pagefault_enable();
> +	kunmap_local(kaddr);
>  	put_page(page);
>  	return ret;
>  }
>
> base-commit: f14faaf3a1fb3b9e4cf2e56269711fb85fba9458
> --
> 2.51.0
>


^ permalink raw reply

* Re: [PATCH] uprobes: replace deprecated kmap_atomic() with kmap_local_page()
From: Carlos López @ 2026-02-05 11:19 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: linux-trace-kernel, linux-perf-users, Masami Hiramatsu,
	Oleg Nesterov, Ingo Molnar, Arnaldo Carvalho de Melo,
	Namhyung Kim, Mark Rutland, Alexander Shishkin, Jiri Olsa,
	Ian Rogers, Adrian Hunter, James Clark, open list:UPROBES
In-Reply-To: <20260205111208.GK232055@noisy.programming.kicks-ass.net>

Hi,

On 2/5/26 12:12 PM, Peter Zijlstra wrote:
> On Thu, Feb 05, 2026 at 11:57:25AM +0100, Carlos López wrote:
>> kmap_atomic() has been deprecated for a few years, and kmap_local_page()
>> should be used instead, so replace it. Since the uprobes code relied on
>> kmap_atomic() disabling page faults to access user pages, add the
>> required calls to keep the existing behavior.
> 
> Are those pagefault_disable()s really needed here, or is this just
> cargo-culting?

The subsystem experts can correct me, but it seems to me this code is
primarily accessing user memory, e.g. is_trap_at_addr() ->
get_user_pages() -> uprobe_copy_from_page().

^ permalink raw reply

* Re: [PATCH] uprobes: replace deprecated kmap_atomic() with kmap_local_page()
From: Peter Zijlstra @ 2026-02-05 11:12 UTC (permalink / raw)
  To: Carlos López
  Cc: linux-trace-kernel, linux-perf-users, Masami Hiramatsu,
	Oleg Nesterov, Ingo Molnar, Arnaldo Carvalho de Melo,
	Namhyung Kim, Mark Rutland, Alexander Shishkin, Jiri Olsa,
	Ian Rogers, Adrian Hunter, James Clark, open list:UPROBES
In-Reply-To: <20260205105725.298340-1-clopez@suse.de>

On Thu, Feb 05, 2026 at 11:57:25AM +0100, Carlos López wrote:
> kmap_atomic() has been deprecated for a few years, and kmap_local_page()
> should be used instead, so replace it. Since the uprobes code relied on
> kmap_atomic() disabling page faults to access user pages, add the
> required calls to keep the existing behavior.

Are those pagefault_disable()s really needed here, or is this just
cargo-culting?

> Signed-off-by: Carlos López <clopez@suse.de>
> ---
>  kernel/events/uprobes.c | 22 ++++++++++++++++------
>  1 file changed, 16 insertions(+), 6 deletions(-)
> 
> diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
> index d546d32390a8..38898435acfe 100644
> --- a/kernel/events/uprobes.c
> +++ b/kernel/events/uprobes.c
> @@ -179,16 +179,24 @@ bool __weak is_trap_insn(uprobe_opcode_t *insn)
>  
>  void uprobe_copy_from_page(struct page *page, unsigned long vaddr, void *dst, int len)
>  {
> -	void *kaddr = kmap_atomic(page);
> +	void *kaddr = kmap_local_page(page);
> +
> +	pagefault_disable();
>  	memcpy(dst, kaddr + (vaddr & ~PAGE_MASK), len);
> -	kunmap_atomic(kaddr);
> +	pagefault_enable();
> +
> +	kunmap_local(kaddr);
>  }
>  
>  static void copy_to_page(struct page *page, unsigned long vaddr, const void *src, int len)
>  {
> -	void *kaddr = kmap_atomic(page);
> +	void *kaddr = kmap_local_page(page);
> +
> +	pagefault_disable();
>  	memcpy(kaddr + (vaddr & ~PAGE_MASK), src, len);
> -	kunmap_atomic(kaddr);
> +	pagefault_enable();
> +
> +	kunmap_local(kaddr);
>  }
>  
>  static int verify_opcode(struct page *page, unsigned long vaddr, uprobe_opcode_t *insn,
> @@ -323,9 +331,10 @@ __update_ref_ctr(struct mm_struct *mm, unsigned long vaddr, short d)
>  		return ret == 0 ? -EBUSY : ret;
>  	}
>  
> -	kaddr = kmap_atomic(page);
> +	kaddr = kmap_local_page(page);
>  	ptr = kaddr + (vaddr & ~PAGE_MASK);
>  
> +	pagefault_disable();
>  	if (unlikely(*ptr + d < 0)) {
>  		pr_warn("ref_ctr going negative. vaddr: 0x%lx, "
>  			"curr val: %d, delta: %d\n", vaddr, *ptr, d);
> @@ -336,7 +345,8 @@ __update_ref_ctr(struct mm_struct *mm, unsigned long vaddr, short d)
>  	*ptr += d;
>  	ret = 0;
>  out:
> -	kunmap_atomic(kaddr);
> +	pagefault_enable();
> +	kunmap_local(kaddr);
>  	put_page(page);
>  	return ret;
>  }
> 
> base-commit: f14faaf3a1fb3b9e4cf2e56269711fb85fba9458
> -- 
> 2.51.0
> 

^ permalink raw reply

* [PATCH] uprobes: replace deprecated kmap_atomic() with kmap_local_page()
From: Carlos López @ 2026-02-05 10:57 UTC (permalink / raw)
  To: linux-trace-kernel, linux-perf-users
  Cc: Carlos López, Masami Hiramatsu, Oleg Nesterov,
	Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Namhyung Kim, Mark Rutland, Alexander Shishkin, Jiri Olsa,
	Ian Rogers, Adrian Hunter, James Clark, open list:UPROBES

kmap_atomic() has been deprecated for a few years, and kmap_local_page()
should be used instead, so replace it. Since the uprobes code relied on
kmap_atomic() disabling page faults to access user pages, add the
required calls to keep the existing behavior.

Signed-off-by: Carlos López <clopez@suse.de>
---
 kernel/events/uprobes.c | 22 ++++++++++++++++------
 1 file changed, 16 insertions(+), 6 deletions(-)

diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index d546d32390a8..38898435acfe 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -179,16 +179,24 @@ bool __weak is_trap_insn(uprobe_opcode_t *insn)
 
 void uprobe_copy_from_page(struct page *page, unsigned long vaddr, void *dst, int len)
 {
-	void *kaddr = kmap_atomic(page);
+	void *kaddr = kmap_local_page(page);
+
+	pagefault_disable();
 	memcpy(dst, kaddr + (vaddr & ~PAGE_MASK), len);
-	kunmap_atomic(kaddr);
+	pagefault_enable();
+
+	kunmap_local(kaddr);
 }
 
 static void copy_to_page(struct page *page, unsigned long vaddr, const void *src, int len)
 {
-	void *kaddr = kmap_atomic(page);
+	void *kaddr = kmap_local_page(page);
+
+	pagefault_disable();
 	memcpy(kaddr + (vaddr & ~PAGE_MASK), src, len);
-	kunmap_atomic(kaddr);
+	pagefault_enable();
+
+	kunmap_local(kaddr);
 }
 
 static int verify_opcode(struct page *page, unsigned long vaddr, uprobe_opcode_t *insn,
@@ -323,9 +331,10 @@ __update_ref_ctr(struct mm_struct *mm, unsigned long vaddr, short d)
 		return ret == 0 ? -EBUSY : ret;
 	}
 
-	kaddr = kmap_atomic(page);
+	kaddr = kmap_local_page(page);
 	ptr = kaddr + (vaddr & ~PAGE_MASK);
 
+	pagefault_disable();
 	if (unlikely(*ptr + d < 0)) {
 		pr_warn("ref_ctr going negative. vaddr: 0x%lx, "
 			"curr val: %d, delta: %d\n", vaddr, *ptr, d);
@@ -336,7 +345,8 @@ __update_ref_ctr(struct mm_struct *mm, unsigned long vaddr, short d)
 	*ptr += d;
 	ret = 0;
 out:
-	kunmap_atomic(kaddr);
+	pagefault_enable();
+	kunmap_local(kaddr);
 	put_page(page);
 	return ret;
 }

base-commit: f14faaf3a1fb3b9e4cf2e56269711fb85fba9458
-- 
2.51.0


^ permalink raw reply related

* Re: [PATCH 2/2] tracing: resolve enum names for function arguments via BTF
From: Donglin Peng @ 2026-02-05  9:21 UTC (permalink / raw)
  To: Alexei Starovoitov
  Cc: Steven Rostedt, Andrii Nakryiko, Alexei Starovoitov,
	Masami Hiramatsu, LKML, Donglin Peng, linux-trace-kernel, bpf,
	Eduard Zingerman
In-Reply-To: <CAErzpmu9mNXTOw-WwkSGEdvmJY2VjyUbGWZD=5s6kXNRE_YkJQ@mail.gmail.com>

On Wed, Feb 4, 2026 at 10:52 PM Donglin Peng <dolinux.peng@gmail.com> wrote:
>
> On Wed, Feb 4, 2026 at 12:00 AM Alexei Starovoitov
> <alexei.starovoitov@gmail.com> wrote:
> >
> > On Tue, Feb 3, 2026 at 7:16 AM Steven Rostedt <rostedt@goodmis.org> wrote:
> > >
> > > On Tue, 3 Feb 2026 21:50:47 +0800
> > > Donglin Peng <dolinux.peng@gmail.com> wrote:
> > >
> > > > Testing revealed that sorting within resolve_btfids introduces issues with
> > > > btf__dedup. Therefore, I plan to move the sorting logic directly into
> > > > btf__add_enum_value and btf__add_enum64_value in libbpf, which are
> > > > invoked by pahole. However, it means that we need a newer pahole
> > > > version.
> > >
> > > Sorting isn't a requirement just something I wanted to bring up. If it's
> > > too complex and doesn't achieve much benefit then let's not do it.
> > >
> > > My worry is because "cat trace" takes quite a long time just reading the
> > > BTF arguments. I'm worried it will just get worse with enums as well.
> > >
> > > I have trace-cmd reading BTF now (just haven't officially released it) and
> > > doing an extract and reading the trace.dat file is much faster than reading
> > > the trace file with arguments. I'll need to implement the enum logic too in
> > > libtraceevent.
> >
> > If you mean to do pretty printing of the trace in user space then +1 from me.
> >
> > I don't like sorting enums either in resolve_btfid, pahole or kernel.
> > Sorted BTF by name was ok, since it doesn't change original semantics.
> > While sorting enums by value gets us to the grey zone where
> > the sequence of enum names in vmlinux.h becomes different than in dwarf.
>
> Thanks, I agreed.
>
> >
> > Also id->name mapping in general is not precise.
> > There is no requirement for enums to be unique.
> > Just grabbing the first one:
> > ATA_PIO0 = 1,
> > ATA_PIO1 = 3,
> > ATA_PIO2 = 7,
> > ATA_UDMA0 = 1,
> > ATA_UDMA1 = 3,
> > ATA_UDMA2 = 7,
> > ATA_ID_CYLS = 1,
> > ATA_ID_HEADS = 3,
> > SCR_ERROR = 1,
> > SCR_CONTROL = 2,
> > SCR_ACTIVE = 3,
> >
> > All these names are part of the same enum type.
> > Which one to print? First one?

Another option is to print all matching entries, incurring increased
overhead and extended trace log length. However, I prefer printing
the first matching entry, though it might be inaccurate in rare cases.

>
> I think these cases are not very common and printing the first
> one would be helpful enough, and we can add documentation
> notes in ftrace to guide users.
>
> >
> > another example:
> > enum {
> >         BPF_LOCAL_STORAGE_GET_F_CREATE = 1,
> >         BPF_SK_STORAGE_GET_F_CREATE = 1,
> > };
> >
> > and another:
> > enum {
> >         BPF_SKB_TSTAMP_UNSPEC = 0,
> >         BPF_SKB_TSTAMP_DELIVERY_MONO = 1,
> >         BPF_SKB_CLOCK_REALTIME = 0,
> >         BPF_SKB_CLOCK_MONOTONIC = 1,
> >         BPF_SKB_CLOCK_TAI = 2,
> > };
> >
> > I'd rather not print any and keep it integer only.
> >
> > pw-bot: cr

^ permalink raw reply

* Re: [RFC bpf-next 06/12] bpf: Add bpf_trampoline_multi_attach/detach functions
From: Menglong Dong @ 2026-02-05  9:16 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, bpf,
	linux-trace-kernel, Martin KaFai Lau, Eduard Zingerman, Song Liu,
	Yonghong Song, Menglong Dong, Steven Rostedt
In-Reply-To: <20260203093819.2105105-7-jolsa@kernel.org>

On 2026/2/3 17:38 Jiri Olsa <jolsa@kernel.org> write:
> Adding bpf_trampoline_multi_attach/detach functions that allows
> to attach/detach multi tracing trampoline.
> 
> The attachment is defined with bpf_program and array of BTF ids
> of functions to attach the bpf program to.
> 
[...]
> @@ -367,7 +367,11 @@ static struct bpf_trampoline *bpf_trampoline_lookup(u64 key, unsigned long ip)
>  	head = &trampoline_ip_table[hash_64(tr->ip, TRAMPOLINE_HASH_BITS)];
>  	hlist_add_head(&tr->hlist_ip, head);
>  	refcount_set(&tr->refcnt, 1);
> +#ifdef CONFIG_LOCKDEP
> +	mutex_init_with_key(&tr->mutex, &__lockdep_no_track__);
> +#else
>  	mutex_init(&tr->mutex);
> +#endif
>  	for (i = 0; i < BPF_TRAMP_MAX; i++)
>  		INIT_HLIST_HEAD(&tr->progs_hlist[i]);
>  out:
> @@ -1400,6 +1404,188 @@ int __weak arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags,
>  	return -ENOTSUPP;
>  }
>  
> +#if defined(CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS) && defined(CONFIG_HAVE_SINGLE_FTRACE_DIRECT_OPS)

Hi, Jiri. It's great to see your tracing_multi link finally. It looks great ;)

After analyzing a little deeper on the SINGLE_FTRACE_DIRECT_OPS, I
understand why it is only supported on x86_64 for now. It seems that
it's a little hard to implement it in the other arch, as we need to
restructure the implement of ftrace direct call.

So do we need some more ftrace API here to make the tracing multi-link
independent from SINGLE_FTRACE_DIRECT_OPS? Otherwise, we can only
use it on x86_64.

Have you ever tried to implement the SINGLE_FTRACE_DIRECT_OPS on arm64?
The direct call on arm64 is so complex, and I didn't work it out :/

Thanks!
Menglong Dong

> +
> +struct fentry_multi_data {
> +	struct ftrace_hash *unreg;
> +	struct ftrace_hash *modify;
> +	struct ftrace_hash *reg;
> +};
> +
[...]
> 
> 
> 





^ permalink raw reply

* Re: [RFC bpf-next 08/12] libbpf: Add btf__find_by_glob_kind function
From: Jiri Olsa @ 2026-02-05  8:57 UTC (permalink / raw)
  To: Andrii Nakryiko
  Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, bpf,
	linux-trace-kernel, Martin KaFai Lau, Eduard Zingerman, Song Liu,
	Yonghong Song, Menglong Dong, Steven Rostedt
In-Reply-To: <CAEf4BzY7zZmEqFq577NiG2wh0aU0_og1_RjVSURjaqTOnTc-Bw@mail.gmail.com>

On Wed, Feb 04, 2026 at 11:04:09AM -0800, Andrii Nakryiko wrote:
> On Tue, Feb 3, 2026 at 1:39 AM Jiri Olsa <jolsa@kernel.org> wrote:
> >
> > Adding btf__find_by_glob_kind function that returns array of
> > BTF ids that match given kind and allow/deny patterns.
> >
> > int btf__find_by_glob_kind(const struct btf *btf, __u32 kind,
> >                            const char *allow_pattern,
> >                            const char *deny_pattern,
> >                            __u32 **__ids);
> >
> > The __ids array is allocated and needs to be manually freed.
> >
> > The pattern check is done by glob_match function.
> >
> > Signed-off-by: Jiri Olsa <jolsa@kernel.org>
> > ---
> >  tools/lib/bpf/btf.c | 41 +++++++++++++++++++++++++++++++++++++++++
> >  tools/lib/bpf/btf.h |  3 +++
> >  2 files changed, 44 insertions(+)
> >
> > diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
> > index 83fe79ffcb8f..64502b3ef38a 100644
> > --- a/tools/lib/bpf/btf.c
> > +++ b/tools/lib/bpf/btf.c
> > @@ -1010,6 +1010,47 @@ __s32 btf__find_by_name_kind(const struct btf *btf, const char *type_name,
> >         return btf_find_by_name_kind(btf, 1, type_name, kind);
> >  }
> >
> > +int btf__find_by_glob_kind(const struct btf *btf, __u32 kind,
> > +                          const char *allow_pattern, const char *deny_pattern,
> > +                          __u32 **__ids)
> > +{
> > +       __u32 i, nr_types = btf__type_cnt(btf);
> > +       int cnt = 0, alloc = 0;
> > +       __u32 *ids = NULL;
> > +
> > +       for (i = 1; i < nr_types; i++) {
> > +               const struct btf_type *t = btf__type_by_id(btf, i);
> > +               const char *name;
> > +               __u32 *p;
> > +
> > +               if (btf_kind(t) != kind)
> > +                       continue;
> > +               name = btf__name_by_offset(btf, t->name_off);
> > +               if (!name)
> > +                       continue;
> > +
> > +               if (deny_pattern && glob_match(name, deny_pattern))
> > +                       continue;
> > +               if (allow_pattern && !glob_match(name, allow_pattern))
> > +                       continue;
> > +
> > +               if (cnt == alloc) {
> > +                       alloc = max(16, alloc * 3 / 2);
> > +                       p = libbpf_reallocarray(ids, alloc, sizeof(__u32));
> > +                       if (!p) {
> > +                               free(ids);
> > +                               return -ENOMEM;
> > +                       }
> > +                       ids = p;
> > +               }
> > +               ids[cnt] = i;
> > +               cnt++;
> > +       }
> > +
> > +       *__ids = ids;
> > +       return cnt;
> > +}
> > +
> >  static bool btf_is_modifiable(const struct btf *btf)
> >  {
> >         return (void *)btf->hdr != btf->raw_data;
> > diff --git a/tools/lib/bpf/btf.h b/tools/lib/bpf/btf.h
> > index b30008c267c0..d7b47bb0ba99 100644
> > --- a/tools/lib/bpf/btf.h
> > +++ b/tools/lib/bpf/btf.h
> > @@ -661,6 +661,9 @@ static inline struct btf_decl_tag *btf_decl_tag(const struct btf_type *t)
> >         return (struct btf_decl_tag *)(t + 1);
> >  }
> >
> > +int btf__find_by_glob_kind(const struct btf *btf, __u32 kind,
> > +                          const char *allow_pattern, const char *deny_pattern,
> > +                          __u32 **__ids);
> 
> 
> as AI pointed out, this should be an internal helper, no? Let's also
> not use double underscore pattern here,
> "collect_btf_ids_by_glob_kind()" perhaps?

ok

> 
> Also, you don't seem to be using deny_pattern, where you planning to?

the tests are just rudimentary before we agree we want to do it this way

but I'm not sure I have a usecase for deny_pattern.. I think we added it
just to be complete, I recall we copied that function from somewhere,
it's long time ago ;-)

> 
> Also, are there functions that we'll have BTF for, but they won't be
> attachable? What if I do SEC("fentry.multi/*")? Will it attach or fail
> to attach some functions (and thus fail the overall attachment)?

yes, for the benchmark tests I had to add is_allowed_func which mimics
btf_distill_func_proto and denies attach for some functions

also I had to filter out some core kernel functions like rcu*,trace*,..
which seemed to cause trouble when you attach them

jirka

^ permalink raw reply

* Re: [RFC bpf-next 04/12] bpf: Add struct bpf_tramp_node object
From: Jiri Olsa @ 2026-02-05  8:57 UTC (permalink / raw)
  To: Andrii Nakryiko
  Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, bpf,
	linux-trace-kernel, Martin KaFai Lau, Eduard Zingerman, Song Liu,
	Yonghong Song, Menglong Dong, Steven Rostedt
In-Reply-To: <CAEf4BzYWxmg7YO_ewENt1rr4R1YT=iL0fc5yJqanfQZJk6u1nQ@mail.gmail.com>

On Wed, Feb 04, 2026 at 11:00:57AM -0800, Andrii Nakryiko wrote:
> On Tue, Feb 3, 2026 at 1:39 AM Jiri Olsa <jolsa@kernel.org> wrote:
> >
> > Adding struct bpf_tramp_node to decouple the link out of the trampoline
> > attachment info.
> >
> > At the moment the object for attaching bpf program to the trampoline is
> > 'struct bpf_tramp_link':
> >
> >   struct bpf_tramp_link {
> >        struct bpf_link link;
> >        struct hlist_node tramp_hlist;
> >        u64 cookie;
> >   }
> >
> > The link holds the bpf_prog pointer and forces one link - one program
> > binding logic. In following changes we want to attach program to multiple
> > trampolines but have just one bpf_link object.
> >
> > Splitting struct bpf_tramp_link into:
> >
> >   struct bpf_tramp_link {
> >        struct bpf_link link;
> >        struct bpf_tramp_node node;
> >   };
> >
> >   struct bpf_tramp_node {
> >        struct hlist_node tramp_hlist;
> >        struct bpf_prog *prog;
> >        u64 cookie;
> >   };
> 
> I'm a bit confused here. For singular fentry/fexit attachment we have
> one trampoline and one program, right? For multi-fentry, we have
> multiple trampoline, but still one program pointer, no? So why put a
> prog pointer into tramp_node?.. You do want cookie in tramp_node, yes,
> but not the program.

yes, but both links:
  - single link 'struct bpf_tramp_link'
  - multi link  'struct bpf_tracing_multi_link'

are using same code to attach that code needs to have a hlist_node to
link the program to the trampoline and be able to reach the bpf_prog
(like in invoke_bpf_prog)

current code is passing whole bpf_tramp_link object so it has access
to both, but multi link needs to keep link to each trampoline (nodes
below):

struct bpf_tracing_multi_link {
       struct bpf_link link;
       enum bpf_attach_type attach_type;
       int nodes_cnt;
       struct bpf_tracing_multi_node nodes[] __counted_by(nodes_cnt);
};

and we can't get get from &nodes[x] to bpf_tracing_multi_link.link.prog

it's bit redundant, but not sure what else we can do

> Because then there is also a question what is
> bpf_link's prog pointing to?...

bpf_link.prog is still keeping the prog, I don't think we can remove that

jirka

> 
> 
> >
> > where 'struct bpf_tramp_link' defines standard single trampoline link,
> > and 'struct bpf_tramp_node' is the attachment trampoline object. This
> > will allow us to define link for multiple trampolines, like:
> >
> >   struct bpf_tracing_multi_link {
> >        struct bpf_link link;
> >        ...
> >        int nodes_cnt;
> >        struct bpf_tracing_multi_node nodes[] __counted_by(nodes_cnt);
> >   };
> >
> > Signed-off-by: Jiri Olsa <jolsa@kernel.org>
> > ---
> >  arch/arm64/net/bpf_jit_comp.c  |  58 +++++++++----------
> >  arch/s390/net/bpf_jit_comp.c   |  42 +++++++-------
> >  arch/x86/net/bpf_jit_comp.c    |  54 ++++++++---------
> >  include/linux/bpf.h            |  47 ++++++++-------
> >  kernel/bpf/bpf_struct_ops.c    |  24 ++++----
> >  kernel/bpf/syscall.c           |  25 ++++----
> >  kernel/bpf/trampoline.c        | 102 ++++++++++++++++-----------------
> >  net/bpf/bpf_dummy_struct_ops.c |  11 ++--
> >  8 files changed, 185 insertions(+), 178 deletions(-)
> >
> 
> [...]

^ permalink raw reply

* Re: [RFC bpf-next 00/12] bpf: tracing_multi link
From: Jiri Olsa @ 2026-02-05  8:55 UTC (permalink / raw)
  To: Alexei Starovoitov
  Cc: Jiri Olsa, Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
	bpf, linux-trace-kernel, Martin KaFai Lau, Eduard Zingerman,
	Song Liu, Yonghong Song, Menglong Dong, Steven Rostedt
In-Reply-To: <CAADnVQJPbnVEDYAAy4mUP7NmsGkUmeV9B73V+Bc=LYb8r8Zrow@mail.gmail.com>

On Wed, Feb 04, 2026 at 08:06:50AM -0800, Alexei Starovoitov wrote:
> On Wed, Feb 4, 2026 at 4:36 AM Jiri Olsa <olsajiri@gmail.com> wrote:
> >
> > On Tue, Feb 03, 2026 at 03:17:05PM -0800, Alexei Starovoitov wrote:
> > > On Tue, Feb 3, 2026 at 1:38 AM Jiri Olsa <jolsa@kernel.org> wrote:
> > > >
> > > > hi,
> > > > as an option to Meglong's change [1] I'm sending proposal for tracing_multi
> > > > link that does not add static trampoline but attaches program to all needed
> > > > trampolines.
> > > >
> > > > This approach keeps the same performance but has some drawbacks:
> > > >
> > > >  - when attaching 20k functions we allocate and attach 20k trampolines
> > > >  - during attachment we hold each trampoline mutex, so for above
> > > >    20k functions we will hold 20k mutexes during the attachment,
> > > >    should be very prone to deadlock, but haven't hit it yet
> > >
> > > If you check that it's sorted and always take them in the same order
> > > then there will be no deadlock.
> > > Or just grab one global mutex first and then grab trampolines mutexes
> > > next in any order. The global one will serialize this attach operation.
> > >
> > > > It looks the trampoline allocations/generation might not be big a problem
> > > > and I'll try to find a solution for holding that many mutexes. If there's
> > > > no better solution I think having one read/write mutex for tracing multi
> > > > link attach/detach should work.
> > >
> > > If you mean to have one global mutex as I proposed above then I don't see
> > > a downside. It only serializes multiple libbpf calls.
> >
> > we also need to serialize it with standard single trampoline attach,
> > because the direct ftrace update is now done under trampoline->mutex:
> >
> >   bpf_trampoline_link_prog(tr)
> >   {
> >     mutex_lock(&tr->mutex);
> >     ...
> >     update_ftrace_direct_*
> >     ...
> >     mutex_unlock(&tr->mutex);
> >   }
> >
> > for tracing_multi we would link the program first (with tr->mutex)
> > and do the bulk ftrace update later (without tr->mutex)
> >
> >   {
> >     for each involved trampoline:
> >       bpf_trampoline_link_prog
> >
> >     --> and here we could race with some other thread doing single
> >         trampoline attach
> >
> >     update_ftrace_direct_*
> >   }
> >
> > note the current version locks all tr->mutex instances all the way
> > through the update_ftrace_direct_* update
> >
> > I think we could use global rwsem and take read lock on single
> > trampoline attach path and write lock on tracing_multi attach,
> >
> > I thought we could take direct_mutex early, but that would mean
> > different order with trampoline mutex than we already have in
> > single attach path
> 
> I feel we're talking past each other.
> I meant:
> 
> For multi:
> 1. take some global mutex
> 2. take N tramp mutexes in any order
> 
> For single:
> 1. take that 1 specific tramp mutex.

ah ok, I understand, it's to prevent the lockup but keep holding all
the trampolines locks.. the rwsem I mentioned was for the 'fix', where
we do not take all the trampolines locks

thanks,
jirka

^ permalink raw reply

* Re: [RFC bpf-next 07/12] bpf: Add support to create tracing multi link
From: Jiri Olsa @ 2026-02-05  8:55 UTC (permalink / raw)
  To: Andrii Nakryiko
  Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, bpf,
	linux-trace-kernel, Martin KaFai Lau, Eduard Zingerman, Song Liu,
	Yonghong Song, Menglong Dong, Steven Rostedt
In-Reply-To: <CAEf4BzYsE3W8QvtKBOZZWGudFjXJ-_szUZOejT-Ab5v72Sei+A@mail.gmail.com>

On Wed, Feb 04, 2026 at 11:05:09AM -0800, Andrii Nakryiko wrote:
> On Tue, Feb 3, 2026 at 1:39 AM Jiri Olsa <jolsa@kernel.org> wrote:
> >
> > Adding new link to allow to attach program to multiple function
> > BTF IDs. The link is represented by struct bpf_tracing_multi_link.
> >
> > To configure the link, new fields are added to bpf_attr::link_create
> > to pass array of BTF IDs;
> >
> >   struct {
> >       __aligned_u64   btf_ids;        /* addresses to attach */
> >       __u32           btf_ids_cnt;    /* addresses count */
> 
> cookies suspiciously missing?

right, need to be added, no mystery there ;-)

we will just assign it to the bpf_tramp_node object for each trampoline/id

thanks,
jirka


> 
> >   } tracing_multi;
> >
> > Each BTF ID represents function (BTF_KIND_FUNC) that the link will
> > attach bpf program to.
> >
> > We use previously added bpf_trampoline_multi_attach/detach functions
> > to attach/detach the link.
> >
> > Signed-off-by: Jiri Olsa <jolsa@kernel.org>
> > ---
> >  include/linux/trace_events.h   |   6 ++
> >  include/uapi/linux/bpf.h       |   5 ++
> >  kernel/bpf/syscall.c           |   2 +
> >  kernel/trace/bpf_trace.c       | 105 +++++++++++++++++++++++++++++++++
> >  tools/include/uapi/linux/bpf.h |   5 ++
> >  5 files changed, 123 insertions(+)
> >
> 
> [...]

^ permalink raw reply

* Re: [PATCH v2 20/20] rv/rvgen: add missing return type annotations
From: Gabriele Monaco @ 2026-02-05  7:24 UTC (permalink / raw)
  To: Wander Lairson Costa
  Cc: Steven Rostedt, Nam Cao, open list:RUNTIME VERIFICATION (RV),
	open list
In-Reply-To: <20260204144914.104028-21-wander@redhat.com>

On Wed, 2026-02-04 at 11:42 -0300, Wander Lairson Costa wrote:
> Add missing `-> str` return type annotations to code generation
> methods in RVGenerator. These methods return strings, and the missing
> hints caused errors with static analysis tools.
> 
> Signed-off-by: Wander Lairson Costa <wander@redhat.com>
> ---
>  tools/verification/rvgen/rvgen/generator.py | 16 ++++++++--------
>  1 file changed, 8 insertions(+), 8 deletions(-)
> 
> diff --git a/tools/verification/rvgen/rvgen/generator.py
> b/tools/verification/rvgen/rvgen/generator.py
> index ef6c9150f50c6..4b984869a7b3d 100644
> --- a/tools/verification/rvgen/rvgen/generator.py
> +++ b/tools/verification/rvgen/rvgen/generator.py
> @@ -73,13 +73,13 @@ class RVGenerator:
>              return f"#include <monitors/{self.parent}/{self.parent}.h>\n"
>          return ""
>  
> -    def fill_tracepoint_handlers_skel(self):
> +    def fill_tracepoint_handlers_skel(self) -> str:
>          return "NotImplemented"

Those are the ones that will raise an exception in a later iteration of this,
right? I wonder if we really need to touch them now.
Anyway I'm fine with this if it pleases your tools, thanks.

Reviewed-by: Gabriele Monaco <gmonaco@redhat.com>

>  
> -    def fill_tracepoint_attach_probe(self):
> +    def fill_tracepoint_attach_probe(self) -> str:
>          return "NotImplemented"
>  
> -    def fill_tracepoint_detach_helper(self):
> +    def fill_tracepoint_detach_helper(self) -> str:
>          return "NotImplemented"
>  
>      def fill_main_c(self):
> @@ -100,19 +100,19 @@ class RVGenerator:
>  
>          return main_c
>  
> -    def fill_model_h(self):
> +    def fill_model_h(self) -> str:
>          return "NotImplemented"
>  
> -    def fill_monitor_class_type(self):
> +    def fill_monitor_class_type(self) -> str:
>          return "NotImplemented"
>  
> -    def fill_monitor_class(self):
> +    def fill_monitor_class(self) -> str:
>          return "NotImplemented"
>  
> -    def fill_tracepoint_args_skel(self, tp_type):
> +    def fill_tracepoint_args_skel(self, tp_type) -> str:
>          return "NotImplemented"
>  
> -    def fill_monitor_deps(self):
> +    def fill_monitor_deps(self) -> str:
>          buff = []
>          buff.append("	# XXX: add dependencies if there")
>          if self.parent:


^ permalink raw reply

* Re: [PATCH v2 19/20] rv/rvgen: fix _fill_states() return type annotation
From: Gabriele Monaco @ 2026-02-05  7:24 UTC (permalink / raw)
  To: Wander Lairson Costa
  Cc: Steven Rostedt, Nam Cao, open list:RUNTIME VERIFICATION (RV),
	open list
In-Reply-To: <20260204144914.104028-20-wander@redhat.com>

On Wed, 2026-02-04 at 11:42 -0300, Wander Lairson Costa wrote:
> The _fill_states() method returns a list of strings, but the type
> annotation incorrectly specified str. Update the annotation to
> list[str] to match the actual return value.
> 
> Signed-off-by: Wander Lairson Costa <wander@redhat.com>
> ---

Looks good, thanks. I would keep all annotation changes together (i.e. squash
with the next patch), but if you prefer this way, I'm fine too.

Reviewed-by: Gabriele Monaco <gmonaco@redhat.com>

>  tools/verification/rvgen/rvgen/ltl2k.py | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/tools/verification/rvgen/rvgen/ltl2k.py
> b/tools/verification/rvgen/rvgen/ltl2k.py
> index 2c564cc937235..de765b8486bd1 100644
> --- a/tools/verification/rvgen/rvgen/ltl2k.py
> +++ b/tools/verification/rvgen/rvgen/ltl2k.py
> @@ -71,7 +71,7 @@ class ltl2k(generator.Monitor):
>          if not self.name:
>              self.name = Path(file_path).stem
>  
> -    def _fill_states(self) -> str:
> +    def _fill_states(self) -> list[str]:
>          buf = [
>              "enum ltl_buchi_state {",
>          ]


^ permalink raw reply

* Re: [RFC PATCH v1 05/37] KVM: guest_memfd: Wire up kvm_get_memory_attributes() to per-gmem attributes
From: Xu Yilun @ 2026-02-05  7:04 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: Sean Christopherson, Ackerley Tng, Alexey Kardashevskiy, cgroups,
	kvm, linux-doc, linux-fsdevel, linux-kernel, linux-kselftest,
	linux-mm, linux-trace-kernel, x86, akpm, binbin.wu, bp, brauner,
	chao.p.peng, chenhuacai, corbet, dave.hansen, dave.hansen, david,
	dmatlack, erdemaktas, fan.du, fvdl, haibo1.xu, hannes, hch, hpa,
	hughd, ira.weiny, isaku.yamahata, jack, james.morse, jarkko,
	jgowans, jhubbard, jroedel, jthoughton, jun.miao, kai.huang,
	keirf, kent.overstreet, liam.merwick, maciej.wieczor-retman, mail,
	maobibo, mathieu.desnoyers, maz, mhiramat, mhocko, mic,
	michael.roth, mingo, mlevitsk, mpe, muchun.song, nikunj, nsaenz,
	oliver.upton, palmer, pankaj.gupta, paul.walmsley, pbonzini,
	peterx, pgonda, prsampat, pvorel, qperret, richard.weiyang,
	rick.p.edgecombe, rientjes, rostedt, roypat, rppt, shakeel.butt,
	shuah, steven.price, steven.sistare, suzuki.poulose, tabba, tglx,
	thomas.lendacky, vannapurve, vbabka, viro, vkuznets, wei.w.wang,
	will, willy, wyihan, xiaoyao.li, yan.y.zhao, yilun.xu, yuzenghui,
	zhiquan1.li
In-Reply-To: <20260204124715.GA2328995@ziepe.ca>

On Wed, Feb 04, 2026 at 08:47:15AM -0400, Jason Gunthorpe wrote:
> On Wed, Feb 04, 2026 at 12:43:16PM +0800, Xu Yilun wrote:
> > > Which means we need VFIO to know what they are, and hopefully it is
> > > just static based on the TDISP reports..
> > 
> > I don't think VMM need to check TDISP report. The only special thing is
> > the MSI-X mixed pages which can be figured out by standard PCI
> > discovery.
> 
> Either that or follow along with the guests's choices on
> shared/private.
> 
> We can't let VFIO mmap a private MMIO page, so it has to know which
> pages are private at any moment, and it can't guess.

No we could only let VFIO mmap MMIO pages that need emulation (like this
MSI-X mixed page). MMIOs in such page cannot be assigned to guest so no
way to convert to private.

We don't allow VFIO mmap all asigned MMIO pages, no matter they will be
private or shared. They are assigned to guest, so host don't touch them.
Does that make sense?

> 
> Jason

^ permalink raw reply

* Re: [PATCH v2 07/20] rv/rvgen: fix typos in automata and generator docstring and comments
From: Gabriele Monaco @ 2026-02-05  7:03 UTC (permalink / raw)
  To: Wander Lairson Costa
  Cc: Steven Rostedt, Nam Cao, open list:RUNTIME VERIFICATION (RV),
	open list
In-Reply-To: <20260204144914.104028-8-wander@redhat.com>

On Wed, 2026-02-04 at 11:42 -0300, Wander Lairson Costa wrote:
> Fix two typos in the Automata class documentation that have been
> present since the initial implementation. Fix the class
> docstring: "part it" instead of "parses it". Additionally, a
> comment describing transition labels contained the misspelling
> "lables" instead of "labels".
> 
> Fix a typo in the comment describing the insertion of the initial
> state into the states list: "bein og" should be "beginning of".
> 
> Fix typo in the module docstring: "Abtract" should be "Abstract".
> 
> Signed-off-by: Wander Lairson Costa <wander@redhat.com>


While you're at it there are a few singular/plural inconsistencies, see below.

Other than that it looks good, thanks!

Reviewed-by: Gabriele Monaco <gmonaco@redhat.com>


> ---
>  tools/verification/rvgen/rvgen/automata.py  | 6 +++---
>  tools/verification/rvgen/rvgen/generator.py | 2 +-
>  2 files changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/tools/verification/rvgen/rvgen/automata.py
> b/tools/verification/rvgen/rvgen/automata.py
> index 1feb5f0c0bc3e..0d7cbd0c634a9 100644
> --- a/tools/verification/rvgen/rvgen/automata.py
> +++ b/tools/verification/rvgen/rvgen/automata.py
> @@ -18,7 +18,7 @@ class AutomataError(Exception):
>      """
>  
>  class Automata:
> -    """Automata class: Reads a dot file and part it as an automata.
> +    """Automata class: Reads a dot file and parses it as an automata.
>  

Automata is plural, the singular is automaton (you can keep the class name
unchanged): 

+    """Automata class: Reads a dot file and parses it as an automaton.

>      Attributes:
>          dot_file: A dot file with an state_automaton definition.
> @@ -113,7 +113,7 @@ class Automata:
>          states = sorted(set(states))
>          states.remove(initial_state)
>  
> -        # Insert the initial state at the bein og the states
> +        # Insert the initial state at the beginning of the states
>          states.insert(0, initial_state)
>  
>          if not has_final_states:
> @@ -134,7 +134,7 @@ class Automata:
>                  line = self.__dot_lines[cursor].split()
>                  event = line[-2].replace('"','')
>  
> -                # when a transition has more than one lables, they are like
> this
> +                # when a transition has more than one labels, they are like
> this

This should be "more than one label" as singular.

>                  # "local_irq_enable\nhw_local_irq_enable_n"
>                  # so split them.
>  
> diff --git a/tools/verification/rvgen/rvgen/generator.py
> b/tools/verification/rvgen/rvgen/generator.py
> index ee75e111feef1..a3fbb1ac74916 100644
> --- a/tools/verification/rvgen/rvgen/generator.py
> +++ b/tools/verification/rvgen/rvgen/generator.py
> @@ -3,7 +3,7 @@
>  #
>  # Copyright (C) 2019-2022 Red Hat, Inc. Daniel Bristot de Oliveira
> <bristot@kernel.org>
>  #
> -# Abtract class for generating kernel runtime verification monitors from
> specification file
> +# Abstract class for generating kernel runtime verification monitors from
> specification file
>  
>  import platform
>  import os


^ permalink raw reply

* Re: [PATCH v2 01/20] rv/rvgen: introduce AutomataError exception class
From: Gabriele Monaco @ 2026-02-05  6:50 UTC (permalink / raw)
  To: Wander Lairson Costa, Nam Cao
  Cc: Steven Rostedt, open list:RUNTIME VERIFICATION (RV), open list
In-Reply-To: <20260204144914.104028-2-wander@redhat.com>

On Wed, 2026-02-04 at 11:42 -0300, Wander Lairson Costa wrote:
> Replace the generic except Exception block with a custom AutomataError
> class that inherits from Exception. This provides more precise exception
> handling for automata parsing and validation errors while avoiding
> overly broad exception catches that could mask programming errors like
> SyntaxError or TypeError.
> 
> The AutomataError class is raised when DOT file processing fails due to
> invalid format, I/O errors, or malformed automaton definitions. The
> main entry point catches this specific exception and provides a
> user-friendly error message to stderr before exiting.
> 
> Signed-off-by: Wander Lairson Costa <wander@redhat.com>

Looks very good, thanks.
Now I wonder though why is LTL not included in the change. ltl2ba.py raises a
few ValueError that should probably be treated just like these AutomataError.
You could either create a new exception class or share the same for all model
errors (DA and LTL).

What do you think?

Thanks,
Gabriele

> ---
>  tools/verification/rvgen/__main__.py        |  9 ++++++---
>  tools/verification/rvgen/rvgen/automata.py  | 17 ++++++++++++-----
>  tools/verification/rvgen/rvgen/dot2c.py     |  4 ++--
>  tools/verification/rvgen/rvgen/generator.py |  7 ++-----
>  4 files changed, 22 insertions(+), 15 deletions(-)
> 
> diff --git a/tools/verification/rvgen/__main__.py
> b/tools/verification/rvgen/__main__.py
> index fa6fc1f4de2f7..3bd438f8476ed 100644
> --- a/tools/verification/rvgen/__main__.py
> +++ b/tools/verification/rvgen/__main__.py
> @@ -8,11 +8,15 @@
>  # For further information, see:
>  #   Documentation/trace/rv/da_monitor_synthesis.rst
>  
> +from sys import stderr
> +
> +
>  if __name__ == '__main__':
>      from rvgen.dot2k import dot2k
>      from rvgen.generator import Monitor
>      from rvgen.container import Container
>      from rvgen.ltl2k import ltl2k
> +    from rvgen.automata import AutomataError
>      import argparse
>      import sys
>  
> @@ -51,9 +55,8 @@ if __name__ == '__main__':
>                  sys.exit(1)
>          else:
>              monitor = Container(vars(params))
> -    except Exception as e:
> -        print('Error: '+ str(e))
> -        print("Sorry : :-(")
> +    except AutomataError as e:
> +        print(f"There was an error processing {params.spec}: {e}",
> file=sys.stderr)
>          sys.exit(1)
>  
>      print("Writing the monitor into the directory %s" % monitor.name)
> diff --git a/tools/verification/rvgen/rvgen/automata.py
> b/tools/verification/rvgen/rvgen/automata.py
> index 3f06aef8d4fdc..6ecd5ccd8f3d3 100644
> --- a/tools/verification/rvgen/rvgen/automata.py
> +++ b/tools/verification/rvgen/rvgen/automata.py
> @@ -10,6 +10,13 @@
>  
>  import ntpath
>  
> +class AutomataError(Exception):
> +    """Exception raised for errors in automata parsing and validation.
> +
> +    Raised when DOT file processing fails due to invalid format, I/O errors,
> +    or malformed automaton definitions.
> +    """
> +
>  class Automata:
>      """Automata class: Reads a dot file and part it as an automata.
>  
> @@ -32,11 +39,11 @@ class Automata:
>          basename = ntpath.basename(self.__dot_path)
>          if not basename.endswith(".dot") and not basename.endswith(".gv"):
>              print("not a dot file")
> -            raise Exception("not a dot file: %s" % self.__dot_path)
> +            raise AutomataError("not a dot file: %s" % self.__dot_path)
>  
>          model_name = ntpath.splitext(basename)[0]
>          if model_name.__len__() == 0:
> -            raise Exception("not a dot file: %s" % self.__dot_path)
> +            raise AutomataError("not a dot file: %s" % self.__dot_path)
>  
>          return model_name
>  
> @@ -45,8 +52,8 @@ class Automata:
>          dot_lines = []
>          try:
>              dot_file = open(self.__dot_path)
> -        except:
> -            raise Exception("Cannot open the file: %s" % self.__dot_path)
> +        except OSError as exc:
> +            raise AutomataError(f"Cannot open the file: {self.__dot_path}")
> from exc
>  
>          dot_lines = dot_file.read().splitlines()
>          dot_file.close()
> @@ -55,7 +62,7 @@ class Automata:
>          line = dot_lines[cursor].split()
>  
>          if (line[0] != "digraph") and (line[1] != "state_automaton"):
> -            raise Exception("Not a valid .dot format: %s" % self.__dot_path)
> +            raise AutomataError("Not a valid .dot format: %s" %
> self.__dot_path)
>          else:
>              cursor += 1
>          return dot_lines
> diff --git a/tools/verification/rvgen/rvgen/dot2c.py
> b/tools/verification/rvgen/rvgen/dot2c.py
> index 06a26bf15a7e9..74147ae2942f9 100644
> --- a/tools/verification/rvgen/rvgen/dot2c.py
> +++ b/tools/verification/rvgen/rvgen/dot2c.py
> @@ -13,7 +13,7 @@
>  # For further information, see:
>  #   Documentation/trace/rv/deterministic_automata.rst
>  
> -from .automata import Automata
> +from .automata import Automata, AutomataError
>  
>  class Dot2c(Automata):
>      enum_suffix = ""
> @@ -71,7 +71,7 @@ class Dot2c(Automata):
>              min_type = "unsigned int"
>  
>          if self.states.__len__() > 1000000:
> -            raise Exception("Too many states: %d" % self.states.__len__())
> +            raise AutomataError("Too many states: %d" %
> self.states.__len__())
>  
>          return min_type
>  
> diff --git a/tools/verification/rvgen/rvgen/generator.py
> b/tools/verification/rvgen/rvgen/generator.py
> index 3441385c11770..a7bee6b1ea70c 100644
> --- a/tools/verification/rvgen/rvgen/generator.py
> +++ b/tools/verification/rvgen/rvgen/generator.py
> @@ -51,10 +51,7 @@ class RVGenerator:
>          raise FileNotFoundError("Could not find the rv directory, do you have
> the kernel source installed?")
>  
>      def _read_file(self, path):
> -        try:
> -            fd = open(path, 'r')
> -        except OSError:
> -            raise Exception("Cannot open the file: %s" % path)
> +        fd = open(path, 'r')
>  
>          content = fd.read()
>  
> @@ -65,7 +62,7 @@ class RVGenerator:
>          try:
>              path = os.path.join(self.abs_template_dir, file)
>              return self._read_file(path)
> -        except Exception:
> +        except OSError:
>              # Specific template file not found. Try the generic template file
> in the template/
>              # directory, which is one level up
>              path = os.path.join(self.abs_template_dir, "..", file)

^ permalink raw reply

* Re: [PATCH net-next 00/15] mptcp: misc. features for v6.20/7.0
From: patchwork-bot+netdevbpf @ 2026-02-05  2:50 UTC (permalink / raw)
  To: Matthieu Baerts
  Cc: martineau, geliang, davem, edumazet, kuba, pabeni, horms, shuah,
	netdev, mptcp, linux-kernel, linux-kselftest, rostedt, mhiramat,
	mathieu.desnoyers, linux-trace-kernel, david.laight.linux,
	yangang, thomas.weissschuh
In-Reply-To: <20260203-net-next-mptcp-misc-feat-6-20-v1-0-31ec8bfc56d1@kernel.org>

Hello:

This series was applied to netdev/net-next.git (main)
by Jakub Kicinski <kuba@kernel.org>:

On Tue, 03 Feb 2026 19:41:16 +0100 you wrote:
> This series contains a few independent new features, and small fixes for
> net-next:
> 
>  - Patches 1-2: two small fixes linked to the MPTCP receive buffer that
>    are not urgent, requiring code that has been recently changed, and is
>    needed for the next patch. Because we are at the end of the cycle, it
>    seems easier to send them to net-next, instead of dealing with
>    conflicts between net and net-next.
> 
> [...]

Here is the summary with links:
  - [net-next,01/15] mptcp: do not account for OoO in mptcp_rcvbuf_grow()
    https://git.kernel.org/netdev/net-next/c/6b329393502e
  - [net-next,02/15] mptcp: fix receive space timestamp initialization
    https://git.kernel.org/netdev/net-next/c/70274765fef5
  - [net-next,03/15] mptcp: consolidate rcv space init
    https://git.kernel.org/netdev/net-next/c/5c4dcc52c68a
  - [net-next,04/15] trace: mptcp: add mptcp_rcvbuf_grow tracepoint
    https://git.kernel.org/netdev/net-next/c/2002286e68c9
  - [net-next,05/15] mptcp: pm: align endpoint flags size with the NL specs
    https://git.kernel.org/netdev/net-next/c/d7e712b66f9b
  - [net-next,06/15] mptcp: Change some dubious min_t(int, ...) to min()
    https://git.kernel.org/netdev/net-next/c/b582090005d5
  - [net-next,07/15] mptcp: allow overridden write_space to be invoked
    (no matching commit)
  - [net-next,08/15] selftests: mptcp: diag: sort all #include
    https://git.kernel.org/netdev/net-next/c/f7f4e8e9448c
  - [net-next,09/15] selftests: mptcp: join: wait for estab event instead of MPJ
    https://git.kernel.org/netdev/net-next/c/32207bed0547
  - [net-next,10/15] selftests: mptcp: join: fix wait_mpj helper
    https://git.kernel.org/netdev/net-next/c/ab8b64ca3af3
  - [net-next,11/15] selftests: mptcp: join: userspace: wait for new events
    https://git.kernel.org/netdev/net-next/c/62c0774f0f18
  - [net-next,12/15] selftests: mptcp: join chk_stale_nr: avoid dup stats
    https://git.kernel.org/netdev/net-next/c/91453a62e5ec
  - [net-next,13/15] selftests: mptcp: join: avoid declaring i if not used
    https://git.kernel.org/netdev/net-next/c/79d5069cfbec
  - [net-next,14/15] selftests: mptcp: connect cleanup TFO setup
    https://git.kernel.org/netdev/net-next/c/ae68da495ae9
  - [net-next,15/15] selftests: mptcp: join: no SKIP mark for group checks
    https://git.kernel.org/netdev/net-next/c/4dca8d0030c7

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply

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

On Sun,  1 Feb 2026 12:29:15 +0900
"Masami Hiramatsu (Google)" <mhiramat@kernel.org> wrote:

> 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 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        |   94 +++++++++++++++++++++++++++++--------------
>  kernel/trace/trace.h        |    7 +++
>  kernel/trace/trace_boot.c   |    5 +-
>  kernel/trace/trace_events.c |   76 ++++++++++++++++++++---------------
>  4 files changed, 117 insertions(+), 65 deletions(-)
> 
> diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
> index 5c3e4a554143..b0efcf1e0809 100644
> --- a/kernel/trace/trace.c
> +++ b/kernel/trace/trace.c
> @@ -5052,6 +5052,11 @@ static ssize_t
>  tracing_write_stub(struct file *filp, const char __user *ubuf,
>  		   size_t count, loff_t *ppos)
>  {
> +	struct trace_array *tr = file_inode(filp)->i_private;
> +
> +	if (trace_array_is_readonly(tr))
> +		return -EPERM;
> +
>  	return count;
>  }
>  
> @@ -5152,6 +5157,9 @@ tracing_cpumask_write(struct file *filp, const char __user *ubuf,
>  	cpumask_var_t tracing_cpumask_new;
>  	int err;
>  
> +	if (trace_array_is_readonly(tr))
> +		return -EPERM;
> +

Shouldn't these checks be done in the open function? Doing it now is
too late, as -EPERM on a write is confusing when the open for write
succeeds.

-- Steve

>  	if (count == 0 || count > KMALLOC_MAX_SIZE)
>  		return -EINVAL;
>  

^ permalink raw reply

* Re: [PATCH v6 1/4] tracing: Reset last_boot_info if ring buffer is reset
From: Steven Rostedt @ 2026-02-05  1:40 UTC (permalink / raw)
  To: Masami Hiramatsu (Google)
  Cc: Mathieu Desnoyers, linux-kernel, linux-trace-kernel
In-Reply-To: <176991654703.4025429.9641092475053587709.stgit@mhiramat.tok.corp.google.com>

On Sun,  1 Feb 2026 12:29:07 +0900
"Masami Hiramatsu (Google)" <mhiramat@kernel.org> wrote:

> @@ -8036,6 +8042,7 @@ tracing_snapshot_write(struct file *filp, const char __user *ubuf, size_t cnt,
>  				tracing_reset_online_cpus(&tr->max_buffer);
>  			else
>  				tracing_reset_cpu(&tr->max_buffer, iter->cpu_file);
> +			update_last_data_if_empty(tr);

Is this needed? Memory mapped buffers (which the persistent ring buffer
is) do not have snapshot buffers.

-- Steve


>  		}
>  		break;
>  	}

^ permalink raw reply

* Re: [PATCH v11 14/30] tracing: Add a trace remote module for testing
From: Steven Rostedt @ 2026-02-05  1:32 UTC (permalink / raw)
  To: Vincent Donnefort
  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: <20260131132848.254084-15-vdonnefort@google.com>

On Sat, 31 Jan 2026 13:28:32 +0000
Vincent Donnefort <vdonnefort@google.com> wrote:

> Add a module to help testing the tracefs support for trace remotes. This
> module:
> 
>   * Use simple_ring_buffer to write into a ring-buffer.
>   * Declare a single "selftest" event that can be triggered from
>     user-space.
>   * Register a "test" trace remote.
> 
> This is intended to be used by trace remote selftests.
> 
> Signed-off-by: Vincent Donnefort <vdonnefort@google.com>

Reviewed-by: Steven Rostedt (Google) <rostedt@goodmis.org>

-- Steve

^ 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