diff --git a/lisa/_cli_tools/lisa_load_kmod.py b/lisa/_cli_tools/lisa_load_kmod.py index db914aa1905b896a517ae82d737df0a5ce1979ca..98cb01e5fb3f8ca022d17fbdb2e400996ce3c4d0 100755 --- a/lisa/_cli_tools/lisa_load_kmod.py +++ b/lisa/_cli_tools/lisa_load_kmod.py @@ -20,6 +20,12 @@ def main(): action='append', help='Enable a specific module feature. Can be repeated. By default, the module will try to enable all features and will log in dmesg the ones that failed to enable' ), + 'feature-param': dict( + action='append', + metavar=('FEATURE_NAME', 'PARAM_NAME', 'PARAM_VALUE'), + nargs=3, + help='Set a feature parameter value.' + ), 'cmd': dict( nargs=argparse.REMAINDER, help='Load the module, run the given command then unload the module. If not command is provided, just load the module and exit.' @@ -47,23 +53,26 @@ def main(): def _main(args, target): - - features = args.feature + features = args.feature or [] + features_params = args.feature_param or {} keep_loaded = not bool(args.cmd) cmd = args.cmd or [] if cmd and cmd[0] == '--': cmd = cmd[1:] - kmod_params = {} - if features is not None: - kmod_params['features'] = list(features) + features = { + feature: {} + for feature in features + } + for feature, param_name, param_value in features_params: + features.setdefault(feature, {})[param_name] = param_value kmod = target.get_kmod(LISADynamicKmod) pretty_events = ', '.join(kmod.defined_events) logging.info(f'Kernel module provides the following ftrace events: {pretty_events}') - _kmod_cm = kmod.run(kmod_params=kmod_params) + _kmod_cm = kmod.run(features=features) if keep_loaded: @contextlib.contextmanager diff --git a/lisa/_kmod.py b/lisa/_kmod.py index 9f320d4fd7cf0ae3ac00a76c31f040773327ff15..50245cea9deef79bce85e07b0d6053eac949b353 100644 --- a/lisa/_kmod.py +++ b/lisa/_kmod.py @@ -2800,4 +2800,26 @@ class LISADynamicKmod(FtraceDynamicKmod): return ret + + def install(self, features=None, **kwargs): + """ + Install and load the module on the target. + + :param features: Features to enable and associated parameters. + Top-level in the dict is feature names, nested dict is for parameters. + :type features: dict(str, dict(str, object)) or None + """ + features = features or {} + params = dict( + features=sorted(features.keys()), + **{ + f'{feature}___{name}': value + for feature, params in features.items() + for name, value in (params or {}).items() + } + ) + + return super().install(kmod_params=params, **kwargs) + + # vim :set tabstop=4 shiftwidth=4 expandtab textwidth=80 diff --git a/lisa/trace.py b/lisa/trace.py index 8d3f6610f6a6d92828c0258619ca322496832052..285c80f3b3ca94eb4501e6e5d7da7a09ecfbf43b 100644 --- a/lisa/trace.py +++ b/lisa/trace.py @@ -6110,8 +6110,9 @@ class FtraceCollector(CollectorBase, Configurable): needed, functools.partial( kmod.run, - kmod_params={ - 'features': sorted(kmod._event_features(needed)) + features={ + feature: {} + for feature in sorted(kmod._event_features(needed)) } ) )