Update tuna command line interface

- Update tuna command line interface
- Move get_policy_and_rtprio call to parser level
- Remove threads print statement
Resolves: rhbz#2062865

Signed-off-by: Leah Leshchinsky <lleshchi@redhat.com>
This commit is contained in:
Leah Leshchinsky 2022-10-26 09:12:27 -04:00
parent e7d521df13
commit b47cdc5ca4
No known key found for this signature in database
GPG Key ID: 1674BC3F464A7C0C
6 changed files with 823 additions and 21 deletions

View File

@ -1,9 +1,9 @@
From 3f1fbb092f5ef07d04fef7ddec9e538f36d84450 Mon Sep 17 00:00:00 2001
From: John Kacur <jkacur@redhat.com>
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 <jkacur@redhat.com>
---
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

View File

@ -0,0 +1,48 @@
From 9dd8c3e889fe632405561cc8476ed42659a99e2e Mon Sep 17 00:00:00 2001
From: Leah Leshchinsky <lleshchi@redhat.com>
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 <lleshchi@redhat.com>
Signed-off-by: John Kacur <jkacur@redhat.com>
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

View File

@ -0,0 +1,24 @@
From b82d9037fe7f51e49a9b3c84b1ccb71fda1e1f61 Mon Sep 17 00:00:00 2001
From: Leah Leshchinsky <lleshchi@redhat.com>
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 <lleshchi@redhat.com>
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

View File

@ -1,7 +1,7 @@
From f2a28b05264fa9557192b73a1b888756748930ac Mon Sep 17 00:00:00 2001
From: John Kacur <jkacur@redhat.com>
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 <fede@evolware.org>
- return 'tun' only if tun_flags exists
Signed-off-by: John Kacur <jkacur@redhat.com>
---
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

View File

@ -0,0 +1,733 @@
From eba1333c50f8a5eebb12b523c30faffac33681b3 Mon Sep 17 00:00:00 2001
From: Leah Leshchinsky <lleshchi@redhat.com>
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 <lleshchi@redhat.com>
Signed-off-by: John Kacur <jkacur@redhat.com>
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

View File

@ -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 <lleshchi@redhat.com> - 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 <jkacur@redhat.com> - 0.18-5
- Match irqs with "irqs/"
Resolves: rhbz#2131343