diff --git a/tuna-Fix-matching-irqs-in-ps_show_thread.patch b/tuna-Fix-matching-irqs-in-ps_show_thread.patch index 3d7cf16..b218c88 100644 --- a/tuna-Fix-matching-irqs-in-ps_show_thread.patch +++ b/tuna-Fix-matching-irqs-in-ps_show_thread.patch @@ -1,9 +1,9 @@ From 3f1fbb092f5ef07d04fef7ddec9e538f36d84450 Mon Sep 17 00:00:00 2001 From: John Kacur Date: Fri, 2 Sep 2022 11:55:07 -0400 -Subject: [PATCH] tuna: Fix matching irqs in ps_show_thread +Subject: [PATCH 5/6] tuna: Fix matching irqs in ps_show_thread -The new format to match irqs is "irqs/" +To new format to match irqs is "irqs/" We already test this when we call is_irq_thread(cmd): With this fix if you do @@ -16,9 +16,6 @@ You will get nic information that was previously missed such as ue iwlwifi:default_queue Signed-off-by: John Kacur ---- - tuna-cmd.py | 15 +++++---------- - 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/tuna-cmd.py b/tuna-cmd.py index b13b25b8a801..80e27523acc6 100755 @@ -48,5 +45,5 @@ index b13b25b8a801..80e27523acc6 100755 users = "Not found in /proc/interrupts!" -- -2.37.3 +2.31.1 diff --git a/tuna-Move-get_policy_and_rtprio-call-to-parser-level.patch b/tuna-Move-get_policy_and_rtprio-call-to-parser-level.patch new file mode 100644 index 0000000..45c4fb6 --- /dev/null +++ b/tuna-Move-get_policy_and_rtprio-call-to-parser-level.patch @@ -0,0 +1,48 @@ +From 9dd8c3e889fe632405561cc8476ed42659a99e2e Mon Sep 17 00:00:00 2001 +From: Leah Leshchinsky +Date: Thu, 4 Aug 2022 09:39:11 -0400 +Subject: [PATCH 2/6] tuna: Move get_policy_and_rtprio call to parser level + +Due to the implementation of the parser for the priority action, +the valid policy and rtprio input can be checked at the parser level. + +Call get_policy_and_rtprio on `priority` and `run --priority` commands +at argparse level. + +Signed-off-by: Leah Leshchinsky +Signed-off-by: John Kacur + +diff --git a/tuna-cmd.py b/tuna-cmd.py +index f49cce4d84d4..554912057f03 100755 +--- a/tuna-cmd.py ++++ b/tuna-cmd.py +@@ -102,7 +102,7 @@ def gen_parser(): + "filename": dict(metavar='FILENAME', type=str, help="Save kthreads sched tunables to this file"), + "profilename": dict(type=str, help="Apply changes described in this file"), + "run_command": dict(metavar='COMMAND', type=str, help="fork a new process and run the \"COMMAND\""), +- "priority": dict(type=str, help="policy/priority help"), ++ "priority": dict(type=tuna.get_policy_and_rtprio, help="policy/priority help"), + } + + MODS = { +diff --git a/tuna/tuna.py b/tuna/tuna.py +index 8650f11c81c3..30a5a570c9d4 100755 +--- a/tuna/tuna.py ++++ b/tuna/tuna.py +@@ -558,11 +558,8 @@ def thread_set_priority(tid, policy, rtprio): + os.sched_setscheduler(tid, policy, param) + + def threads_set_priority(tids, parm, affect_children=False): +- try: +- (policy, rtprio) = get_policy_and_rtprio(parm) +- except ValueError: +- print("tuna: " + _("\"%s\" is an unsupported priority value!") % parm[0]) +- return ++ ++ (policy, rtprio) = parm + + for tid in tids: + try: +-- +2.31.1 + diff --git a/tuna-Remove-threads-print-statement.patch b/tuna-Remove-threads-print-statement.patch new file mode 100644 index 0000000..297038e --- /dev/null +++ b/tuna-Remove-threads-print-statement.patch @@ -0,0 +1,24 @@ +From b82d9037fe7f51e49a9b3c84b1ccb71fda1e1f61 Mon Sep 17 00:00:00 2001 +From: Leah Leshchinsky +Date: Tue, 25 Oct 2022 16:19:25 -0400 +Subject: [PATCH 6/6] tuna: Remove threads print statement + +Remove unnecessary print statement from threadstring_to_list function + +Signed-off-by: Leah Leshchinsky + +diff --git a/tuna-cmd.py b/tuna-cmd.py +index 80e27523acc6..c5bc65059da7 100755 +--- a/tuna-cmd.py ++++ b/tuna-cmd.py +@@ -533,7 +533,6 @@ def threadstring_to_list(threadstr): + global ps + thread_list = [] + thread_strings = list(set(threadstr.split(','))) +- print(thread_strings) + for s in thread_strings: + if s.isdigit(): + thread_list.append(int(s)) +-- +2.31.1 + diff --git a/tuna-Replace-python_ethtool-with-builtin-funtionalit.patch b/tuna-Replace-python_ethtool-with-builtin-funtionalit.patch index 766c715..b8408f6 100644 --- a/tuna-Replace-python_ethtool-with-builtin-funtionalit.patch +++ b/tuna-Replace-python_ethtool-with-builtin-funtionalit.patch @@ -1,7 +1,7 @@ From f2a28b05264fa9557192b73a1b888756748930ac Mon Sep 17 00:00:00 2001 From: John Kacur Date: Tue, 27 Sep 2022 12:59:54 -0400 -Subject: [PATCH] tuna: Replace python_ethtool with builtin funtionality +Subject: [PATCH 4/6] tuna: Replace python_ethtool with builtin funtionality This patch replaces the dependency on python_ethtool with some simplified functions to achieve the same result. @@ -9,13 +9,6 @@ simplified functions to achieve the same result. Reviewed-by: Federico Pellegrin - return 'tun' only if tun_flags exists Signed-off-by: John Kacur ---- - tuna-cmd.py | 2 +- - tuna/gui/irqview.py | 2 +- - tuna/new_eth.py | 37 +++++++++++++++++++++++++++++++++++++ - tuna/tuna.py | 2 +- - 4 files changed, 40 insertions(+), 3 deletions(-) - create mode 100755 tuna/new_eth.py diff --git a/tuna-cmd.py b/tuna-cmd.py index 9a3d3f32398b..b13b25b8a801 100755 @@ -100,5 +93,5 @@ index 30a5a570c9d4..43adb84079e4 100755 from procfs import utilist from tuna import help -- -2.37.3 +2.31.1 diff --git a/tuna-Update-command-line-interface.patch b/tuna-Update-command-line-interface.patch new file mode 100644 index 0000000..d86331e --- /dev/null +++ b/tuna-Update-command-line-interface.patch @@ -0,0 +1,733 @@ +From eba1333c50f8a5eebb12b523c30faffac33681b3 Mon Sep 17 00:00:00 2001 +From: Leah Leshchinsky +Date: Thu, 4 Aug 2022 09:39:10 -0400 +Subject: [PATCH 1/6] tuna: Update command-line interface + +The current command-line interface allows for chaining of multiple +actions, which results in ambiguous user input, a need for maintaining +variable states (thread-list, cpu-list, etc.) in the program, and a need +to type check input after parsing. The help menu can also be +overwhelming. + +Allow for the use of argparse rather than getopt to significantly +simplify the program. +Provide subcommands and clearer usage menus for the user, +introduce type checking at the parser level, and remove +ambiguity for user input. + +Signed-off-by: Leah Leshchinsky +Signed-off-by: John Kacur + +diff --git a/tuna-cmd.py b/tuna-cmd.py +index bdaa70ffc156..f49cce4d84d4 100755 +--- a/tuna-cmd.py ++++ b/tuna-cmd.py +@@ -14,8 +14,9 @@ + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + # General Public License for more details. + +-""" tuna - Application Tuning GUI """ ++""" tuna - Application Tuning Program""" + ++import argparse + import os + import sys + import errno +@@ -37,7 +38,7 @@ def get_loglevel(level): + # logging built-in module levels: + # 0 - NOTSET + # 10 - DEBUG +- # 20 - INFO, ++ # 20 - INFO + # 30 - WARNING + # 40 - ERROR + return int(level) * 10 +@@ -85,70 +86,138 @@ except: + nr_cpus = None + ps = None + irqs = None +-version = "0.18" +- +- +-def usage(): +- print(_('Usage: tuna [OPTIONS]')) +- fmt = '\t%-40s %s' +- print(fmt % ('-h, --help', _('Give this help list'))) +- print(fmt % ('-a, --config_file_apply=profilename', +- _('Apply changes described in profile'))) +- print(fmt % ('-l, --config_file_list', +- _('List preloaded profiles'))) +- print(fmt % ('-g, --gui', _('Start the GUI'))) +- print(fmt % ('-G, --cgroup', +- _('Display the processes with the type of cgroups they are in'))) +- print(fmt % ('-c, --cpus=' + _('CPU-LIST'), _('%(cpulist)s affected by commands') % +- {"cpulist": _('CPU-LIST')})) +- print(fmt % ('-C, --affect_children', +- _('Operation will affect children threads'))) +- print(fmt % ('-d, --disable_perf', +- _('Explicitly disable usage of perf in GUI for process view'))) +- print(fmt % ('-D, --debug', _('Print DEBUG level logging details to console'))) +- print(fmt % ('-f, --filter', +- _('Display filter the selected entities'))) +- print(fmt % ('-i, --isolate', _('Move all allowed threads and IRQs away from %(cpulist)s') % +- {"cpulist": _('CPU-LIST')})) +- print(fmt % ('-I, --include', _('Allow all allowed threads and IRQs to run on %(cpulist)s') % +- {"cpulist": _('CPU-LIST')})) +- print(fmt % ('-K, --no_kthreads', +- _('Operations will not affect kernel threads'))) +- print(fmt % ('-L, --logging', +- _('Log application details to log file for given LOG-LEVEL'))) +- print(fmt % ('-m, --move', _('Move selected entities to %(cpulist)s') % +- {"cpulist": _('CPU-LIST')})) +- print(fmt % ('-N, --nohz_full', +- _('CPUs in nohz_full= kernel command line will be affected by operations'))) ++ ++class HelpMessageParser(argparse.ArgumentParser): ++ def error(self, message): ++ sys.stderr.write('error: %s\n' % message) ++ self.print_help() ++ sys.exit(2) ++ ++def gen_parser(): ++ ++ ++ POS = { ++ "cpu_list": dict(metavar='CPU-LIST', type=tuna.cpustring_to_list, help="CPU-LIST affected by commands"), ++ "thread_list": dict(metavar='THREAD-LIST', type=threadstring_to_list, help="THREAD-LIST affected by commands"), ++ "filename": dict(metavar='FILENAME', type=str, help="Save kthreads sched tunables to this file"), ++ "profilename": dict(type=str, help="Apply changes described in this file"), ++ "run_command": dict(metavar='COMMAND', type=str, help="fork a new process and run the \"COMMAND\""), ++ "priority": dict(type=str, help="policy/priority help"), ++ } ++ ++ MODS = { ++ "logging": dict(dest='loglevel', metavar='LOG-LEVEL', type=get_loglevel, help="Log application details to file for given LOG-LEVEL"), ++ "debug" : dict(action='store_true', dest='debug', help='Print DEBUG level logging details to console'), ++ "version": dict(action='version', version='0.18', help="show version"), ++ "threads": dict(dest='thread_list', default=[], metavar='THREAD-LIST', type=threadstring_to_list, help="THREAD-LIST affected by commands"), ++ "irqs": dict(dest='irq_list', default=[], metavar='IRQ-LIST', type=irqstring_to_list, help="IRQ-LIST affect by commands"), ++ "cpus": dict(dest='cpu_list', default=[], metavar='CPU-LIST', type=tuna.cpustring_to_list, help='CPU-LIST affected by commands'), ++ "sockets": dict(default=[], nargs='+', type=int, help="CPU-SOCKET-LIST affected by commands"), ++ "show_sockets": dict(action='store_true', help='Show network sockets in use by threads'), ++ "cgroups": dict(action='store_true', dest='cgroups', help='Display the processes with the type of cgroups they are in'), ++ "affect_children": dict(action='store_true', help="Operation will affect children threads"), ++ "nohz_full": dict(action='store_true', help="CPUs in nohz_full kernel command line will be affected by operations"), ++ "no_uthreads": dict(action='store_false', dest='uthreads', help="Operations will not affect user threads"), ++ "no_kthreads": dict(action='store_false', dest='kthreads', help="Operations will not affect kernel threads"), ++ "disable_perf": dict(action='store_true', help="Explicitly disable usage of perf in GUI for process view"), ++ "refresh": dict(default=2500, metavar='MSEC', type=int, help="Refresh the GUI every MSEC milliseconds"), ++ "priority": dict(default=(None, None), type=tuna.get_policy_and_rtprio, help="Set thread scheduler tunables: POLICY and RTPRIO"), ++ "background": dict(action='store_true', help="Run command as background task") ++ } ++ ++ parser = HelpMessageParser(description="tuna - Application Tuning Program") ++ ++ parser._positionals.title = "commands" ++ parser.add_argument('-v', '--version', **MODS['version']) ++ parser.add_argument('-L', '--logging', **MODS['logging']) ++ parser.add_argument('-D', '--debug', **MODS['debug']) ++ ++ subparser = parser.add_subparsers(dest='command') ++ ++ isolate = subparser.add_parser('isolate', description="Move all allowed threads and IRQs away from CPU-LIST", ++ help="Move all allowed threads and IRQs away from CPU-LIST") ++ include = subparser.add_parser('include', description="Allow all threads to run on CPU-LIST", ++ help="Allow all threads to run on CPU-LIST") ++ move = subparser.add_parser('move', description="Move selected entities to CPU-LIST", ++ help="Move selected entities to CPU-LIST") ++ spread = subparser.add_parser('spread', description="Move selected entities to CPU-LIST", ++ help="Spread selected entities over CPU-LIST") ++ priority = subparser.add_parser('priority', description="Set thread scheduler tunables: POLICY and RTPRIO", ++ help="Set thread scheduler tunables: POLICY and RTPRIO") ++ run = subparser.add_parser('run', description="Fork a new process and run the COMMAND", ++ help="Fork a new process and run the COMMAND") ++ save = subparser.add_parser('save', description="Save kthreads sched tunables to FILENAME", ++ help="Save kthreads sched tunables to FILENAME") ++ apply = subparser.add_parser('apply', description="Apply changes described in profile", ++ help="Apply changes described in profile") ++ show_threads = subparser.add_parser('show_threads', description='Show thread list', help='Show thread list') ++ show_irqs = subparser.add_parser('show_irqs', description='Show IRQ list', help='Show IRQ list') ++ show_configs = subparser.add_parser('show_configs', description='List preloaded profiles', help='List preloaded profiles') ++ ++ what_is = subparser.add_parser('what_is', description='Provides help about selected entities', help='Provides help about selected entities') ++ gui = subparser.add_parser('gui', description="Start the GUI", help="Start the GUI") ++ ++ isolate_group = isolate.add_mutually_exclusive_group(required=True) ++ isolate_group.add_argument('-c', '--cpus', **MODS['cpus']) ++ isolate_group.add_argument('-N', '--nohz_full', **MODS['nohz_full']) ++ ++ include_group = include.add_mutually_exclusive_group(required=True) ++ include_group.add_argument('-c', '--cpus', **MODS['cpus']) ++ include_group.add_argument('-N', '--nohz_full', **MODS['nohz_full']) ++ ++ move_group = move.add_mutually_exclusive_group(required=True) ++ move_group.add_argument('-c', '--cpus', **MODS['cpus']) ++ move_group.add_argument('-N', '--nohz_full', **MODS['nohz_full']) ++ move.add_argument('-t', '--threads', **MODS['threads']) ++ move.add_argument('-q', '--irqs', **MODS['irqs']) ++ ++ spread_group = spread.add_mutually_exclusive_group(required=True) ++ spread_group.add_argument('-c', '--cpus', **MODS['cpus']) ++ spread_group.add_argument('-N', '--nohz_full', **MODS['nohz_full']) ++ spread.add_argument('-t', '--threads', **MODS['threads']) ++ spread.add_argument('-q', '--irqs', **MODS['irqs']) ++ ++ priority.add_argument('priority', **POS['priority']) ++ priority.add_argument('-t', '--threads', **MODS['threads'], required=True) ++ priority.add_argument('-C', '--affect_children', **MODS['affect_children']) ++ ++ run.add_argument('run_command', **POS['run_command']) ++ run.add_argument('-c', '--cpus', **MODS['cpus']) ++ run.add_argument('-p', '--priority', **MODS['priority']) ++ run.add_argument('-b', '--background', **MODS['background']) ++ ++ save.add_argument('filename', **POS['filename']) ++ save.add_argument('-c', '--cpus', **MODS['cpus']) ++ save.add_argument('-t', '--threads', **MODS['threads']) ++ ++ apply.add_argument('profilename', **POS['profilename']) ++ ++ show_threads_group1 = show_threads.add_mutually_exclusive_group(required=False) ++ show_threads_group1.add_argument('-c', '--cpus', **MODS['cpus']) ++ show_threads_group1.add_argument('-N', '--nohz_full', **MODS['nohz_full']) ++ show_threads_group2 = show_threads.add_mutually_exclusive_group(required=False) ++ show_threads_group2.add_argument('-t', '--threads', **MODS['threads']) ++ show_threads_group2.add_argument('-q', '--irqs', **MODS['irqs']) ++ show_threads.add_argument('-U', '--no_uthreads', **MODS['no_uthreads']) ++ show_threads.add_argument('-K', '--no_kthreads', **MODS['no_kthreads']) ++ show_threads.add_argument('-C', '--affect_children', **MODS['affect_children']) ++ + if have_inet_diag: +- print(fmt % ('-n, --show_sockets', +- _('Show network sockets in use by threads'))) +- print(fmt % ('-p, --priority=[' + +- _('POLICY') + ':]' + +- _('RTPRIO'), _('Set thread scheduler tunables: %(policy)s and %(rtprio)s') % +- {"policy": _('POLICY'), "rtprio": _('RTPRIO')})) +- print(fmt % ('-P, --show_threads', _('Show thread list'))) +- print(fmt % ('-Q, --show_irqs', _('Show IRQ list'))) +- print(fmt % ('-q, --irqs=' + _('IRQ-LIST'), _('%(irqlist)s affected by commands') % +- {"irqlist": _('IRQ-LIST')})) +- print(fmt % ('-r, --run=' + _('COMMAND'), _('fork a new process and run the %(command)s') % +- {"command": _('COMMAND')})) +- print(fmt % ('-R, --refresh=' + _('MSEC'), _('Refresh the GUI every MSEC milliseconds'))) +- print(fmt % ('-s, --save=' + _('FILENAME'), _('Save kthreads sched tunables to %(filename)s') % +- {"filename": _('FILENAME')})) +- print(fmt % ('-S, --sockets=' + +- _('CPU-SOCKET-LIST'), _('%(cpusocketlist)s affected by commands') % +- {"cpusocketlist": _('CPU-SOCKET-LIST')})) +- print(fmt % ('-t, --threads=' + +- _('THREAD-LIST'), _('%(threadlist)s affected by commands') % +- {"threadlist": _('THREAD-LIST')})) +- print(fmt % ('-U, --no_uthreads', +- _('Operations will not affect user threads'))) +- print(fmt % ('-v, --version', _('Show version'))) +- print(fmt % ('-W, --what_is', +- _('Provides help about selected entities'))) +- print(fmt % ('-x, --spread', _('Spread selected entities over %(cpulist)s') % +- {"cpulist": _('CPU-LIST')})) ++ show_threads.add_argument('-n', '--show_sockets', **MODS['show_sockets']) ++ show_threads.add_argument('-G', '--cgroups', **MODS['cgroups']) ++ ++ show_irqs.add_argument('-c', '--cpus', **MODS['cpus']) ++ show_irqs.add_argument('-q', '--irqs', **MODS['irqs']) ++ ++ what_is.add_argument('thread_list', **POS['thread_list']) ++ ++ gui.add_argument('-d', '--disable_perf', **MODS['disable_perf']) ++ gui.add_argument('-R', '--refresh', **MODS['refresh']) ++ gui.add_argument('-c', '--cpus', **MODS['cpus']) ++ gui.add_argument('-U', '--no_uthreads', **MODS['no_uthreads']) ++ gui.add_argument('-K', '--no_kthreads', **MODS['no_kthreads']) ++ ++ return parser + + + def get_nr_cpus(): +@@ -447,39 +516,34 @@ def do_list_op(op, current_list, op_list): + return list(set(current_list) - set(op_list)) + return list(set(op_list)) + +- +-def thread_mapper(s): ++def threadstring_to_list(threadstr): + global ps +- try: +- return [int(s), ] +- except: +- pass +- +- ps = procfs.pidstats() +- +- try: +- return ps.find_by_regex(re.compile(fnmatch.translate(s))) +- except: +- return ps.find_by_name(s) +- ++ thread_list = [] ++ thread_strings = list(set(threadstr.split(','))) ++ print(thread_strings) ++ for s in thread_strings: ++ if s.isdigit(): ++ thread_list.append(int(s)) ++ else: ++ ps = procfs.pidstats() ++ try: ++ thread_list += ps.find_by_regex(re.compile(fnmatch.translate(s))) ++ except: ++ thread_list += ps.find_by_name(s) ++ return thread_list + +-def irq_mapper(s): +- global irqs +- try: +- return [int(s), ] +- except: +- pass +- if not irqs: +- irqs = procfs.interrupts() ++def irqstring_to_list(irqstr): + +- irq_list_str = irqs.find_by_user_regex(re.compile(fnmatch.translate(s))) + irq_list = [] +- for i in irq_list_str: +- try: +- irq_list.append(int(i)) +- except: +- pass +- ++ irq_strings = list(set(irqstr.split(','))) ++ print(irq_strings) ++ for s in irq_strings: ++ if s.isdigit(): ++ irq_list.append(int(s)) ++ else: ++ # find_by_user_regex returns a list of strings corresponding to irq number ++ irq_list_str = procfs.interrupts().find_by_user_regex(re.compile(fnmatch.translate(s))) ++ irq_list += [int(i) for i in irq_list_str if i.isdigit()] + return irq_list + + +@@ -531,298 +595,123 @@ def list_config(): + print(value) + sys.exit(1) + ++def nohz_full_to_cpu(): ++ ++ try: ++ return tuna.nohz_full_list() ++ except: ++ print("tuna: --nohz_full " + ++ _(" needs nohz_full=cpulist on the kernel command line")) ++ sys.exit(2) + + def main(): + global ps + + i18n_init() +- try: +- short = "a:c:dDCfgGhiIKlmNp:PQq:r:R:s:S:t:UvWxL:" +- long = ["cpus=", "affect_children", "filter", "gui", "help", +- "isolate", "include", "no_kthreads", "move", "nohz_full", +- "show_sockets", "priority=", "show_threads", +- "show_irqs", "irqs=", +- "save=", "sockets=", "threads=", "no_uthreads", +- "version", "what_is", "spread", "cgroup", "config_file_apply=", +- "config_file_list", "run=", "refresh=", "disable_perf", "logging=", "debug"] +- if have_inet_diag: +- short += "n" +- long.append("show_sockets") +- opts, args = getopt.getopt(sys.argv[1:], short, long) +- except getopt.GetoptError as err: +- usage() +- print(str(err)) +- sys.exit(2) ++ parser = gen_parser() ++ # Set all necessary defaults for gui subparser if no arguments provided ++ args = parser.parse_args() if len(sys.argv) > 1 else parser.parse_args(['gui']) ++ ++ if args.debug: ++ my_logger = setup_logging("my_logger") ++ my_logger.addHandler(add_handler("DEBUG", tofile=False)) ++ my_logger.info("Debug option set") ++ ++ if args.loglevel: ++ if not args.debug: ++ my_logger = setup_logging("my_logger") ++ try: ++ my_logger.addHandler(add_handler(args.loglevel, tofile=True)) ++ my_logger.info("Logging option set at log level {}".format(args.loglevel)) + +- run_gui = not opts +- kthreads = True +- uthreads = True +- cgroups = False +- cpu_list = None +- debug = False +- irq_list = None +- irq_list_str = None +- log = False +- rtprio = None +- policy = None +- thread_list = [] +- thread_list_str = None +- filter = False +- affect_children = False +- show_sockets = False +- p_waiting_action = False +- gui_refresh = 2500 +- disable_perf = False +- +- for o, a in opts: +- if o in ("-h", "--help"): +- usage() +- return +- if o in ("-D", "--debug"): +- if debug: +- my_logger.warning("Debugging already set") +- continue +- debug = True +- if not log: +- my_logger = setup_logging("my_logger") +- my_logger.addHandler(add_handler("DEBUG", tofile=False)) +- my_logger.info("Debug option set") +- if o in ("-L", "--logging"): +- if log: +- my_logger.warning("Logging already set") +- continue +- log = True +- loglevel = get_loglevel(a) +- if not debug: +- my_logger = setup_logging("my_logger") +- try: +- my_logger.addHandler(add_handler(loglevel, tofile=True)) +- except ValueError as e: +- print(e, "tuna: --logging requires valid logging level\n") +- print("Valid log levels: NOTSET, DEBUG, INFO, WARNING, ERROR") +- print("Log levels may be specified numerically (0-4)") +- my_logger.info("Logging option set") +- if o in ("-a", "--config_file_apply"): +- apply_config(a) +- elif o in ("-l", "--config_file_list"): +- list_config() +- elif o in ("-c", "--cpus"): +- (op, a) = pick_op(a) +- try: +- op_list = tuna.cpustring_to_list(a) +- except ValueError: +- usage() +- return +- cpu_list = do_list_op(op, cpu_list, op_list) +- elif o in ("-N", "--nohz_full"): +- try: +- cpu_list = tuna.nohz_full_list() +- except: +- print("tuna: --nohz_full " + +- _(" needs nohz_full=cpulist on the kernel command line")) +- sys.exit(2) +- elif o in ("-C", "--affect_children"): +- affect_children = True +- elif o in ("-G", "--cgroup"): +- cgroups = True +- elif o in ("-t", "--threads"): +- # The -t - will reset thread list +- if a == '-': +- thread_list = [] +- thread_list_str = '' +- else: +- (op, a) = pick_op(a) +- op_list = reduce(lambda i, j: i + j, +- list(map(thread_mapper, a.split(",")))) +- op_list = list(set(op_list)) +- thread_list = do_list_op(op, thread_list, op_list) +- # Check if a process name was specified and no +- # threads was found, which would result in an empty +- # thread list, i.e. we would print all the threads +- # in the system when we should print nothing. +- if not op_list and isinstance(a, type('')): +- thread_list_str = do_list_op(op, thread_list_str, +- a.split(",")) +- if not op: +- irq_list = None +- elif o in ("-f", "--filter"): +- filter = True +- elif o in ("-g", "--gui"): +- run_gui = True +- elif o in ("-R", "--refresh"): +- run_gui = True +- (op, a) = pick_op(a) +- try: +- gui_refresh=int(a) +- except Exception as err: +- print("tuna: --refresh %s" % err) +- sys.exit(2) +- elif o in ("-d", "--disable_perf"): +- run_gui = True +- disable_perf = True +- elif o in ("-i", "--isolate"): +- if not cpu_list: +- print("tuna: --isolate " + _("requires a cpu list!")) +- sys.exit(2) +- tuna.isolate_cpus(cpu_list, get_nr_cpus()) +- elif o in ("-I", "--include"): +- if not cpu_list: +- print("tuna: --include " + _("requires a cpu list!")) +- sys.exit(2) +- tuna.include_cpus(cpu_list, get_nr_cpus()) +- elif o in ("-p", "--priority"): +- # Save policy and rtprio for future Actions (e.g. --run). +- try: +- (policy, rtprio) = tuna.get_policy_and_rtprio(a) +- except ValueError: +- print("tuna: " + _("\"%s\" is an unsupported priority value!") % a) +- sys.exit(2) +- if not thread_list: +- # For backward compatibility +- p_waiting_action = True +- else: +- try: +- tuna.threads_set_priority(thread_list, a, affect_children) +- except OSError as err: +- print("tuna: %s" % err) +- sys.exit(2) +- elif o in ("-P", "--show_threads"): +- # If the user specified process names that weren't +- # resolved to pids, don't show all threads. +- if not thread_list and not irq_list: +- if thread_list_str or irq_list_str: +- continue +- do_ps(thread_list, cpu_list, irq_list, uthreads, +- kthreads, affect_children, show_sockets, cgroups) +- elif o in ("-Q", "--show_irqs"): +- # If the user specified IRQ names that weren't +- # resolved to IRQs, don't show all IRQs. +- if not irq_list and irq_list_str: +- continue +- show_irqs(irq_list, cpu_list) +- elif o in ("-n", "--show_sockets"): +- show_sockets = True +- elif o in ("-m", "--move", "-x", "--spread"): +- spread = o in ("-x", "--spread") +- if not cpu_list: +- print("tuna: %s " % ("--spread" if spread else "--move") + _("requires a cpu list!")) +- sys.exit(2) +- if not (thread_list or irq_list): +- print("tuna: %s " % ("--spread" if spread else "--move") + _("requires a list of threads/irqs!")) +- sys.exit(2) +- +- if thread_list: +- tuna.move_threads_to_cpu(cpu_list, thread_list, spread=spread) +- +- if irq_list: +- tuna.move_irqs_to_cpu(cpu_list, irq_list, spread=spread) +- elif o in ("-s", "--save"): +- save(cpu_list, thread_list, a) +- elif o in ("-S", "--sockets"): +- (op, a) = pick_op(a) +- sockets = list(a.split(',')) +- +- if not cpu_list: +- cpu_list = [] +- +- cpu_info = sysfs.cpus() +- op_list = [] +- for socket in sockets: +- if socket not in cpu_info.sockets: +- print("tuna: %s" % +- (_("invalid socket %(socket)s sockets available: %(available)s") % +- {"socket": socket, +- "available": ",".join(list(cpu_info.sockets.keys()))})) +- sys.exit(2) +- op_list += [int(cpu.name[3:]) +- for cpu in cpu_info.sockets[socket]] +- cpu_list = do_list_op(op, cpu_list, op_list) +- elif o in ("-K", "--no_kthreads"): +- kthreads = False +- elif o in ("-q", "--irqs"): +- (op, a) = pick_op(a) +- op_list = reduce(lambda i, j: i + j, +- list(map(irq_mapper, list(set(a.split(",")))))) +- irq_list = do_list_op(op, irq_list, op_list) +- # See comment above about thread_list_str +- if not op_list and isinstance(a, type('')): +- irq_list_str = do_list_op(op, irq_list_str, a.split(",")) +- if not op: +- thread_list = [] +- if not ps: +- ps = procfs.pidstats() +- if tuna.has_threaded_irqs(ps): +- for irq in irq_list: +- irq_re = tuna.threaded_irq_re(irq) +- irq_threads = ps.find_by_regex(irq_re) +- if irq_threads: +- # Change the affinity of the thread too +- # as we can't rely on changing the irq +- # affinity changing the affinity of the +- # thread or vice versa. We need to change +- # both. +- thread_list += irq_threads +- +- elif o in ("-U", "--no_uthreads"): +- uthreads = False +- elif o in ("-v", "--version"): +- print(version) +- elif o in ("-W", "--what_is"): +- if not thread_list: +- print("tuna: --what_is " + _("requires a thread list!")) +- sys.exit(2) +- for tid in thread_list: +- thread_help(tid) +- elif o in ("-r", "--run"): +- # If -p is set, it will be consumed. So, no backward compatible +- # error handling action must be taken. +- p_waiting_action = False +- +- # pick_op() before run the command: to remove the prefix +- # + or - from command line. +- (op, a) = pick_op(a) +- +- # In order to include the new process, it must run +- # the command first, and then get the list of pids, +- tuna.run_command(a, policy, rtprio, cpu_list) +- +- op_list = reduce(lambda i, j: i + j, +- list(map(thread_mapper, a.split(",")))) +- op_list = list(set(op_list)) +- thread_list = do_list_op(op, thread_list, op_list) +- +- # Check if a process name was specified and no +- # threads was found, which would result in an empty +- # thread list, i.e. we would print all the threads +- # in the system when we should print nothing. +- if not op_list and isinstance(a, type('')): +- thread_list_str = do_list_op(op, thread_list_str, a.split(",")) +- if not op: +- irq_list = None +- +- # For backward compatibility: when -p used to be only an Action, it +- # used to exit(2) if no action was taken (i.e. if no threads_list +- # was set). +- if p_waiting_action: +- print(("tuna: -p ") + _("requires a thread list!")) +- sys.exit(2) ++ except ValueError as e: ++ print(e, "tuna: --logging requires valid logging level\n") ++ print("Valid log levels: NOTSET, DEBUG, INFO, WARNING, ERROR") ++ print("Log levels may be specified numerically (0-4)\n") ++ ++ if 'irq_list' in vars(args): ++ ps = procfs.pidstats() ++ if tuna.has_threaded_irqs(ps): ++ for irq in args.irq_list: ++ irq_re = tuna.threaded_irq_re(irq) ++ irq_threads = ps.find_by_regex(irq_re) ++ if irq_threads: ++ # Change the affinity of the thread too ++ # as we can't rely on changing the irq ++ # affinity changing the affinity of the ++ # thread or vice versa. We need to change ++ # both. ++ if 'thread_list' in vars(args): ++ args.thread_list += irq_threads ++ ++ if 'nohz_full' in vars(args) and args.nohz_full: ++ args.cpu_list = nohz_full_to_cpu() ++ ++ if args.command in ['apply', 'a']: ++ apply_config(args.profilename) ++ ++ elif args.command in ['include', 'I']: ++ tuna.include_cpus(args.cpu_list, get_nr_cpus()) ++ ++ elif args.command in ['isolate', 'i']: ++ tuna.isolate_cpus(args.cpu_list, get_nr_cpus()) ++ ++ elif args.command in ['run', 'r']: ++ ++ tuna.run_command(args.run_command, args.priority[0], args.priority[1], args.cpu_list, args.background) ++ ++ elif args.command in ['priority', 'p']: ++ ++ try: ++ tuna.threads_set_priority(args.thread_list, args.priority, args.affect_children) ++ except OSError as err: ++ print("tuna: %s" % err) ++ sys.exit(2) ++ ++ elif args.command in ['show_configs']: ++ list_config() ++ ++ elif args.command in ['show_threads']: ++ do_ps(args.thread_list, args.cpu_list, args.irq_list, args.uthreads, ++ args.kthreads, args.affect_children, args.show_sockets if "show_sockets" in args else None, args.cgroups) ++ ++ elif args.command in ['show_irqs']: ++ show_irqs(args.irq_list, args.cpu_list) ++ ++ elif args.command in ['move', 'm', 'spread', 'x']: ++ spread = args.command in ['spread', 'x'] ++ ++ if not (args.thread_list or args.irq_list): ++ parser.error("tuna: %s " % (args.command) + _("requires a thread/irq list!\n")) ++ ++ if args.thread_list: ++ tuna.move_threads_to_cpu(args.cpu_list, args.thread_list, spread=spread) ++ ++ if args.irq_list: ++ tuna.move_irqs_to_cpu(args.cpu_list, args.irq_list, spread=spread) ++ ++ elif args.command in ['s', 'save']: ++ save(args.cpu_list, args.thread_list, args.filename) ++ ++ elif args.command in ['W', 'what_is']: ++ for tid in args.thread_list: ++ thread_help(tid) + +- if run_gui: ++ elif args.command in ['g', 'gui']: + try: + from tuna import tuna_gui + except ImportError: + # gui packages not installed + print(_('tuna: packages needed for the GUI missing.')) + print(_(' Make sure xauth, pygtk2-libglade are installed.')) +- usage() ++ parser.print_help() + return + except RuntimeError: + print("tuna: machine needs to be authorized via xhost or ssh -X?") + return + + try: +- cpus_filtered = filter if cpu_list else [] +- app = tuna_gui.main_gui(kthreads, uthreads, cpus_filtered, gui_refresh, disable_perf) ++ app = tuna_gui.main_gui(args.kthreads, args.uthreads, args.cpu_list, args.refresh, args.disable_perf) + app.run() + except KeyboardInterrupt: + pass +diff --git a/tuna/tuna.py b/tuna/tuna.py +index 31707c9cb69c..8650f11c81c3 100755 +--- a/tuna/tuna.py ++++ b/tuna/tuna.py +@@ -618,7 +618,7 @@ def get_kthread_sched_tunings(proc=None): + + return kthreads + +-def run_command(cmd, policy, rtprio, cpu_list): ++def run_command(cmd, policy, rtprio, cpu_list, background): + newpid = os.fork() + if newpid == 0: + cmd_list = shlex.split(cmd) +@@ -642,7 +642,8 @@ def run_command(cmd, policy, rtprio, cpu_list): + print("tuna: %s" % err) + sys.exit(2) + else: +- os.waitpid(newpid, 0) ++ if not background: ++ os.waitpid(newpid, 0) + + def generate_rtgroups(filename, kthreads, nr_cpus): + f = open(filename, "w") +-- +2.31.1 + diff --git a/tuna.spec b/tuna.spec index c8abae0..4485c9d 100644 --- a/tuna.spec +++ b/tuna.spec @@ -1,6 +1,6 @@ Name: tuna Version: 0.18 -Release: 5%{?dist} +Release: 6%{?dist} License: GPLv2 Summary: Application tuning GUI & command line utility URL: https://git.kernel.org/pub/scm/utils/tuna/tuna.git @@ -13,8 +13,11 @@ Requires: python3-linux-procfs >= 0.6 # Requires: python-inet_diag # Patches -Patch1: tuna-Replace-python_ethtool-with-builtin-funtionalit.patch -Patch2: tuna-Fix-matching-irqs-in-ps_show_thread.patch +Patch1: tuna-Update-command-line-interface.patch +Patch2: tuna-Move-get_policy_and_rtprio-call-to-parser-level.patch +Patch3: tuna-Replace-python_ethtool-with-builtin-funtionalit.patch +Patch4: tuna-Fix-matching-irqs-in-ps_show_thread.patch +Patch5: tuna-Remove-threads-print-statement.patch %description Provides interface for changing scheduler and IRQ tunables, at whole CPU and at @@ -26,9 +29,7 @@ Can be used as a command line utility without requiring the GUI libraries to be installed. %prep -%setup -q -%patch1 -p1 -%patch2 -p1 +%autosetup -p1 %build %py3_build @@ -70,6 +71,12 @@ done %{_datadir}/polkit-1/actions/org.tuna.policy %changelog +* Wed Oct 26 2022 Leah Leshchinsky - 0.18-6 +- Update tuna command line interface +- Move get_policy_and_rtprio call to parser level +- Remove threads print statement +Resolves: rhbz#2062865 + * Mon Oct 03 2022 John Kacur - 0.18-5 - Match irqs with "irqs/" Resolves: rhbz#2131343