diff --git a/SOURCES/CLI-start-a-process-from-tuna.patch b/SOURCES/CLI-start-a-process-from-tuna.patch new file mode 100644 index 00000000..8b5c27ad --- /dev/null +++ b/SOURCES/CLI-start-a-process-from-tuna.patch @@ -0,0 +1,313 @@ +From d7a7671477710eca0673a54475b47a58dbf44842 Mon Sep 17 00:00:00 2001 +From: Daniel Bristot de Oliveira +Date: Thu, 25 Jun 2015 16:50:18 -0300 +Subject: [PATCH 1/2] CLI: start a process from tuna +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Currently it is possible to set the CPU affinity and sched tunables for +threads running on a system. However, tuna does not permit to start a +new application with these parameters set. + +This patch adds the ability to start a new process with its affinity +and sched tunable set before it starts to run. + +To do so, one parameter was added to tuna's command line. This +parameter is the Action -r, --run=: + + -r, --run="COMMAND" + Run the COMMAND. If arguments are passed, the entire com‐ + mand line must be provided inside "quotes". Modifiers -c + and -p can be used to set the affinity and scheduler tun‐ + ables of the given COMMAND. The arg[0] (i.e. the command) + will be set in THREAD-LIST. Likewise the -t, the COMMAND + accepts the prefix + and - as wildcards in order to be + appended or removed from THREAD-LIST, respectively. + +The option -r will fork a new process, set the sched tunables and +affinity, and execute the new application's binary. + +Tuna will wait for the new process to return, and then continue +its execution. That means that it is possible to execute many Actions +after the creation of a new process, including the start of many process +in a single command line. + +Example of use: + +[root@kiron tuna]# tuna -p fifo:1 -t bash -c 1,2 -r +httpd -P + thread ctxt_switches + pid SCHED_ rtpri affinity voluntary nonvoluntary cmd + 10550 OTHER 0 0,1,2,3 300 81 bash + 12898 OTHER 0 0,1,2,3 30 6 bash + 12930 OTHER 0 0,1,2,3 246 27 bash + 13022 FIFO 1 1,2 1 0 httpd + +In this example, the schedule policy:prio fifo:1 is saved for future +Actions, "bash" is set in Thread list, cpus 1,2 are set in the cpulist, +the command "httpd" is appended to the Thread list and is started. +Finally, the threads in Thread list are printed. + +Signed-off-by: Daniel Bristot de Oliveira +Signed-off-by: John Kacur +--- + tuna-cmd.py | 98 ++++++++++++++++++++++++++++++++++++++++++++---------------- + tuna/tuna.py | 59 ++++++++++++++++++++++++++++-------- + 2 files changed, 119 insertions(+), 38 deletions(-) + +diff --git a/tuna-cmd.py b/tuna-cmd.py +index 3c9bfaa50bb4..164fbfcfe5e0 100755 +--- a/tuna-cmd.py ++++ b/tuna-cmd.py +@@ -69,6 +69,8 @@ def usage(): + 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 % ('-s, --save=' + _('FILENAME'), _('Save kthreads sched tunables to %(filename)s') % \ + {"filename": _('FILENAME')}) + print fmt % ('-S, --sockets=' + +@@ -377,8 +379,8 @@ def thread_mapper(s): + return [ int(s), ] + except: + pass +- if not ps: +- ps = procfs.pidstats() ++ ++ ps = procfs.pidstats() + + try: + return ps.find_by_regex(re.compile(fnmatch.translate(s))) +@@ -454,13 +456,14 @@ def main(): + + i18n_init() + try: +- short = "a:c:CfgGhiIKlmNp:PQq:s:S:t:UvWx" ++ short = "a:c:CfgGhiIKlmNp:PQq:r:s:S:t:UvWx" + 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="] ++ "version", "what_is", "spread","cgroup","config_file_apply=","config_file_list=", ++ "run=" ] + if have_inet_diag: + short += "n" + long.append("show_sockets") +@@ -477,11 +480,14 @@ def main(): + cpu_list = None + irq_list = None + irq_list_str = None ++ rtprio = None ++ policy = None + thread_list = [] + thread_list_str = None + filter = False + affect_children = False + show_sockets = False ++ p_waiting_action = False + + for o, a in opts: + if o in ("-h", "--help"): +@@ -510,20 +516,25 @@ def main(): + elif o in ("-G", "--cgroup"): + cgroups = True + elif o in ("-t", "--threads"): +- (op, a) = pick_op(a) +- op_list = reduce(lambda i, j: i + j, +- 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 especified 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 type(a) == type(''): +- thread_list_str = do_list_op(op, thread_list_str, +- a.split(",")) +- if not op: +- irq_list = None ++ # 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, ++ 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 especified 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 type(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"): +@@ -539,14 +550,17 @@ def main(): + 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). ++ (policy, rtprio) = tuna.get_policy_and_rtprio(a) + if not thread_list: +- print ("tuna: %s " % o) + _("requires a thread list!") +- sys.exit(2) +- try: +- tuna.threads_set_priority(thread_list, a, affect_children) +- except (SystemError, OSError) as err: # (3, 'No such process') old python-schedutils incorrectly raised SystemError +- print "tuna: %s" % err +- sys.exit(2) ++ # For backward compatibility ++ p_waiting_action = True ++ else: ++ try: ++ tuna.threads_set_priority(thread_list, a, affect_children) ++ except (SystemError, OSError) as err: # (3, 'No such process') old python-schedutils incorrectly raised SystemError ++ 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. +@@ -637,6 +651,40 @@ def main(): + 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, ++ 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 especified 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 type(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) + + if run_gui: + try: +diff --git a/tuna/tuna.py b/tuna/tuna.py +index 646b8dfa700f..9aab16a409d2 100755 +--- a/tuna/tuna.py ++++ b/tuna/tuna.py +@@ -1,7 +1,7 @@ + # -*- python -*- + # -*- coding: utf-8 -*- + +-import copy, ethtool, os, procfs, re, schedutils ++import copy, ethtool, os, procfs, re, schedutils, sys, shlex + import help, fnmatch + from procfs import utilist + +@@ -498,6 +498,22 @@ def get_irq_affinity_text(irqs, irq): + # needs root prio to read /proc/irq//smp_affinity + return "" + ++def get_policy_and_rtprio(parm): ++ parms = parm.split(":") ++ rtprio = 0 ++ policy = None ++ if parms[0].upper() in ["OTHER", "BATCH", "IDLE", "FIFO", "RR"]: ++ policy = schedutils.schedfromstr("SCHED_%s" % parms[0].upper()) ++ if len(parms) > 1: ++ rtprio = int(parms[1]) ++ elif parms[0].upper() in ["FIFO", "RR"]: ++ rtprio = 1 ++ elif parms[0].isdigit(): ++ rtprio = int(parms[0]) ++ else: ++ raise ValueError ++ return (policy, rtprio) ++ + def thread_filtered(tid, cpus_filtered, show_kthreads, show_uthreads): + if cpus_filtered: + try: +@@ -532,18 +548,9 @@ def thread_set_priority(tid, policy, rtprio): + schedutils.set_scheduler(tid, policy, rtprio) + + def threads_set_priority(tids, parm, affect_children = False): +- parms = parm.split(":") +- rtprio = 0 +- policy = None +- if parms[0].upper() in ["OTHER", "BATCH", "IDLE", "FIFO", "RR"]: +- policy = schedutils.schedfromstr("SCHED_%s" % parms[0].upper()) +- if len(parms) > 1: +- rtprio = int(parms[1]) +- elif parms[0].upper() in ["FIFO", "RR"]: +- rtprio = 1 +- elif parms[0].isdigit(): +- rtprio = int(parms[0]) +- else: ++ try: ++ (policy, rtprio) = get_policy_and_rtprio(parm) ++ except ValueError: + print "tuna: " + _("\"%s\" is unsupported priority value!") % parms[0] + return + +@@ -602,6 +609,32 @@ def get_kthread_sched_tunings(proc = None): + + return kthreads + ++def run_command(cmd, policy, rtprio, cpu_list): ++ newpid = os.fork() ++ if newpid == 0: ++ cmd_list = shlex.split(cmd) ++ pid = os.getpid() ++ if rtprio: ++ try: ++ thread_set_priority(pid, policy, rtprio) ++ except (SystemError, OSError) as err: ++ print "tuna: %s" % err ++ sys.exit(2) ++ if cpu_list: ++ try: ++ schedutils.set_affinity(pid, cpu_list) ++ except (SystemError, OSError) as err: ++ print "tuna: %s" % err ++ sys.exit(2) ++ ++ try: ++ os.execvp(cmd_list[0], cmd_list) ++ except (SystemError, OSError) as err: ++ print "tuna: %s" % err ++ sys.exit(2) ++ else: ++ os.waitpid(newpid, 0); ++ + def generate_rtgroups(filename, kthreads, nr_cpus): + f = file(filename, "w") + f.write('''# Generated by tuna +-- +2.4.11 + diff --git a/SOURCES/display-usage-instead-of-traceback-when-c-missing-args.patch b/SOURCES/display-usage-instead-of-traceback-when-c-missing-args.patch new file mode 100644 index 00000000..164da06a --- /dev/null +++ b/SOURCES/display-usage-instead-of-traceback-when-c-missing-args.patch @@ -0,0 +1,86 @@ +From e9a4bc14e15115e3493781fe8487fb4bd575ae9e Mon Sep 17 00:00:00 2001 +From: John Kacur +Date: Mon, 30 May 2016 20:31:37 +0200 +Subject: [PATCH] tuna: tuna-cmd: Display usage instead of traceback -c missing + args + +Display a usage messaage instead of a python traceback when a required +argument to the -c or --cpus is missing, or when the argument doesn't +make sense. (Such as passing a nonsense string, instead of a comma separated list of numbers) + +- In function pick_op, handle the unusual but possible case where an + empty string is passed as an argument. +- Display a usage message upon ValueError when caling cpustring_to_list + when processing the -c option + +This fixes various erroneous or missing input to -c, such as the +following + +./tuna-cmd.py -c -P +Traceback (most recent call last): + File "./tuna-cmd.py", line 656, in + main() + File "./tuna-cmd.py", line 494, in main + op_list = tuna.cpustring_to_list(a) + File "/home/jkacur/source/tuna/tuna/tuna.py", line 124, in +cpustring_to_list + ends = [ int(a, 0) for a in field.split("-") ] +ValueError: invalid literal for int() with base 0: 'P' + +./tuna-cmd.py -c "" -P +Traceback (most recent call last): + File "./tuna-cmd.py", line 656, in + main() + File "./tuna-cmd.py", line 493, in main + (op, a) = pick_op(a) + File "./tuna-cmd.py", line 408, in pick_op + if argument[0] in ('+', '-'): +IndexError: string index out of range + +./tuna-cmd.py -c "nonesense" -P +Traceback (most recent call last): + File "./tuna-cmd.py", line 656, in + main() + File "./tuna-cmd.py", line 494, in main + op_list = tuna.cpustring_to_list(a) + File "/home/jkacur/source/tuna/tuna/tuna.py", line 124, in +cpustring_to_list + ends = [ int(a, 0) for a in field.split("-") ] +ValueError: invalid literal for int() with base 0: 'nonesense' + +This fixes bugzilla 1268287 + +Signed-off-by: John Kacur +--- + tuna-cmd.py | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/tuna-cmd.py b/tuna-cmd.py +index ae4f78ab7d56..3c9bfaa50bb4 100755 +--- a/tuna-cmd.py ++++ b/tuna-cmd.py +@@ -405,6 +405,8 @@ def irq_mapper(s): + return irq_list + + def pick_op(argument): ++ if argument == "": ++ return (None, argument) + if argument[0] in ('+', '-'): + return (argument[0], argument[1:]) + return (None, argument) +@@ -491,7 +493,11 @@ def main(): + list_config() + elif o in ("-c", "--cpus"): + (op, a) = pick_op(a) +- op_list = tuna.cpustring_to_list(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: +-- +2.4.11 + diff --git a/SOURCES/docs-upgrade-tuna.8-man-page-with-option-r.patch b/SOURCES/docs-upgrade-tuna.8-man-page-with-option-r.patch new file mode 100644 index 00000000..86616d70 --- /dev/null +++ b/SOURCES/docs-upgrade-tuna.8-man-page-with-option-r.patch @@ -0,0 +1,76 @@ +From 3a07bae7e8539955bc3a0f4bafe82a8ff0e25fa9 Mon Sep 17 00:00:00 2001 +From: Daniel Bristot de Oliveira +Date: Thu, 25 Jun 2015 16:51:59 -0300 +Subject: [PATCH 2/2] docs: upgrade tuna.8 man page with option -r +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Update tuna.8 man page with the descriptions of the new command line +options: + -r, --run="COMMAND" + Run the COMMAND. If arguments are passed, the entire com‐ + mand line must be provided inside "quotes". Modifiers -c + and -p can be used to set the affinity and scheduler tun‐ + ables of the given COMMAND. The arg[0] (i.e. the command) + will be set in THREAD-LIST. Likewise the -t, the COMMAND + accepts the prefix + and - as wildcards in order to be + appended or removed from THREAD-LIST, respectively. + +And the modifications of -p behavior: + -p, --priority=[POLICY:]RTPRIO + Set thread scheduler tunables: POLICY and RTPRIO. POLICY + is one of OTHER, FIFO, RR, or BATCH. If -t is not set, -p + will act as a Modifier, saving the sched tunables for + future Actions, for example -r. + +And -t behavior: + -t, --threads=THREAD-LIST + THREAD-LIST affected by commands. Requires a thread num‐ + ber or thread name, or a comma-separated list of thread + numbers and/or names. Thread names may contain wildcards. + Be sure to quote or escape any wildcard specifications. + If only - is passed as argument, the THREAD-LIST will be + cleared. + +Signed-off-by: Daniel Bristot de Oliveira +Signed-off-by: John Kacur +--- + docs/tuna.8 | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/docs/tuna.8 b/docs/tuna.8 +index a0a504cb13b9..81a42dd114a5 100644 +--- a/docs/tuna.8 ++++ b/docs/tuna.8 +@@ -35,7 +35,7 @@ Allow all threads to run on CPU\-LIST. Requires \fB\-c\fR or \fB-S\fR. + Move selected entities to CPU\-LIST. Requires \fB\-c\fR and either \fB-t\fR or \fB-q\fR. + .TP + \fB\-p\fR, \fB\-\-priority\fR=\fI[POLICY:]\fRRTPRIO +-Set thread scheduler tunables: POLICY and RTPRIO. POLICY is one of OTHER, FIFO, RR, or BATCH. Requires \fB\-t\fR. ++Set thread scheduler tunables: POLICY and RTPRIO. POLICY is one of OTHER, FIFO, RR, or BATCH. If \fB\-t\fR is not set, \fB\-p\fR will act as a Modifier saving the sched tunables for future Actions, for example \fB\-r\fR. + .TP + \fB\-P\fR, \fB\-\-show_threads\fR + Show thread list. +@@ -43,6 +43,9 @@ Show thread list. + \fB\-s\fR, \fB\-\-save\fR=\fIFILENAME\fR + Save kthreads sched tunables to FILENAME. + .TP ++\fB\-r\fR, \fB\-\-run\fR=\fI"COMMAND"\fR ++Run the COMMAND. If arguments are passed, the entire command line must be provided inside "quotes". Modifiers \fB-c\fR and \fB-p\fR can be used to set the affinity and scheduler tunables of the given COMMAND. The arg[0] (i.e. the command) will be set in THREAD\-LIST. Likewise the \fB-t\fR, the COMMAND accepts the prefix \fB+\fR and \fB-\fR as wildcards in order to be appended or removed from THREAD\-LIST, respectively. ++.TP + \fB\-v\fR, \fB\-\-version\fR + Show version + .TP +@@ -75,7 +78,7 @@ IRQ\-LIST affected by commands. Requires an IRQ number or a comma-separated list + CPU\-SOCKET\-LIST affected by commands. Requires a socket number or a comma-separated list of socket numbers. + .TP + \fB\-t\fR, \fB\-\-threads\fR=\fITHREAD\-LIST\fR +-THREAD\-LIST affected by commands. Requires a thread number or thread name, or a comma-separated list of thread numbers and/or names. Thread names may contain wildcards. Be sure to quote or escape any wildcard specifications. ++THREAD\-LIST affected by commands. Requires a thread number or thread name, or a comma-separated list of thread numbers and/or names. Thread names may contain wildcards. Be sure to quote or escape any wildcard specifications. If only \fB-\fR is passed as argument, the THREAD\-LIST will be cleared. + .TP + \fB\-U\fR, \fB\-\-no_uthreads\fR + Operations will not affect user threads. +-- +2.4.11 + diff --git a/SOURCES/tuna-Use-errno-codes-instead-of-numbers.patch b/SOURCES/tuna-Use-errno-codes-instead-of-numbers.patch new file mode 100644 index 00000000..081445db --- /dev/null +++ b/SOURCES/tuna-Use-errno-codes-instead-of-numbers.patch @@ -0,0 +1,279 @@ +From 876beba81c6b213e0fe4755409142cddb78e344d Mon Sep 17 00:00:00 2001 +From: John Kacur +Date: Tue, 12 Sep 2017 23:35:39 +0100 +Subject: [PATCH 1/2] tuna: Use errno codes instead of numbers + +Use errno codes instead of numbers since they +are self documenting. + +Simplify the comments as a result + +Signed-off-by: John Kacur +--- + tuna-cmd.py | 12 +++++----- + tuna/tuna.py | 78 ++++++++++++++++++++++++++++++------------------------------ + 2 files changed, 45 insertions(+), 45 deletions(-) + +diff --git a/tuna-cmd.py b/tuna-cmd.py +index 39666c7c77f1..f0c5c0662ebd 100755 +--- a/tuna-cmd.py ++++ b/tuna-cmd.py +@@ -14,7 +14,7 @@ + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + # General Public License for more details. + +-import getopt, ethtool, fnmatch, os, procfs, re, schedutils, sys ++import getopt, ethtool, fnmatch, errno, os, procfs, re, schedutils, sys + from tuna import tuna, sysfs + + import gettext +@@ -180,8 +180,8 @@ def ps_show_thread(pid, affect_children, ps, + global irqs + try: + affinity = format_affinity(schedutils.get_affinity(pid)) +- except (SystemError, OSError) as e: # (3, 'No such process') old python-schedutils incorrectly raised SystemError +- if e[0] == 3: ++ except (SystemError, OSError) as e: # old python-schedutils incorrectly raised SystemError ++ if e[0] == errno.ESRCH: + return + raise e + +@@ -262,8 +262,8 @@ def ps_show(ps, affect_children, thread_list, cpu_list, + continue + try: + affinity = schedutils.get_affinity(pid) +- except (SystemError, OSError) as e: # (3, 'No such process') old python-schedutils incorrectly raised SystemError +- if e[0] == 3: ++ except (SystemError, OSError) as e: # old python-schedutils incorrectly raised SystemError ++ if e[0] == errno.ESRCH: + continue + raise e + if cpu_list and not set(cpu_list).intersection(set(affinity)): +@@ -558,7 +558,7 @@ def main(): + else: + try: + tuna.threads_set_priority(thread_list, a, affect_children) +- except (SystemError, OSError) as err: # (3, 'No such process') old python-schedutils incorrectly raised SystemError ++ except (SystemError, OSError) as err: # old python-schedutils incorrectly raised SystemError + print "tuna: %s" % err + sys.exit(2) + elif o in ("-P", "--show_threads"): +diff --git a/tuna/tuna.py b/tuna/tuna.py +index 9aab16a409d2..562c7fcf92d9 100755 +--- a/tuna/tuna.py ++++ b/tuna/tuna.py +@@ -1,7 +1,7 @@ + # -*- python -*- + # -*- coding: utf-8 -*- + +-import copy, ethtool, os, procfs, re, schedutils, sys, shlex ++import copy, ethtool, errno, os, procfs, re, schedutils, sys, shlex + import help, fnmatch + from procfs import utilist + +@@ -209,8 +209,8 @@ def move_threads_to_cpu(cpus, pid_list, set_affinity_warning = None, + try: + try: + curr_affinity = schedutils.get_affinity(pid) +- except (SystemError, OSError) as e: # (3, 'No such process') old python-schedutils incorrectly raised SystemError +- if e[0] == 3: # 'No such process' ++ except (SystemError, OSError) as e: # old python-schedutils incorrectly raised SystemError ++ if e[0] == errno.ESRCH: + continue + curr_affinity = None + raise e +@@ -218,8 +218,8 @@ def move_threads_to_cpu(cpus, pid_list, set_affinity_warning = None, + try: + schedutils.set_affinity(pid, new_affinity) + curr_affinity = schedutils.get_affinity(pid) +- except (SystemError, OSError) as e: # (3, 'No such process') old python-schedutils incorrectly raised SystemError +- if e[0] == 3: # 'No such process' ++ except (SystemError, OSError) as e: # old python-schedutils incorrectly raised SystemError ++ if e[0] == errno.ESRCH: + continue + curr_affinity == None + raise e +@@ -247,16 +247,16 @@ def move_threads_to_cpu(cpus, pid_list, set_affinity_warning = None, + for tid in threads.keys(): + try: + curr_affinity = schedutils.get_affinity(tid) +- except (SystemError, OSError) as e: # (3, 'No such process') old python-schedutils incorrectly raised SystemError +- if e[0] == 3: ++ except (SystemError, OSError) as e: # old python-schedutils incorrectly raised SystemError ++ if e[0] == errno.ESRCH: + continue + raise e + if set(curr_affinity) != set(new_affinity): + try: + schedutils.set_affinity(tid, new_affinity) + curr_affinity = schedutils.get_affinity(tid) +- except (SystemError, OSError) as e: # (3, 'No such process') old python-schedutils incorrectly raised SystemError +- if e[0] == 3: ++ except (SystemError, OSError) as e: # old python-schedutils incorrectly raised SystemError ++ if e[0] == errno.ESRCH: + continue + raise e + if set(curr_affinity) == set(new_affinity): +@@ -267,12 +267,12 @@ def move_threads_to_cpu(cpus, pid_list, set_affinity_warning = None, + print "move_threads_to_cpu: %s " % \ + (_("could not change %(pid)d affinity to %(new_affinity)s") % \ + {'pid':pid, 'new_affinity':new_affinity}) +- except (SystemError, OSError) as e: # (3, 'No such process') old python-schedutils incorrectly raised SystemError +- if e[0] == 3: ++ except (SystemError, OSError) as e: # old python-schedutils incorrectly raised SystemError ++ if e[0] == errno.ESRCH: + # process died + continue +- elif e[0] == 22: # (22, EINVAL - unmovable thread) +- print "thread %(pid)d cannot be moved as requested" %{'pid':pid} ++ elif e[0] == errno.EINVAL: # unmovable thread) ++ print >> stderr, "thread %(pid)d cannot be moved as requested" %{'pid':pid} + continue + raise e + return changed +@@ -317,8 +317,8 @@ def move_irqs_to_cpu(cpus, irq_list, spread = False): + pid = int(pid[0]) + try: + schedutils.set_affinity(pid, new_affinity) +- except (SystemError, OSError) as e: # (3, 'No such process') old python-schedutils incorrectly raised SystemError +- if e[0] == 3: ++ except (SystemError, OSError) as e: # old python-schedutils incorrectly raised SystemError ++ if e[0] == errno.ESRCH: + unprocessed.append(i) + changed -= 1 + continue +@@ -351,8 +351,8 @@ def isolate_cpus(cpus, nr_cpus): + continue + try: + affinity = schedutils.get_affinity(pid) +- except (SystemError, OSError) as e: # (3, 'No such process') old python-schedutils incorrectly raised SystemError +- if e[0] == 3: ++ except (SystemError, OSError) as e: # old python-schedutils incorrectly raised SystemError ++ if e[0] == errno.ESRCH: + continue + raise e + if set(affinity).intersection(set(cpus)): +@@ -360,8 +360,8 @@ def isolate_cpus(cpus, nr_cpus): + affinity = affinity_remove_cpus(affinity, cpus, nr_cpus) + try: + schedutils.set_affinity(pid, affinity) +- except (SystemError, OSError) as e: # (3, 'No such process') old python-schedutils incorrectly raised SystemError +- if e[0] == 3: ++ except (SystemError, OSError) as e: # old python-schedutils incorrectly raised SystemError ++ if e[0] == errno.ESRCH: + continue + raise e + +@@ -373,8 +373,8 @@ def isolate_cpus(cpus, nr_cpus): + continue + try: + affinity = schedutils.get_affinity(tid) +- except (SystemError, OSError) as e: # (3, 'No such process') old python-schedutils incorrectly raised SystemError +- if e[0] == 3: ++ except (SystemError, OSError) as e: # old python-schedutils incorrectly raised SystemError ++ if e[0] == errno.ESRCH: + continue + raise e + if set(affinity).intersection(set(cpus)): +@@ -382,8 +382,8 @@ def isolate_cpus(cpus, nr_cpus): + affinity = affinity_remove_cpus(affinity, cpus, nr_cpus) + try: + schedutils.set_affinity(tid, affinity) +- except (SystemError, OSError) as e: # (3, 'No such process') old python-schedutils incorrectly raised SystemError +- if e[0] == 3: ++ except (SystemError, OSError) as e: # old python-schedutils incorrectly raised SystemError ++ if e[0] == errno.ESRCH: + continue + raise e + +@@ -419,8 +419,8 @@ def include_cpus(cpus, nr_cpus): + continue + try: + affinity = schedutils.get_affinity(pid) +- except (SystemError, OSError) as e: # (3, 'No such process') old python-schedutils incorrectly raised SystemError +- if e[0] == 3: ++ except (SystemError, OSError) as e: # old python-schedutils incorrectly raised SystemError ++ if e[0] == errno.ESRCH: + continue + raise e + if set(affinity).intersection(set(cpus)) != set(cpus): +@@ -428,8 +428,8 @@ def include_cpus(cpus, nr_cpus): + affinity = list(set(affinity + cpus)) + try: + schedutils.set_affinity(pid, affinity) +- except (SystemError, OSError) as e: # (3, 'No such process') old python-schedutils incorrectly raised SystemError +- if e[0] == 3: ++ except (SystemError, OSError) as e: # old python-schedutils incorrectly raised SystemError ++ if e[0] == errno.ESRCH: + continue + raise e + +@@ -441,8 +441,8 @@ def include_cpus(cpus, nr_cpus): + continue + try: + affinity = schedutils.get_affinity(tid) +- except (SystemError, OSError) as e: # (3, 'No such process') old python-schedutils incorrectly raised SystemError +- if e[0] == 3: ++ except (SystemError, OSError) as e: # old python-schedutils incorrectly raised SystemError ++ if e[0] == errno.ESRCH: + continue + raise e + if set(affinity).intersection(set(cpus)) != set(cpus): +@@ -450,8 +450,8 @@ def include_cpus(cpus, nr_cpus): + affinity = list(set(affinity + cpus)) + try: + schedutils.set_affinity(tid, affinity) +- except (SystemError, OSError) as e: # (3, 'No such process') old python-schedutils incorrectly raised SystemError +- if e[0] == 3: ++ except (SystemError, OSError) as e: # old python-schedutils incorrectly raised SystemError ++ if e[0] == errno.ESRCH: + continue + raise e + +@@ -518,8 +518,8 @@ def thread_filtered(tid, cpus_filtered, show_kthreads, show_uthreads): + if cpus_filtered: + try: + affinity = schedutils.get_affinity(tid) +- except (SystemError, OSError) as e: # (3, 'No such process') old python-schedutils incorrectly raised SystemError +- if e[0] == 3: ++ except (SystemError, OSError) as e: # old python-schedutils incorrectly raised SystemError ++ if e[0] == errno.ESRCH: + return False + raise e + +@@ -557,8 +557,8 @@ def threads_set_priority(tids, parm, affect_children = False): + for tid in tids: + try: + thread_set_priority(tid, policy, rtprio) +- except (SystemError, OSError) as e: # (3, 'No such process') old python-schedutils incorrectly raised SystemError +- if e[0] == 3: ++ except (SystemError, OSError) as e: # old python-schedutils incorrectly raised SystemError ++ if e[0] == errno.ESRCH: + continue + raise e + if affect_children: +@@ -566,8 +566,8 @@ def threads_set_priority(tids, parm, affect_children = False): + if child != tid: + try: + thread_set_priority(child, policy, rtprio) +- except (SystemError, OSError) as e: # (3, 'No such process') old python-schedutils incorrectly raised SystemError +- if e[0] == 3: ++ except (SystemError, OSError) as e: # old python-schedutils incorrectly raised SystemError ++ if e[0] == errno.ESRCH: + continue + raise e + +@@ -597,8 +597,8 @@ def get_kthread_sched_tunings(proc = None): + try: + policy = schedutils.get_scheduler(pid) + affinity = schedutils.get_affinity(pid) +- except (SystemError, OSError) as e: # (3, 'No such process') old python-schedutils incorrectly raised SystemError +- if e[0] == 3: ++ except (SystemError, OSError) as e: # old python-schedutils incorrectly raised SystemError ++ if e[0] == errno.ESRCH: + continue + raise e + percpu = iskthread(pid) and \ +-- +2.9.5 + diff --git a/SOURCES/tuna-cpuview.py-Omit-offline-cpus-in-socket_ids-list.patch b/SOURCES/tuna-cpuview.py-Omit-offline-cpus-in-socket_ids-list.patch new file mode 100644 index 00000000..065ec844 --- /dev/null +++ b/SOURCES/tuna-cpuview.py-Omit-offline-cpus-in-socket_ids-list.patch @@ -0,0 +1,53 @@ +From 6e19631d5e5e27b28e02d0a3f612b95c56e9ba4c Mon Sep 17 00:00:00 2001 +From: John Kacur +Date: Mon, 30 May 2016 12:57:44 +0200 +Subject: [PATCH] tuna: cpuview.py: Omit offline cpus in socket_ids list + +sysfy.py inserts None for offline cpus in class cpus, method reload, via +class cpu method reload. + +This is potentially useful, so we don't want to change these classes. +However in cpuview.py - class cpuview, we don't want to display these +offline cpus, so we only need to recognize that the type None can be +returned and then skip over it. + +This fixes Bugzilla 1036156 +First detected on some ppc + +./tuna-cmd.py +Traceback (most recent call last): + File "./tuna-cmd.py", line 656, in + main() + File "./tuna-cmd.py", line 650, in main + app = tuna_gui.main_gui(kthreads, uthreads, cpus_filtered) + File "/home/jkacur/tuna/tuna/tuna_gui.py", line 49, in __init__ + self.procview, self.irqview, cpus_filtered) + File "/home/jkacur/tuna/tuna/gui/cpuview.py", line 253, in __init__ + socket_ids = [ int(id) for id in self.cpus.sockets.keys() ] + +Signed-off-by: John Kacur +--- + tuna/gui/cpuview.py | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/tuna/gui/cpuview.py b/tuna/gui/cpuview.py +index 41a3d9bbbfc3..c84ecd739c70 100755 +--- a/tuna/gui/cpuview.py ++++ b/tuna/gui/cpuview.py +@@ -250,7 +250,12 @@ class cpuview: + self.irqview = irqview + + vbox = window.get_child().get_child() +- socket_ids = [ int(id) for id in self.cpus.sockets.keys() ] ++ socket_ids = [] ++ for id in self.cpus.sockets.keys(): ++ try: ++ socket_ids.append(int(id)) ++ except TypeError: # Skip over offline cpus - type None ++ continue + socket_ids.sort() + + self.nr_sockets = len(socket_ids) +-- +2.4.11 + diff --git a/SOURCES/tuna-isolate_cpus-exit-with-a-message.patch b/SOURCES/tuna-isolate_cpus-exit-with-a-message.patch new file mode 100644 index 00000000..2e31957d --- /dev/null +++ b/SOURCES/tuna-isolate_cpus-exit-with-a-message.patch @@ -0,0 +1,69 @@ +From 048250c4e0469f5ab3b6230092e1ce40b6b148c6 Mon Sep 17 00:00:00 2001 +From: John Kacur +Date: Wed, 13 Sep 2017 00:39:08 +0100 +Subject: [PATCH 2/2] tuna: isolate_cpus - exit with a message instead of a + traceback + +isolate_cpus can create a traceback if passed an illegal cpuset +If this happens, exit with a message instead of a traceback + +Signed-off-by: John Kacur +--- + tuna/tuna.py | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/tuna/tuna.py b/tuna/tuna.py +index 13b3743e8d06..1ed21353ab48 100755 +--- a/tuna/tuna.py ++++ b/tuna/tuna.py +@@ -343,6 +343,7 @@ def parse_irq_affinity_filename(filename, nr_cpus): + + + def isolate_cpus(cpus, nr_cpus): ++ fname = sys._getframe( ).f_code.co_name # Function name + ps = procfs.pidstats() + ps.reload_threads() + previous_pid_affinities = {} +@@ -354,6 +355,9 @@ def isolate_cpus(cpus, nr_cpus): + except (SystemError, OSError) as e: # old python-schedutils incorrectly raised SystemError + if e[0] == errno.ESRCH: + continue ++ elif e[0] == errno.EINVAL: ++ print >> sys.stderr, "Function:", fname, ",", e.strerror ++ sys.exit(2) + raise e + if set(affinity).intersection(set(cpus)): + previous_pid_affinities[pid] = copy.copy(affinity) +@@ -363,6 +367,9 @@ def isolate_cpus(cpus, nr_cpus): + except (SystemError, OSError) as e: # old python-schedutils incorrectly raised SystemError + if e[0] == errno.ESRCH: + continue ++ elif e[0] == errno.EINVAL: ++ print >> sys.stderr, "Function:", fname, ",", e.strerror ++ sys.exit(2) + raise e + + if not ps[pid].has_key("threads"): +@@ -376,6 +383,9 @@ def isolate_cpus(cpus, nr_cpus): + except (SystemError, OSError) as e: # old python-schedutils incorrectly raised SystemError + if e[0] == errno.ESRCH: + continue ++ elif e[0] == errno.EINVAL: ++ print >> sys.stderr, "Function:", fname, ",", e.strerror ++ sys.exit(2) + raise e + if set(affinity).intersection(set(cpus)): + previous_pid_affinities[tid] = copy.copy(affinity) +@@ -385,6 +395,9 @@ def isolate_cpus(cpus, nr_cpus): + except (SystemError, OSError) as e: # old python-schedutils incorrectly raised SystemError + if e[0] == errno.ESRCH: + continue ++ elif e[0] == errno.EINVAL: ++ print >> sys.stderr, "Function:", fname, ",", e.strerror ++ sys.exit(2) + raise e + + del ps +-- +2.9.5 + diff --git a/SPECS/tuna.spec b/SPECS/tuna.spec new file mode 100644 index 00000000..53a4c1b6 --- /dev/null +++ b/SPECS/tuna.spec @@ -0,0 +1,227 @@ +%{!?python_sitelib: %define python_sitelib %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")} +%{!?python_ver: %define python_ver %(%{__python} -c "import sys ; print sys.version[:3]")} + +Name: tuna +Version: 0.13 +Release: 6%{?dist} +License: GPLv2 +Summary: Application tuning GUI & command line utility +Group: Applications/System +Source: https://www.kernel.org/pub/software/utils/tuna/%{name}-%{version}.tar.xz + +Patch1: tuna-cpuview.py-Omit-offline-cpus-in-socket_ids-list.patch +Patch2: display-usage-instead-of-traceback-when-c-missing-args.patch +Patch3: CLI-start-a-process-from-tuna.patch +Patch4: docs-upgrade-tuna.8-man-page-with-option-r.patch +Patch5: tuna-Use-errno-codes-instead-of-numbers.patch +Patch6: tuna-isolate_cpus-exit-with-a-message.patch + +URL: https://git.kernel.org/pub/scm/utils/tuna/tuna.git +BuildArch: noarch +BuildRequires: python-devel, gettext, desktop-file-utils +Requires: python-ethtool +Requires: python-linux-procfs >= 0.4.5 +Requires: python-schedutils >= 0.2 +# This really should be a Suggests... +# Requires: python-inet_diag +BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) + +%description +Provides interface for changing scheduler and IRQ tunables, at whole CPU and at +per thread/IRQ level. Allows isolating CPUs for use by a specific application +and moving threads and interrupts to a CPU by just dragging and dropping them. +Operations can be done on CPU sockets, understanding CPU topology. + +Can be used as a command line utility without requiring the GUI libraries to be +installed. + +%package -n oscilloscope +Summary: Generic graphical signal plotting tool +Group: Applications/System +Requires: python-matplotlib +Requires: numpy +Requires: pygtk2 +Requires: tuna = %{version}-%{release} + +%description -n oscilloscope +Plots stream of values read from standard input on the screen together with +statistics and a histogram. + +Allows to instantly see how a signal generator, such as cyclictest, signaltest +or even ping, reacts when, for instance, its scheduling policy or real time +priority is changed, be it using tuna or plain chrt & taskset. + +%prep +%setup -q +%patch1 -p1 +%patch2 -p1 +%patch3 -p1 +%patch4 -p1 +%patch5 -p1 +%patch6 -p1 + +%build +%{__python} setup.py build + +%install +rm -rf %{buildroot} +%{__python} setup.py install --skip-build --root %{buildroot} +mkdir -p %{buildroot}/%{_sysconfdir}/tuna/ +mkdir -p %{buildroot}/{%{_bindir},%{_datadir}/tuna/help/kthreads,%{_mandir}/man8} +mkdir -p %{buildroot}/%{_datadir}/polkit-1/actions/ +install -p -m644 tuna/tuna_gui.glade %{buildroot}/%{_datadir}/tuna/ +install -p -m755 tuna-cmd.py %{buildroot}/%{_bindir}/tuna +install -p -m755 oscilloscope-cmd.py %{buildroot}/%{_bindir}/oscilloscope +install -p -m644 help/kthreads/* %{buildroot}/%{_datadir}/tuna/help/kthreads/ +install -p -m644 docs/tuna.8 %{buildroot}/%{_mandir}/man8/ +install -p -m644 etc/tuna/example.conf %{buildroot}/%{_sysconfdir}/tuna/ +install -p -m644 etc/tuna.conf %{buildroot}/%{_sysconfdir}/ +install -p -m644 org.tuna.policy %{buildroot}/%{_datadir}/polkit-1/actions/ +desktop-file-install --dir=%{buildroot}/%{_datadir}/applications tuna.desktop + +# l10n-ed message catalogues +for lng in `cat po/LINGUAS`; do + po=po/"$lng.po" + mkdir -p %{buildroot}/%{_datadir}/locale/${lng}/LC_MESSAGES + msgfmt $po -o %{buildroot}/%{_datadir}/locale/${lng}/LC_MESSAGES/%{name}.mo +done + +%find_lang %name + +%clean +rm -rf %{buildroot} + +%files -f %{name}.lang +%defattr(-,root,root,-) +%doc ChangeLog +%if "%{python_ver}" >= "2.5" +%{python_sitelib}/*.egg-info +%endif +%{_bindir}/tuna +%{_datadir}/tuna/ +%{python_sitelib}/tuna/ +%{_mandir}/man8/tuna.8* +%config(noreplace) %{_sysconfdir}/tuna.conf +%config %{_sysconfdir}/tuna/example.conf +%{_datadir}/polkit-1/actions/org.tuna.policy +%{_datadir}/applications/tuna.desktop + +%files -n oscilloscope +%defattr(-,root,root,-) +%{_bindir}/oscilloscope +%doc docs/oscilloscope+tuna.html +%doc docs/oscilloscope+tuna.pdf + +%changelog +* Wed Sep 13 2017 John Kacur - 0.13-6 +- Use errno codes instead of plain numbers +- Exit with a message instead of a traceback in isolate_cpus +Resolves: rhbz#1472840 + +* Mon Jun 13 2016 John Kacur - 0.13-5 +- Rebuild to document + tuna thows an exception instead of an error message when sched_setaffinity returns EINVAL + This was actually fixed in v0.13-1 +Resolves: rhbz#1290445 + +* Mon May 30 2016 John Kacur - 0.13-4 +- CLI-start-a-process-from-tuna +- docs: upgrade tuna.8 man page with option -r +Resolves: rhbz#1235829 + +* Mon May 30 2016 John Kacur - 0.13-3 +- Display usage instead of traceback when -c missing args or args is incorrect +Resolves: rhbz#1268287 + +* Mon May 30 2016 John Kacur - 0.13-2 +- tuna: cpuview.py: Omit offline cpus in socket_ids list +Resolves: rhbz#1036156 + +* Tue May 24 2016 John Kacur - 0.13-1 +- Upgrade to v0.13 +- Remove patches that are included in 0.13 +Resolves: rhbz#1235828 + +* Mon Dec 21 2015 John Kacur - 0.11.1-11 +- tuna-fix-the-check-of-PF_NO_SETAFFINITY-flag-for-thr.patch +Resolves: rhbz#1286221 + +* Thu Jun 25 2015 John Kacur - 0.11.1-10 +- dropped the git housekeeping patch, not relevant here +- docs-Remove-stray-a.patch +- CLI-Introduce-nohz_full-N-entity.patch +- tuna-config-Fix-pygtk-import.patch +- tuna-Make-isolate-include-operations-affect-proc-irq.patch +- tuna-Decide-whether-to-isolate-a-thread-based-on-PF_.patch +- tuna-Fix-race-in-is_hardirq_handler.patch +- CLI-Do-not-show-column-headers-when-not-outputting-t.patch +- Correct-a-typo-in-the-net.ipv4.ipfrag_time-help-stri.patch +Resolves: rhbz#1234963 + +* Wed May 27 2015 John Kacur - 0.11.1-9 +- Fix-behavior-for-dot-inside-proc-sys-path.patch +Resolves: rhbz#1178917 + +* Mon Oct 20 2014 John Kacur - 0.11.1-8 +- CLI-fix-traceback-due-unavailable-display.patch +Resolves: rhbz#1035853 + +* Fri Sep 12 2014 John Kacur - 0.11.1-7 +- Add a tuna.desktop file +Resolves: rhbz#996954 + +* Tue Mar 11 2014 John Kacur - 0.11.1-6 +- tuna-modified-sysctl-settings-in-example.conf (1031582) +- CLI-fix-traceback-where-enter-p-policy-without-prio (1035794) +Resolves: rhbz#1035794 + +* Fri Dec 27 2013 Daniel Mach - 0.11.1-5 +- Mass rebuild 2013-12-27 + +* Thu Nov 07 2013 John Kacur - 0.11.1-4 +- tuna: Do polkit auth for GUI BZ:919212,974027 (996885) +- tuna: Auto Correction for config file errors (1015062) +- Rebased to 0.11.1 upstream +Resolves: rhbz#996885 +Resolves: rhbz#1015062 + +* Thu Aug 22 2013 John Kacur - 0.11-3 +- spec: Mark configuration files with %config (998984) +- spec: Document the real location of the source in a comment (998987) +- CLI: fix ps_show_thread call with bad args count (1000025) + +* Tue Jun 11 2013 Jiri Kastner - 0.11-2 +- changed dependencies from python-numeric to numpy +- merged spec changes from upstream + +* Thu Jun 6 2013 Jiri Kastner - 0.11-1 +- New upstream release + +* Fri Feb 15 2013 Fedora Release Engineering - 0.9.1-6 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild + +* Sun Jul 22 2012 Fedora Release Engineering - 0.9.1-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Sat Jan 14 2012 Fedora Release Engineering - 0.9.1-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild + +* Wed Feb 09 2011 Fedora Release Engineering - 0.9.1-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild + +* Sun Aug 01 2010 Orcan Ogetbil - 0.9.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Features/Python_2.7/MassRebuild + +* Thu Sep 03 2009 Arnaldo Carvalho de Melo - 0.9.1-1 +- New upstream release + +* Wed Aug 26 2009 Arnaldo Carvalho de Melo - 0.9-3 +- Rewrite the oscilloscope package summary +- Remove the shebang in tuna/oscilloscope.py + +* Mon Aug 17 2009 Arnaldo Carvalho de Melo - 0.9-2 +- Use install -p +- Add BuildRequires for gettext + +* Fri Jul 10 2009 Arnaldo Carvalho de Melo - 0.9-1 +- Fedora package reviewing changes: introduce ChangeLog file