!41 fix SWAPIN I/O display issue

From: @lv_1245 
Reviewed-by: @swf504 
Signed-off-by: @swf504
This commit is contained in:
openeuler-ci-bot 2024-11-15 08:55:20 +00:00 committed by Gitee
commit aeba6ff24b
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
7 changed files with 562 additions and 1 deletions

View File

@ -0,0 +1,89 @@
From 16a30ece6ab4eaa9ca5d056ada94673265195e27 Mon Sep 17 00:00:00 2001
From: Paul Wise <pabs3@bonedaddy.net>
Date: Thu, 4 Aug 2016 18:00:29 +0800
Subject: [PATCH] Hide UI elements on smaller terminals
This helps usability on smaller terminals.
Hide the status bar first, then the summary and then the titles,
since that is the approximate order of usefulness.
Conflict: Adapt patch Context
Reference: https://repo.or.cz/iotop.git/commit/16a30ece6ab4eaa9ca5d056ada94673265195e27
---
iotop/ui.py | 39 +++++++++++++++++++++++++++------------
1 file changed, 27 insertions(+), 12 deletions(-)
diff --git a/iotop/ui.py b/iotop/ui.py
index abd6b79..b2ac8fb 100644
--- a/iotop/ui.py
+++ b/iotop/ui.py
@@ -410,8 +410,6 @@ class IOTopUI(object):
stats_lambda = lambda p: p.stats_delta
processes.sort(key=lambda p: key(p, stats_lambda(p)),
reverse=self.sorting_reverse)
- if not self.options.batch:
- del processes[self.height - 2:]
return list(map(format, processes))
def refresh_display(self, first_time, total, actual, duration):
@@ -448,10 +446,33 @@ class IOTopUI(object):
sys.stdout.flush()
else:
self.win.erase()
+
+ if Stats.has_blkio_delay_total:
+ status_msg = None
+ else:
+ status_msg = ('CONFIG_TASK_DELAY_ACCT not enabled in kernel, '
+ 'cannot determine SWAPIN and IO %')
+
+ len_summary = len(summary)
+ len_titles = int(bool(titles))
+ len_status_msg = int(bool(status_msg))
+ max_lines = self.height - len_summary - len_titles - len_status_msg
+ if max_lines < 5:
+ titles = []
+ len_titles = 0
+ if max_lines < 6:
+ summary = []
+ len_summary = 0
+ if max_lines < 7:
+ status_msg = None
+ len_status_msg = 0
+ max_lines = self.height - len_summary - len_titles - len_status_msg
+ num_lines = min(len(lines), max_lines)
+
for i, s in enumerate(summary):
self.win.addstr(i, 0, s[:self.width])
- self.win.hline(len(summary), 0, ord(' ') | curses.A_REVERSE,
- self.width)
+ if titles:
+ self.win.hline(len_summary, 0, ord(' ') | curses.A_REVERSE, self.width)
pos = 0
remaining_cols = self.width
for i in range(len(titles)):
@@ -464,18 +485,12 @@ class IOTopUI(object):
title += self.sorting_reverse and '>' or '<'
title = title[:remaining_cols]
remaining_cols -= len(title)
- self.win.addstr(len(summary), pos, title, attr)
+ self.win.addstr(len_summary, pos, title, attr)
pos += len(title)
- if Stats.has_blkio_delay_total:
- status_msg = None
- else:
- status_msg = ('CONFIG_TASK_DELAY_ACCT not enabled in kernel, '
- 'cannot determine SWAPIN and IO %')
- num_lines = min(len(lines), self.height - 2 - int(bool(status_msg)))
for i in range(num_lines):
try:
def print_line(line):
- self.win.addstr(i + len(summary) + 1, 0, line)
+ self.win.addstr(i + len_summary + len_titles, 0, line)
try:
print_line(lines[i])
except UnicodeEncodeError:
--
2.33.0

View File

@ -0,0 +1,50 @@
From 529a74a28be43c04840d937c87a5ee3b81133852 Mon Sep 17 00:00:00 2001
From: Paul Wise <pabs3@bonedaddy.net>
Date: Thu, 4 Aug 2016 18:24:46 +0800
Subject: [PATCH] Check the column title is not empty before using it
Fixes crash with terminals that don't fit all titles.
Traceback (most recent call last):
File "./iotop.py", line 12, in <module>
main()
File "./iotop/ui.py", line 669, in main
main_loop()
File "./iotop/ui.py", line 659, in <lambda>
main_loop = lambda: run_iotop(options)
File "./iotop/ui.py", line 554, in run_iotop
return curses.wrapper(run_iotop_window, options)
File "/usr/lib/python3.5/curses/__init__.py", line 94, in wrapper
return func(stdscr, *args, **kwds)
File "./iotop/ui.py", line 546, in run_iotop_window
ui.run()
File "./iotop/ui.py", line 176, in run
self.process_list.duration)
File "./iotop/ui.py", line 515, in refresh_display
self.win.addstr(len_summary, pos, title, attr)
_curses.error: addwstr() returned ERR
Conflict: NA
Reference: https://repo.or.cz/iotop.git/commit/529a74a28be43c04840d937c87a5ee3b81133852
---
iotop/ui.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/iotop/ui.py b/iotop/ui.py
index 30efa73..a957bdd 100644
--- a/iotop/ui.py
+++ b/iotop/ui.py
@@ -511,7 +511,8 @@ class IOTopUI(object):
title += self.sorting_reverse and '>' or '<'
title = title[:remaining_cols]
remaining_cols -= len(title)
- self.win.addstr(len_summary, pos, title, attr)
+ if title:
+ self.win.addstr(len_summary, pos, title, attr)
pos += len(title)
for i in range(num_lines):
try:
--
2.33.0

View File

@ -0,0 +1,151 @@
From 877679bf74d1c84040f00eec2a42e2ace056e45e Mon Sep 17 00:00:00 2001
From: Paul Wise <pabs3@bonedaddy.net>
Date: Thu, 4 Aug 2016 18:53:37 +0800
Subject: [PATCH] Add a footer listing keyboard shortcuts
This makes the program more friendly to new users.
Implements: https://bugs.launchpad.net/ubuntu/+source/iotop/+bug/1429645
Conflict: Adapt patch Context
Reference: https://repo.or.cz/iotop.git/commit/877679bf74d1c84040f00eec2a42e2ace056e45e
---
iotop.8 | 3 +++
iotop/ui.py | 66 +++++++++++++++++++++++++++++++++++++++++++++++++----
2 files changed, 64 insertions(+), 5 deletions(-)
diff --git a/iotop.8 b/iotop.8
index 68d9edd..e34fd6a 100644
--- a/iotop.8
+++ b/iotop.8
@@ -71,6 +71,9 @@ Add a timestamp on each line (implies \-\-batch). Each line will be prefixed by
.TP
\fB\-q\fR, \fB\-\-quiet\fR
suppress some lines of header (implies \-\-batch). This option can be specified up to three times to remove header lines.
+.TP
+\fB\-\-no\-help\fR
+Suppress the keyboard shortcuts help display.
.RS
.PD 0
.TP
diff --git a/iotop/ui.py b/iotop/ui.py
index 56383a2..6867ecb 100644
--- a/iotop/ui.py
+++ b/iotop/ui.py
@@ -29,6 +29,7 @@ import select
import signal
import sys
import time
+from collections import OrderedDict
from iotop.data import find_uids, TaskStatsNetlink, ProcessList, Stats
from iotop.data import ThreadInfo
@@ -181,12 +182,17 @@ class IOTopUI(object):
def adjust_sorting_key(self, delta):
orig_sorting_key = self.sorting_key
- self.sorting_key += delta
- self.sorting_key = max(0, self.sorting_key)
- self.sorting_key = min(len(IOTopUI.sorting_keys) - 1, self.sorting_key)
+ self.sorting_key = self.get_sorting_key(delta)
if orig_sorting_key != self.sorting_key:
self.sorting_reverse = IOTopUI.sorting_keys[self.sorting_key][1]
+ def get_sorting_key(self, delta):
+ new_sorting_key = self.sorting_key
+ new_sorting_key += delta
+ new_sorting_key = max(0, new_sorting_key)
+ new_sorting_key = min(len(IOTopUI.sorting_keys) - 1, new_sorting_key)
+ return new_sorting_key
+
# I wonder if switching to urwid for the display would be better here
def prompt_str(self, prompt, default=None, empty_is_cancel=True):
@@ -453,10 +459,47 @@ class IOTopUI(object):
status_msg = ('CONFIG_TASK_DELAY_ACCT not enabled in kernel, '
'cannot determine SWAPIN and IO %')
+ help_lines = []
+ help_attrs = []
+ if self.options.help:
+ prev = self.get_sorting_key(-1)
+ next = self.get_sorting_key(1)
+ help = OrderedDict([
+ ('keys', ''),
+ ('any', 'refresh'),
+ ('q', 'quit'),
+ ('i', 'ionice'),
+ ('o', 'all' if self.options.only else 'active'),
+ ('p', 'threads' if self.options.processes else 'procs'),
+ ('a', 'bandwidth' if self.options.accumulated else 'accum'),
+ ('sort', ''),
+ ('r', 'asc' if self.sorting_reverse else 'desc'),
+ ('left', titles[prev].strip()),
+ ('right', titles[next].strip()),
+ ('home', titles[0].strip()),
+ ('end', titles[-1].strip()),
+ ])
+ help_line = -1
+ for key, help in help.items():
+ if help:
+ help_item = [' ', key, ': ', help]
+ help_attr = [0, 0 if key == 'any' else curses.A_UNDERLINE, 0, 0]
+ else:
+ help_item = [' ', key, ':']
+ help_attr = [0, 0, 0]
+ if not help_lines or not help or len(''.join(help_lines[help_line]) + ''.join(help_item)) > self.width:
+ help_lines.append(help_item)
+ help_attrs.append(help_attr)
+ help_line += 1
+ else:
+ help_lines[help_line] += help_item
+ help_attrs[help_line] += help_attr
+
len_summary = len(summary)
len_titles = int(bool(titles))
len_status_msg = int(bool(status_msg))
- max_lines = self.height - len_summary - len_titles - len_status_msg
+ len_help = len(help_lines)
+ max_lines = self.height - len_summary - len_titles - len_status_msg - len_help
if max_lines < 5:
titles = []
len_titles = 0
@@ -466,7 +509,11 @@ class IOTopUI(object):
if max_lines < 7:
status_msg = None
len_status_msg = 0
- max_lines = self.height - len_summary - len_titles - len_status_msg
+ if max_lines < 8:
+ help_lines = []
+ help_attrs = []
+ len_help = 0
+ max_lines = self.height - len_summary - len_titles - len_status_msg - len_help
num_lines = min(len(lines), max_lines)
for i, s in enumerate(summary):
@@ -500,6 +547,13 @@ class IOTopUI(object):
print_line(lines[i].encode('utf-8'))
except curses.error:
pass
+ for ln in range(len_help):
+ line = self.height - len_status_msg - len_help + ln
+ self.win.hline(line, 0, ord(' ') | curses.A_REVERSE, self.width)
+ pos = 0
+ for i in range(len(help_lines[ln])):
+ self.win.insstr(line, pos, help_lines[ln][i], curses.A_REVERSE | help_attrs[ln][i])
+ pos += len(help_lines[ln][i])
if status_msg:
self.win.insstr(self.height - len(summary), 0, status_msg,
curses.A_BOLD)
@@ -626,6 +680,8 @@ def main():
help='suppress some lines of header (implies --batch)')
parser.add_option('--profile', action='store_true', dest='profile',
default=False, help=optparse.SUPPRESS_HELP)
+ parser.add_option('--no-help', action='store_false', dest='help', default=True,
+ help='suppress listing of shortcuts')
options, args = parser.parse_args()
if args:
--
2.33.0

View File

@ -0,0 +1,78 @@
From dd4fcc71b1184264bed25fbc0ce7e2d758d8c396 Mon Sep 17 00:00:00 2001
From: Paul Wise <pabs3@bonedaddy.net>
Date: Fri, 1 Oct 2021 07:32:49 +0800
Subject: [PATCH] Document the new kernel.task_delayacct sysctl requirement in
Linux 5.14
Fixes: https://github.com/Tomas-M/iotop/issues/21
Reported-by: @ManuLinares
Forwarded-by: Boian Bonev <bbonev@ipacct.com>
Conflict: Adapt patch context
Reference: https://repo.or.cz/iotop.git/commit/dd4fcc71b1184264bed25fbc0ce7e2d758d8c396
---
README | 3 ++-
iotop.8 | 3 ++-
iotop/data.py | 2 +-
iotop/ui.py | 4 +++-
4 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/README b/README
index cf9e050..3f490ab 100644
--- a/README
+++ b/README
@@ -1,7 +1,8 @@
Iotop is a Python program with a top like UI used to show of behalf of which
process is the I/O going on. It requires Python >= 2.7 and a Linux kernel >=
2.6.20 with the CONFIG_TASK_DELAY_ACCT CONFIG_TASKSTATS,
-CONFIG_TASK_IO_ACCOUNTING and CONFIG_VM_EVENT_COUNTERS options on.
+CONFIG_TASK_IO_ACCOUNTING and CONFIG_VM_EVENT_COUNTERS build options on
+and for Linux kernels since 5.14, the kernel.task_delayacct sysctl enabled.
To run a local version of iotop:
diff --git a/iotop.8 b/iotop.8
index e34fd6a..867871f 100644
--- a/iotop.8
+++ b/iotop.8
@@ -10,7 +10,8 @@ iotop watches I/O usage information output by the Linux kernel (requires
2.6.20 or later) and displays a table of current I/O usage by processes
or threads on the system. At least the CONFIG_TASK_DELAY_ACCT,
CONFIG_TASK_IO_ACCOUNTING, CONFIG_TASKSTATS and CONFIG_VM_EVENT_COUNTERS
-options need to be enabled in your Linux kernel build configuration.
+options need to be enabled in your Linux kernel build configuration and
+since Linux kernel 5.14, the kernel.task_delayacct sysctl enabled.
.PP
iotop displays columns for the I/O bandwidth read and written by each
process/thread during the sampling period. It also displays the percentage
diff --git a/iotop/data.py b/iotop/data.py
index befa9c7..606376f 100644
--- a/iotop/data.py
+++ b/iotop/data.py
@@ -49,7 +49,7 @@ if not ioaccounting or not vm_event_counters:
if not ioaccounting:
print(' - I/O accounting support ' \
'(CONFIG_TASKSTATS, CONFIG_TASK_DELAY_ACCT, ' \
- 'CONFIG_TASK_IO_ACCOUNTING)')
+ 'CONFIG_TASK_IO_ACCOUNTING, kernel.task_delayacct sysctl)')
if not vm_event_counters:
print(' - VM event counters (CONFIG_VM_EVENT_COUNTERS)')
sys.exit(1)
diff --git a/iotop/ui.py b/iotop/ui.py
index 8d10721..5ab8fd4 100644
--- a/iotop/ui.py
+++ b/iotop/ui.py
@@ -456,7 +456,9 @@ class IOTopUI(object):
if Stats.has_blkio_delay_total:
status_msg = None
else:
- status_msg = ('CONFIG_TASK_DELAY_ACCT not enabled in kernel, '
+ status_msg = ('CONFIG_TASK_DELAY_ACCT '
+ 'and kernel.task_delayacct sysctl '
+ 'not enabled in kernel, '
'cannot determine SWAPIN and IO %')
help_lines = []
--
2.33.0

View File

@ -0,0 +1,88 @@
From ab35334d374e588bec12d201fb8869c536f0545d Mon Sep 17 00:00:00 2001
From: Paul Wise <pabs3@bonedaddy.net>
Date: Sat, 2 Oct 2021 12:13:16 +0800
Subject: [PATCH] Detect the kernel.task_delayacct sysctl value
If you have ever turned on the kernel.task_delayacct sysctl for the
current
Linux boot, then the heuristic that iotop uses to find out if swapin/io
are
available, gives a false negative, so the sysctl has to be checked too
now.
Fixes: https://github.com/Tomas-M/iotop/issues/21
Reported-by: @ManuLinares
Forwarded-by: Boian Bonev <bbonev@ipacct.com>
Conflict: Adapt patch context
Reference: https://repo.or.cz/iotop.git/commit/ab35334d374e588bec12d201fb8869c536f0545d
---
iotop/data.py | 8 ++++++++
iotop/ui.py | 14 +++++++++++---
2 files changed, 19 insertions(+), 3 deletions(-)
diff --git a/iotop/data.py b/iotop/data.py
index 606376f..b784a19 100644
--- a/iotop/data.py
+++ b/iotop/data.py
@@ -459,3 +459,11 @@ class ProcessList(DumpableObject):
def clear(self):
self.processes = {}
+
+
+def sysctl_task_delayacct():
+ try:
+ with open('/proc/sys/kernel/task_delayacct') as f:
+ return bool(int(f.read().strip()))
+ except FileNotFoundError:
+ return None
diff --git a/iotop/ui.py b/iotop/ui.py
index 5ab8fd4..4ffbeea 100644
--- a/iotop/ui.py
+++ b/iotop/ui.py
@@ -31,7 +31,7 @@ import sys
import time
from collections import OrderedDict
-from iotop.data import find_uids, TaskStatsNetlink, ProcessList, Stats
+from iotop.data import find_uids, TaskStatsNetlink, ProcessList, Stats, sysctl_task_delayacct
from iotop.data import ThreadInfo
from iotop.version import VERSION
from iotop import ioprio
@@ -383,7 +383,7 @@ class IOTopUI(object):
def format(p):
stats = format_stats(self.options, p, self.process_list.duration)
io_delay, swapin_delay, read_bytes, write_bytes = stats
- if Stats.has_blkio_delay_total:
+ if self.has_swapin_io:
delay_stats = '%7s %7s ' % (swapin_delay, io_delay)
else:
delay_stats = ' ?unavailable? '
@@ -435,6 +435,14 @@ class IOTopUI(object):
pid += 'TID'
titles = [pid, ' PRIO', ' USER', ' DISK READ', ' DISK WRITE',
' SWAPIN', ' IO', ' COMMAND']
+ self.has_swapin_io = Stats.has_blkio_delay_total
+ if self.has_swapin_io:
+ # Linux kernels without the sysctl return None and
+ # iotop just uses the heuristic for those versions.
+ # Linux kernels with the sysctl return True or False
+ # and iotop then uses the sysctl value instead.
+ if sysctl_task_delayacct() == False:
+ self.has_swapin_io = False
lines = self.get_data()
if self.options.time:
titles = [' TIME'] + titles
@@ -453,7 +461,7 @@ class IOTopUI(object):
else:
self.win.erase()
- if Stats.has_blkio_delay_total:
+ if self.has_swapin_io:
status_msg = None
else:
status_msg = ('CONFIG_TASK_DELAY_ACCT '
--
2.33.0

View File

@ -0,0 +1,95 @@
From 9c49d594a5ddea14dcb30f0f2b7dc67018767295 Mon Sep 17 00:00:00 2001
From: Paul Wise <pabs3@bonedaddy.net>
Date: Tue, 1 Feb 2022 11:31:15 +0800
Subject: [PATCH] Automatically hide the SWAPIN/IO columns when they are
unavailable
Now that the Linux kernel can enable or disable data collection for them at
runtime, showing the columns when collection is disabled is even less useful,
since the previous data could still be present in the Linux kernel buffers.
Preserve the behaviour of the batch mode though, so that programs parsing
its output aren't broken by the changes to the Linux kernel, but they may
still be broken when the output changes from ?unavailable? to real data.
Since the current sorting keys code makes it hard to dynamically choose which
columns are shown or hidden, when the two columns are hidden, just skip over
displaying them or using them as sorting keys.
Rewrite the data display code to be more flexible wrt column choice though.
Suggested-by: Boian Bonev <bbonev@ipacct.com>
Conflict: NA
Reference: https://repo.or.cz/iotop.git/commit/9c49d594a5ddea14dcb30f0f2b7dc67018767295
---
iotop/ui.py | 31 ++++++++++++++++++++++++-------
1 file changed, 24 insertions(+), 7 deletions(-)
diff --git a/iotop/ui.py b/iotop/ui.py
index 7ae8bad..77f82c7 100644
--- a/iotop/ui.py
+++ b/iotop/ui.py
@@ -224,6 +224,12 @@ class IOTopUI(object):
new_sorting_key += delta
new_sorting_key = max(0, new_sorting_key)
new_sorting_key = min(len(IOTopUI.sorting_keys) - 1, new_sorting_key)
+ if not self.has_swapin_io:
+ if new_sorting_key in (5, 6):
+ if delta <= 0:
+ new_sorting_key = 4
+ elif delta > 0:
+ new_sorting_key = 7
return new_sorting_key
# I wonder if switching to urwid for the display would be better here
@@ -421,14 +427,22 @@ class IOTopUI(object):
def format(p):
stats = format_stats(self.options, p, self.process_list.duration)
io_delay, swapin_delay, read_bytes, write_bytes = stats
+ format = '%%%dd' % MAX_PID_WIDTH
+ params = p.pid,
+ format += ' %4s'
+ params += p.get_ioprio(),
+ format += ' %-8s'
+ params += p.get_user()[:8],
+ format += ' %11s %11s'
+ params += read_bytes, write_bytes
if self.has_swapin_io:
- delay_stats = '%7s %7s ' % (swapin_delay, io_delay)
- else:
- delay_stats = ' ?unavailable? '
- pid_format = '%%%dd' % MAX_PID_WIDTH
- line = (pid_format + ' %4s %-8s %11s %11s %s') % (
- p.pid, p.get_ioprio(), p.get_user()[:8], read_bytes,
- write_bytes, delay_stats)
+ format += ' %7s %7s'
+ params += swapin_delay, io_delay
+ elif self.options.batch:
+ format += ' %s '
+ params += '?unavailable?',
+ format += ' '
+ line = format % (params)
cmdline = p.get_cmdline()
if not self.options.batch:
remaining_length = self.width - len(line)
@@ -481,6 +495,7 @@ class IOTopUI(object):
# and iotop then uses the sysctl value instead.
if sysctl_task_delayacct() == False:
self.has_swapin_io = False
+ self.adjust_sorting_key(0)
lines = self.get_data()
if self.options.time:
titles = [' TIME'] + titles
@@ -571,6 +586,8 @@ class IOTopUI(object):
pos = 0
remaining_cols = self.width
for i in range(len(titles)):
+ if not self.has_swapin_io and i in (5, 6):
+ continue
attr = curses.A_REVERSE
title = titles[i]
if i == self.sorting_key:
--
2.33.0

View File

@ -1,6 +1,6 @@
Name: iotop
Version: 0.6
Release: 27
Release: 28
Summary: Simple top-like I/O monitor
License: GPLv2+
URL: http://guichaz.free.fr/iotop/
@ -23,6 +23,12 @@ Patch10: 0010-Fix-crash-due-to-syntax-error.patch
Patch11: 0011-Use-monotonic-time-to-calculate-durations.patch
Patch12: 0012-riscv-Add-riscv64-support.patch
Patch13: 0013-loongarch64-add-loongarch64-support.patch
Patch14: 0014-Hide-UI-elements-on-smaller-terminals.patch
Patch15: 0015-Check-the-column-title-is-not-empty-before-using-it.patch
Patch16: 0016-Add-a-footer-listing-keyboard-shortcuts.patch
Patch17: 0017-Document-the-new-kernel.task_delayacct-sysctl-requir.patch
Patch18: 0018-Detect-the-kernel.task_delayacct-sysctl-value.patch
Patch19: 0019-Automatically-hide-the-SWAPIN-IO-columns-when-they-a.patch
%description
iotop watches I/O usage information output by the Linux kernel (requires 2.6.20 or later) and
@ -61,6 +67,10 @@ This contains man files for the using of iotop
%changelog
* Thu Nov 14 2024 lvyy <lyunmail@163.com> - 0.6-28
- Fix SWAPIN I/O display issue
Add a footer listing keyboard shortcuts
* Tue Jul 2 2024 cenhuilin <cenhuilin@kylinos.cn> - 0.6-27
- loongarch64: add loongarch64 support