diff options
| author | Steven Rostedt <rostedt@goodmis.org> | 2026-09-02 09:55:01 -0400 |
|---|---|---|
| committer | Steven Rostedt <rostedt@goodmis.org> | 2026-09-02 11:08:21 -0400 |
| commit | 4617721c502b2ddaa4e324e86da4997edf738fa5 (patch) | |
| tree | 350aa83b47da0b574a814795392b20b0bed83cbc /tools/docs/get_feat.py | |
| download | linux-stable-4617721c502b2ddaa4e324e86da4997edf738fa5.tar.gz linux-stable-4617721c502b2ddaa4e324e86da4997edf738fa5.zip | |
ftrace: Synchronize the initialization of ftrace_opsgrafted
There's some internal state that ftrace_ops needs to have set, but since
it can be declared outside of the ftrace.c code, it calls
ftrace_ops_init() on the ops in every global function. The issue is that
if two tasks call it on the same ops at the same time it is possible to
have the initialization of one corrupt the initialization of the other
call.
Create a ops_mutex to use to synchronize every initialization of the
ftrace_ops. The mutex is taken within checking the ftrace_ops flag that
states it was initializied but the flag is checked again after the mutex
has been taken. Checking first outside the mutex allows it to shortcut
having to take the mutex. But then the check needs to be done again after
the mute is taken in case of races.
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20260902095501.6b59af20@gandalf.local.home
Fixes: f04f24fb7e48d ("ftrace, kprobes: Fix a deadlock on ftrace_regex_lock")
Reported-by: sashiko-bot@kernel.org
Close: https://lore.kernel.org/all/20260829025528.49A831F000E9@smtp.kernel.org/
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'tools/docs/get_feat.py')
| -rwxr-xr-x | tools/docs/get_feat.py | 225 |
1 files changed, 225 insertions, 0 deletions
diff --git a/tools/docs/get_feat.py b/tools/docs/get_feat.py new file mode 100755 index 000000000..2b5155a1f --- /dev/null +++ b/tools/docs/get_feat.py @@ -0,0 +1,225 @@ +#!/usr/bin/env python3 +# pylint: disable=R0902,R0911,R0912,R0914,R0915 +# Copyright(c) 2025: Mauro Carvalho Chehab <mchehab@kernel.org>. +# SPDX-License-Identifier: GPL-2.0 + + +""" +Parse the Linux Feature files and produce a ReST book. +""" + +import argparse +import os +import subprocess +import sys + +from pprint import pprint + +LIB_DIR = "../../tools/lib/python" +SRC_DIR = os.path.dirname(os.path.realpath(__file__)) + +sys.path.insert(0, os.path.join(SRC_DIR, LIB_DIR)) + +from feat.parse_features import ParseFeature # pylint: disable=C0413 + +SRCTREE = os.path.join(os.path.dirname(os.path.realpath(__file__)), "../..") +DEFAULT_DIR = "Documentation/features" + + +class GetFeature: + """Helper class to parse feature parsing parameters""" + + @staticmethod + def get_current_arch(): + """Detects the current architecture""" + + proc = subprocess.run(["uname", "-m"], check=True, + capture_output=True, text=True) + + arch = proc.stdout.strip() + if arch in ["x86_64", "i386"]: + arch = "x86" + elif arch == "s390x": + arch = "s390" + + return arch + + def run_parser(self, args): + """Execute the feature parser""" + + feat = ParseFeature(args.directory, args.debug, args.enable_fname) + data = feat.parse() + + if args.debug > 2: + pprint(data) + + return feat + + def run_rest(self, args): + """ + Generate tables in ReST format. Three types of tables are + supported, depending on the calling arguments: + + - neither feature nor arch is passed: generates a full matrix; + - arch provided: generates a table of supported tables for the + guiven architecture, eventually filtered by feature; + - only feature provided: generates a table with feature details, + showing what architectures it is implemented. + """ + + feat = self.run_parser(args) + + if args.arch: + rst = feat.output_arch_table(args.arch, args.feat) + elif args.feat: + rst = feat.output_feature(args.feat) + else: + rst = feat.output_matrix() + + print(rst) + + def run_current(self, args): + """ + Instead of using a --arch parameter, get feature for the current + architecture. + """ + + args.arch = self.get_current_arch() + + self.run_rest(args) + + def run_list(self, args): + """ + Generate a list of features for a given architecture, in a format + parseable by other scripts. The output format is not ReST. + """ + + if not args.arch: + args.arch = self.get_current_arch() + + feat = self.run_parser(args) + msg = feat.list_arch_features(args.arch, args.feat) + + print(msg) + + def parse_arch(self, parser): + """Add a --arch parsing argument""" + + parser.add_argument("--arch", + help="Output features for an specific" + " architecture, optionally filtering for a " + "single specific feature.") + + def parse_feat(self, parser): + """Add a --feat parsing argument""" + + parser.add_argument("--feat", "--feature", + help="Output features for a single specific " + "feature.") + + + def current_args(self, subparsers): + """Implementscurrent argparse subparser""" + + parser = subparsers.add_parser("current", + formatter_class=argparse.RawTextHelpFormatter, + description="Output table in ReST " + "compatible ASCII format " + "with features for this " + "machine's architecture") + + self.parse_feat(parser) + parser.set_defaults(func=self.run_current) + + def rest_args(self, subparsers): + """Implement rest argparse subparser""" + + parser = subparsers.add_parser("rest", + formatter_class=argparse.RawTextHelpFormatter, + description="Output table(s) in ReST " + "compatible ASCII format " + "with features in ReST " + "markup language. The " + "output is affected by " + "--arch or --feat/--feature" + " flags.") + + self.parse_arch(parser) + self.parse_feat(parser) + parser.set_defaults(func=self.run_rest) + + def list_args(self, subparsers): + """Implement list argparse subparser""" + + parser = subparsers.add_parser("list", + formatter_class=argparse.RawTextHelpFormatter, + description="List features for this " + "machine's architecture, " + "using an easier to parse " + "format. The output is " + "affected by --arch flag.") + + self.parse_arch(parser) + self.parse_feat(parser) + parser.set_defaults(func=self.run_list) + + def validate_args(self, subparsers): + """Implement validate argparse subparser""" + + parser = subparsers.add_parser("validate", + formatter_class=argparse.RawTextHelpFormatter, + description="Validate the contents of " + "the files under " + f"{DEFAULT_DIR}.") + + parser.set_defaults(func=self.run_parser) + + def parser(self): + """ + Create an arparse with common options and several subparsers + """ + parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter) + + parser.add_argument("-d", "--debug", action="count", default=0, + help="Put the script in verbose mode, useful for " + "debugging. Can be called multiple times, to " + "increase verbosity.") + + parser.add_argument("--directory", "--dir", default=DEFAULT_DIR, + help="Changes the location of the Feature files. " + f"By default, it uses the {DEFAULT_DIR} " + "directory.") + + parser.add_argument("--enable-fname", action="store_true", + help="Prints the file name of the feature files. " + "This can be used in order to track " + "dependencies during documentation build.") + + subparsers = parser.add_subparsers() + + self.current_args(subparsers) + self.rest_args(subparsers) + self.list_args(subparsers) + self.validate_args(subparsers) + + args = parser.parse_args() + + return args + + +def main(): + """Main program""" + + feat = GetFeature() + + args = feat.parser() + + if "func" in args: + args.func(args) + else: + sys.exit(f"Please specify a valid command for {sys.argv[0]}") + + +# Call main method +if __name__ == "__main__": + main() |
