From bfa160b9ba27abd18f2f9bf225ea7fcfb03677f4 Mon Sep 17 00:00:00 2001 Date: Wed, 6 Oct 2021 15:17:32 -0400 Subject: [PATCH] tryfix --- README | 3 ++- iotop.8 | 3 ++- iotop/data.py | 10 +++++++++- iotop/ui.py | 18 ++++++++++++++---- 4 files changed, 27 insertions(+), 7 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 68d9edd..e62ed3d 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 25b659e..e796d46 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) @@ -453,3 +453,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 e033c92..9aa56ef 100644 --- a/iotop/ui.py +++ b/iotop/ui.py @@ -30,7 +30,7 @@ import signal import sys import time -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 @@ -377,7 +377,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? ' @@ -431,6 +431,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 @@ -464,10 +472,12 @@ class IOTopUI(object): title = title[:remaining_cols] remaining_cols -= len(title) self.win.addstr(title, attr) - if Stats.has_blkio_delay_total: + if self.has_swapin_io: 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 %') num_lines = min(len(lines), self.height - 2 - int(bool(status_msg))) for i in range(num_lines): -- 2.33.0