Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package iotop-c for openSUSE:Factory checked in at 2022-02-03 23:16:41 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/iotop-c (Old) and /work/SRC/openSUSE:Factory/.iotop-c.new.1898 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "iotop-c" Thu Feb 3 23:16:41 2022 rev:2 rq:950831 version:1.21 Changes: -------- --- /work/SRC/openSUSE:Factory/iotop-c/iotop-c.changes 2022-01-06 15:52:00.452995116 +0100 +++ /work/SRC/openSUSE:Factory/.iotop-c.new.1898/iotop-c.changes 2022-02-03 23:17:39.576132305 +0100 @@ -1,0 +2,9 @@ +Wed Feb 02 23:28:14 UTC 2022 - jonat...@jontech.app + +- Update to version 1.21: + * Better support for disabled task_delayacct sysctl + * Add history and graph for all data + * Restore simple inline help +- Fix debuginfo generation + +------------------------------------------------------------------- Old: ---- iotop-c-1.20.tar.xz New: ---- iotop-c-1.21.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ iotop-c.spec ++++++ --- /var/tmp/diff_new_pack.LRAYav/_old 2022-02-03 23:17:40.076128892 +0100 +++ /var/tmp/diff_new_pack.LRAYav/_new 2022-02-03 23:17:40.084128838 +0100 @@ -1,7 +1,7 @@ # # spec file for package iotop-c # -# Copyright (c) 2021 SUSE LLC +# Copyright (c) 2022 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -17,7 +17,7 @@ Name: iotop-c -Version: 1.20 +Version: 1.21 Release: 0 Summary: Simple top-like I/O monitor (implemented in C) License: GPL-2.0-or-later @@ -46,10 +46,11 @@ %setup -q %build +export CFLAGS="%{optflags}" %make_build %install -%make_install +V=1 STRIP=: %make_install %files %{_sbindir}/* ++++++ _service ++++++ --- /var/tmp/diff_new_pack.LRAYav/_old 2022-02-03 23:17:40.124128564 +0100 +++ /var/tmp/diff_new_pack.LRAYav/_new 2022-02-03 23:17:40.128128537 +0100 @@ -1,6 +1,6 @@ <services> <service name="tar_scm" mode="disabled"> - <param name="versionformat">1.20</param> + <param name="versionformat">1.21</param> <param name="url">https://github.com/Tomas-M/iotop</param> <param name="scm">git</param> <param name="changesgenerate">enable</param> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.LRAYav/_old 2022-02-03 23:17:40.148128400 +0100 +++ /var/tmp/diff_new_pack.LRAYav/_new 2022-02-03 23:17:40.152128373 +0100 @@ -1,6 +1,6 @@ <servicedata> <service name="tar_scm"> <param name="url">https://github.com/Tomas-M/iotop</param> - <param name="changesrevision">80df473761510288b3ae9578726b8246e59b4803</param></service></servicedata> + <param name="changesrevision">b12c370c6f495d717adecfe6af0f4920c8e43834</param></service></servicedata> (No newline at EOF) ++++++ iotop-c-1.20.tar.xz -> iotop-c-1.21.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iotop-c-1.20/TODO new/iotop-c-1.21/TODO --- old/iotop-c-1.20/TODO 2021-11-15 22:33:24.000000000 +0100 +++ new/iotop-c-1.21/TODO 2022-01-27 20:37:46.000000000 +0100 @@ -1,4 +1,3 @@ -- restore some form of visible help on the bottom --- history of finished TODO items --- @@ -21,3 +20,10 @@ - Add all missing keys to help window - Freezed, scrollable view of procs/threads for ionice selection (abandoned idea - exited processes should be kept track of) - ESC key close the help dialog +- let the warning window about missing task_delayacct be closed by any key press and reappear on state change +- add a small red indicator for missing kernel support for swapin/io +- mask swapin/io columns and io graph data source if kernel support is disabled +- do not sort on masked columns but continue to sort on hidden ones +- add read/write/read+write data sources for the graph +- add a toggle to select graph data source (as a side effect option 'only' will use the same) +- restore some form of visible help on the bottom diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iotop-c-1.20/archlinux/PKGBUILD new/iotop-c-1.21/archlinux/PKGBUILD --- old/iotop-c-1.20/archlinux/PKGBUILD 2021-11-15 22:33:24.000000000 +0100 +++ new/iotop-c-1.21/archlinux/PKGBUILD 2022-01-27 20:37:46.000000000 +0100 @@ -3,7 +3,7 @@ # Maintainer: Boian Bonev <bbo...@ipacct.com> pkgname=iotop-c -pkgver=1.20 +pkgver=1.21 pkgrel=1 pkgdesc="simple top-like I/O monitor (implemented in C)" arch=('any') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iotop-c-1.20/debian/changelog new/iotop-c-1.21/debian/changelog --- old/iotop-c-1.20/debian/changelog 2021-11-15 22:33:24.000000000 +0100 +++ new/iotop-c-1.21/debian/changelog 2022-01-27 20:37:46.000000000 +0100 @@ -1,3 +1,13 @@ +iotop-c (1.21~pre3-1) unstable; urgency=medium + + * Update to new upstream release of 1.21 + - Better support for disabled task_delayacct sysctl + - Add history and graph for all data + - Restore simple inline help + * Remove filenamemangle from d/watch + + -- Boian Bonev <bbo...@ipacct.com> Wed, 26 Jan 2022 15:20:46 +0000 + iotop-c (1.20-1) unstable; urgency=medium * Update to new upstream release of 1.20 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iotop-c-1.20/debian/copyright new/iotop-c-1.21/debian/copyright --- old/iotop-c-1.20/debian/copyright 2021-11-15 22:33:24.000000000 +0100 +++ new/iotop-c-1.21/debian/copyright 2022-01-27 20:37:46.000000000 +0100 @@ -5,11 +5,11 @@ Files: * Copyright: 2014 Vyacheslav Trushkin - 2020,2021 Boian Bonev <bbo...@ipacct.com> + 2020-2022 Boian Bonev <bbo...@ipacct.com> License: GPL-2.0+ Files: debian/* -Copyright: 2020,2021 Boian Bonev <bbo...@ipacct.com> +Copyright: 2020-2022 Boian Bonev <bbo...@ipacct.com> License: GPL-2.0+ License: GPL-2.0+ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iotop-c-1.20/debian/watch new/iotop-c-1.21/debian/watch --- old/iotop-c-1.20/debian/watch 2021-11-15 22:33:24.000000000 +0100 +++ new/iotop-c-1.21/debian/watch 2022-01-27 20:37:46.000000000 +0100 @@ -1,7 +1,7 @@ version=4 opts=\ - "filenamemangle=s%(?:.*?)?iotop-?(\d[\d.]*)\.tar\.xz%iotop-c_$1.orig.tar.xz%,pgpsigurlmangle=s/releases\/download\/v([0-9.]+)\/iotop-([0-9.]+)\.tar\.xz/releases\/download\/v$1\/iotop-$1\.tar\.xz\.asc/" \ + "pgpsigurlmangle=s/releases\/download\/v([0-9.]+)\/iotop-([0-9.]+)\.tar\.xz/releases\/download\/v$1\/iotop-$1\.tar\.xz\.asc/" \ https://github.com/Tomas-M/iotop/releases \ (?:.*?/)?iotop-?(\d[\d.]*)\.tar\.xz \ debian uupdate diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iotop-c-1.20/fedora/iotop-c.spec new/iotop-c-1.21/fedora/iotop-c.spec --- old/iotop-c-1.20/fedora/iotop-c.spec 2021-11-15 22:33:24.000000000 +0100 +++ new/iotop-c-1.21/fedora/iotop-c.spec 2022-01-27 20:37:46.000000000 +0100 @@ -1,5 +1,5 @@ Name: iotop-c -Version: 1.20 +Version: 1.21 Release: 1%{?dist} Summary: Simple top-like I/O monitor (implemented in C) @@ -52,7 +52,13 @@ %{_mandir}/man8/iotop-c.8* %changelog -* Mon Sep 04 2021 Boian Bonev <bbo...@ipacct.com> - 1.20-1 +* Wed Jan 26 2022 Boian Bonev <bbo...@ipacct.com> - 1.21-1 +- Update to latest ver 1.21 + +* Thu Jan 20 2022 Fedora Release Engineering <rel...@fedoraproject.org> - 1.20-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild + +* Mon Oct 04 2021 Boian Bonev <bbo...@ipacct.com> - 1.20-1 - Update to latest ver 1.20 * Tue Sep 21 2021 Boian Bonev <bbo...@ipacct.com> - 1.19-1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iotop-c-1.20/iotop.8 new/iotop-c-1.21/iotop.8 --- old/iotop-c-1.20/iotop.8 2021-11-15 22:33:24.000000000 +0100 +++ new/iotop-c-1.21/iotop.8 2022-01-27 20:37:46.000000000 +0100 @@ -11,12 +11,12 @@ CONFIG_TASK_IO_ACCOUNTING, CONFIG_TASKSTATS and CONFIG_VM_EVENT_COUNTERS options need to be enabled in your Linux kernel build configuration. .PP -Running \fBiotop\fR as non-root user is possible by adding the NET_ADMIN +Running \fBiotop\fR as non\-root user is possible by adding the NET_ADMIN capability. This can be done by e.g.: .RS .B -$ sudo setcap 'cap_net_admin+eip' <path-to>/iotop +$ sudo setcap 'cap_net_admin+eip' <path\-to>/iotop .RE Be warned that this will also allow other users to run it and get access to @@ -44,9 +44,9 @@ column is hidden), \fBp\fR to toggle the \fB\-\-processes\fR option, \fBa\fR to toggle the \fB\-\-accumulated\fR option, \fBi\fR to change the priority of a thread or a process's thread, \fBf\fR to change filtering by -\fBUID\fR/\fBPID\fR (\fB\-\-user\fR and \fB\-\-pid\fR options), \fB1-9\fR to +\fBUID\fR/\fBPID\fR (\fB\-\-user\fR and \fB\-\-pid\fR options), \fB1\-9\fR to toggle the visibility of the respective column, \fB0\fR to show all columns, -\fBup\fR/\fBdown\fR arrows, \fBpage-up\fR/\fBpage-down\fR/\fBhome\fR/\fBend\fR +\fBup\fR/\fBdown\fR arrows, \fBpage\-up\fR/\fBpage\-down\fR/\fBhome\fR/\fBend\fR keys to scroll and \fBq\fR to quit. Any unrecognized key will be ignored. .PP All processes or threads that have exited are displayed grayed for the same time @@ -65,7 +65,7 @@ When showing threads, they always appear below their main process and are sorted in the same way as the processes. .PP -There are two ways to change the IO priority of a process or thread - press +There are two ways to change the IO priority of a process or thread \- press \fBi\fR and use arrows to select the process or thread from the visible ones on screen or press \fBi\fR and type its TID (PID and TID have the same value for the main process). Then use \fBtab\fR and arrows to change the priority value @@ -80,7 +80,7 @@ .PP Starting with Linux kernel 5.14.x task_delayacct is configurable at runtime and set to off by default. This setting can be changed in interactive mode by the -\fBCtrl-T\fR shortcut. In batch mode a warning is printed when the setting is +\fBCtrl\-T\fR shortcut. In batch mode a warning is printed when the setting is OFF. From the command line this can be enabled by: .RS @@ -106,6 +106,10 @@ \fB\-h\fR, \fB\-\-help\fR Show usage information and exit .TP +\fB\-H\fR, \fB\-\-help\-type\fR=\fITYPE\fR +Set the type of interactive help shown. Accepted values for \fITYPE\fR are +\fBnone\fR, \fBwin\fR and \fBinline\fR. +.TP \fB\-o\fR, \fB\-\-only\fR Only show processes or threads actually doing I/O, instead of showing all processes or threads. This can be dynamically toggled by pressing \fBo\fR @@ -114,21 +118,21 @@ Turn on non\-interactive mode. Useful for logging I/O usage over time .TP -\fB\-n\fR NUM, \fB\-\-iter\fR=\fINUM\fR +\fB\-n\fR \fINUM\fR, \fB\-\-iter\fR=\fINUM\fR Set the number of iterations before quitting (never quit by default). This is most useful in non\-interactive mode .TP -\fB\-d\fR SEC, \fB\-\-delay\fR=\fISEC\fR +\fB\-d\fR \fISEC\fR, \fB\-\-delay\fR=\fISEC\fR Set the delay between iterations in seconds (1 second by default). -Accepts non-integer values such as 1.1 seconds +Accepts non\-integer values such as 1.1 seconds .TP -\fB\-p\fR PID, \fB\-\-pid\fR=\fIPID\fR +\fB\-p\fR \fIPID\fR, \fB\-\-pid\fR=\fIPID\fR A process/thread id to monitor (all by default) .TP -\fB\-u\fR USER, \fB\-\-user\fR=\fIUSER\fR +\fB\-u\fR \fIUSER\fR, \fB\-\-user\fR=\fIUSER\fR A user id to monitor (all by default). The value will always be resolved first unless it is prefixed by \fB+\fR in -which case it is threated as numeric only. Values that do not resolve but appear +which case it is treated as numeric only. Values that do not resolve but appear to be numeric are used as numeric .TP \fB\-P\fR, \fB\-\-processes\fR @@ -151,33 +155,37 @@ \fB\-c\fR, \fB\-\-fullcmdline\fR Show processes' full file path and parameters .TP -\fB\-1\fR, \fB\-\-hide-pid\fR +\fB\-1\fR, \fB\-\-hide\-pid\fR Hide PID/TID column .TP -\fB\-2\fR, \fB\-\-hide-prio\fR +\fB\-2\fR, \fB\-\-hide\-prio\fR Hide PRIO column .TP -\fB\-3\fR, \fB\-\-hide-user\fR +\fB\-3\fR, \fB\-\-hide\-user\fR Hide USER column .TP -\fB\-4\fR, \fB\-\-hide-read\fR +\fB\-4\fR, \fB\-\-hide\-read\fR Hide DISK READ column .TP -\fB\-5\fR, \fB\-\-hide-write\fR +\fB\-5\fR, \fB\-\-hide\-write\fR Hide DISK WRITE column .TP -\fB\-6\fR, \fB\-\-hide-swapin\fR +\fB\-6\fR, \fB\-\-hide\-swapin\fR Hide SWAPIN column .TP -\fB\-7\fR, \fB\-\-hide-io\fR +\fB\-7\fR, \fB\-\-hide\-io\fR Hide IO column .TP -\fB\-8\fR, \fB\-\-hide-graph\fR +\fB\-8\fR, \fB\-\-hide\-graph\fR Hide GRAPH column .TP -\fB\-9\fR, \fB\-\-hide-command\fR +\fB\-9\fR, \fB\-\-hide\-command\fR Hide COMMAND column .TP +\fB\-g\fR \fITYPE\fR, \fB\-\-grtype\fR=\fITYPE\fR +Set GRAPH column data source. Accepted values for \fITYPE\fR are \fBio\fR, +\fBr\fR, \fBw\fR, \fBrw\fR and \fBsw\fR. +.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 @@ -212,10 +220,10 @@ \fB<end>\fR Scroll to the bottom of the list .TP -\fB<page-up>\fR +\fB<page\-up>\fR Scroll one screen up .TP -\fB<page-down>\fR +\fB<page\-down>\fR Scroll one screen down .TP \fB<up>\fR @@ -255,6 +263,10 @@ \fB0\fR Show all columns .TP +\fBg\fR, \fBG\fR +Cycle GRAPH source (\fBIO\fR=IO, \fBR\fR=DISK READ , \fBW\fR=DISK WRITE, \fBR+W\fR=DISK READ+DISK WRITE, +\fBSW\fR=SWAPIN). Using \fBg\fR will cycle forward and \fBG\fR will cycle backward. +.TP \fBi\fR, \fBI\fR IOnice a process/thread (depends on process/thread display mode) .TP @@ -271,7 +283,7 @@ \fBs\fR, \fBS\fR Toggle freeze of data collection .TP -\fBCtrl-T\fR +\fBCtrl\-T\fR Toggle task_delayacct kernel sysctl .SH SEE ALSO .BR ionice (1), diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iotop-c-1.20/src/arr.c new/iotop-c-1.21/src/arr.c --- old/iotop-c-1.20/src/arr.c 2021-11-15 22:33:24.000000000 +0100 +++ new/iotop-c-1.21/src/arr.c 2022-01-27 20:37:46.000000000 +0100 @@ -1,7 +1,7 @@ /* SPDX-License-Identifer: GPL-2.0-or-later Copyright (C) 2014 Vyacheslav Trushkin -Copyright (C) 2020,2021 Boian Bonev +Copyright (C) 2020-2022 Boian Bonev This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iotop-c-1.20/src/checks.c new/iotop-c-1.21/src/checks.c --- old/iotop-c-1.20/src/checks.c 2021-11-15 22:33:24.000000000 +0100 +++ new/iotop-c-1.21/src/checks.c 2022-01-27 20:37:46.000000000 +0100 @@ -1,7 +1,7 @@ /* SPDX-License-Identifer: GPL-2.0-or-later Copyright (C) 2014 Vyacheslav Trushkin -Copyright (C) 2020,2021 Boian Bonev +Copyright (C) 2020-2022 Boian Bonev This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iotop-c-1.20/src/delayacct.c new/iotop-c-1.21/src/delayacct.c --- old/iotop-c-1.20/src/delayacct.c 2021-11-15 22:33:24.000000000 +0100 +++ new/iotop-c-1.21/src/delayacct.c 2022-01-27 20:37:46.000000000 +0100 @@ -1,7 +1,7 @@ /* SPDX-License-Identifer: GPL-2.0-or-later Copyright (C) 2014 Vyacheslav Trushkin -Copyright (C) 2020,2021 Boian Bonev +Copyright (C) 2020-2022 Boian Bonev This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iotop-c-1.20/src/ioprio.c new/iotop-c-1.21/src/ioprio.c --- old/iotop-c-1.20/src/ioprio.c 2021-11-15 22:33:24.000000000 +0100 +++ new/iotop-c-1.21/src/ioprio.c 2022-01-27 20:37:46.000000000 +0100 @@ -1,7 +1,7 @@ /* SPDX-License-Identifer: GPL-2.0-or-later Copyright (C) 2014 Vyacheslav Trushkin -Copyright (C) 2020,2021 Boian Bonev +Copyright (C) 2020-2022 Boian Bonev This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iotop-c-1.20/src/iotop.h new/iotop-c-1.21/src/iotop.h --- old/iotop-c-1.20/src/iotop.h 2021-11-15 22:33:24.000000000 +0100 +++ new/iotop-c-1.21/src/iotop.h 2022-01-27 20:37:46.000000000 +0100 @@ -1,7 +1,7 @@ /* SPDX-License-Identifer: GPL-2.0-or-later Copyright (C) 2014 Vyacheslav Trushkin -Copyright (C) 2020,2021 Boian Bonev +Copyright (C) 2020-2022 Boian Bonev This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -27,7 +27,17 @@ #include <sys/types.h> #include <stdint.h> -#define VERSION "1.20" +#define VERSION "1.21" + +typedef enum { + E_GR_IO, + E_GR_R, + E_GR_W, + E_GR_RW, + E_GR_SW, + E_GR_MIN=E_GR_IO, + E_GR_MAX=E_GR_SW, +} e_grtype; typedef union { struct _flags { @@ -48,11 +58,13 @@ int hideio; int hidegraph; int hidecmd; + int deadx; + e_grtype grtype; + int helptype; int sort_by; int sort_order; - int deadx; } f; - int opts[19]; + int opts[20]; } config_t; typedef struct { @@ -99,7 +111,11 @@ char *cmdline2; char *pw_name; - uint8_t iohist[HISTORY_CNT]; + uint8_t iohist[HISTORY_CNT]; // io history data + uint8_t sihist[HISTORY_CNT]; // swapin history data + double readhist[HISTORY_CNT]; // read history data + double writehist[HISTORY_CNT]; // write history data + int exited; // exited>0 shows for how many refresh cycles the process is gone // there is no point to keep in memory data for processes exited before HISTORY_CNT cycles struct xxxid_stats_arr *threads; @@ -146,6 +162,9 @@ inline unsigned int curses_sleep(unsigned int seconds); +inline e_grtype masked_grtype(int isforward); +inline int masked_sort_by(int isforward); + /* utils.c */ inline char *read_cmdline(int pid,int isshort); @@ -175,7 +194,7 @@ }; enum { - SORT_BY_PID, + SORT_BY_TID, SORT_BY_PRIO, SORT_BY_USER, SORT_BY_READ, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iotop-c-1.20/src/main.c new/iotop-c-1.21/src/main.c --- old/iotop-c-1.20/src/main.c 2021-11-15 22:33:24.000000000 +0100 +++ new/iotop-c-1.21/src/main.c 2022-01-27 20:37:46.000000000 +0100 @@ -1,7 +1,7 @@ /* SPDX-License-Identifer: GPL-2.0-or-later Copyright (C) 2014 Vyacheslav Trushkin -Copyright (C) 2020,2021 Boian Bonev +Copyright (C) 2020-2022 Boian Bonev This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -54,30 +54,32 @@ "option, a to toggle the --accumulated option, i to change I/O priority, q to\n" "quit, any other key to force a refresh.\n\n" "Options:\n" - " -v, --version show program's version number and exit\n" - " -h, --help show this help message and exit\n" - " -o, --only only show processes or threads actually doing I/O\n" - " -b, --batch non-interactive mode\n" - " -n NUM, --iter=NUM number of iterations before ending [infinite]\n" - " -d SEC, --delay=SEC delay between iterations [1 second]\n" - " -p PID, --pid=PID processes/threads to monitor [all]\n" - " -u USER, --user=USER users to monitor [all]\n" - " -P, --processes only show processes, not all threads\n" - " -a, --accumulated show accumulated I/O instead of bandwidth\n" - " -k, --kilobytes use kilobytes instead of a human friendly unit\n" - " -t, --time add a timestamp on each line (implies --batch)\n" - " -c, --fullcmdline show full command line\n" - " -1, --hide-pid hide PID/TID column\n" - " -2, --hide-prio hide PRIO column\n" - " -3, --hide-user hide USER column\n" - " -4, --hide-read hide DISK READ column\n" - " -5, --hide-write hide DISK WRITE column\n" - " -6, --hide-swapin hide SWAPIN column\n" - " -7, --hide-io hide IO column\n" - " -8, --hide-graph hide GRAPH column\n" - " -9, --hide-command hide COMMAND column\n" - " -q, --quiet suppress some lines of header (implies --batch)\n" - " -x, --dead-x show dead processes/threads with letter x\n", + " -v, --version show program's version number and exit\n" + " -h, --help show this help message and exit\n" + " -H, --help-type=TYPE set type of interactive help (none, win or inline)\n" + " -o, --only only show processes or threads actually doing I/O\n" + " -b, --batch non-interactive mode\n" + " -n NUM, --iter=NUM number of iterations before ending [infinite]\n" + " -d SEC, --delay=SEC delay between iterations [1 second]\n" + " -p PID, --pid=PID processes/threads to monitor [all]\n" + " -u USER, --user=USER users to monitor [all]\n" + " -P, --processes only show processes, not all threads\n" + " -a, --accumulated show accumulated I/O instead of bandwidth\n" + " -k, --kilobytes use kilobytes instead of a human friendly unit\n" + " -t, --time add a timestamp on each line (implies --batch)\n" + " -c, --fullcmdline show full command line\n" + " -1, --hide-pid hide PID/TID column\n" + " -2, --hide-prio hide PRIO column\n" + " -3, --hide-user hide USER column\n" + " -4, --hide-read hide DISK READ column\n" + " -5, --hide-write hide DISK WRITE column\n" + " -6, --hide-swapin hide SWAPIN column\n" + " -7, --hide-io hide IO column\n" + " -8, --hide-graph hide GRAPH column\n" + " -9, --hide-command hide COMMAND column\n" + " -g TYPE, --grtype=TYPE set graph data source (io, r, w, rw and sw)\n" + " -q, --quiet suppress some lines of header (implies --batch)\n" + " -x, --dead-x show dead processes/threads with letter x\n", progname ); } @@ -92,6 +94,7 @@ static struct option long_options[]={ {"version",no_argument,NULL,'v'}, {"help",no_argument,NULL,'h'}, + {"help-type",required_argument,NULL,'H'}, {"batch",no_argument,NULL,'b'}, {"only",no_argument,NULL,'o'}, {"iter",required_argument,NULL,'n'}, @@ -114,10 +117,11 @@ {"hide-graph",no_argument,NULL,'8'}, {"hide-command",no_argument,NULL,'9'}, {"dead-x",no_argument,NULL,'x'}, + {"grtype",required_argument,NULL,'g'}, {NULL,0,NULL,0} }; - int c=getopt_long(argc,argv,"vhbon:d:p:u:Paktqc123456789x",long_options,NULL); + int c=getopt_long(argc,argv,"vhbon:d:p:u:Paktqc123456789xg:H:",long_options,NULL); if (c==-1) { if (optind<argc) { @@ -137,6 +141,18 @@ case 'h': print_help(); exit(EXIT_SUCCESS); + case 'H': // below values are not partial prefixes of each other, do a relaxed match + if (!strncmp(optarg,"none",strlen(optarg))) + config.f.helptype=0; + else if (!strncmp(optarg,"win",strlen(optarg))) + config.f.helptype=1; + else if (!strncmp(optarg,"inline",strlen(optarg))) + config.f.helptype=2; + else { + fprintf(stderr,"%s: invalid value %s for interactive help type\n",progname,optarg); + exit(EXIT_FAILURE); + } + break; case 'o': case 'b': case 'P': @@ -158,6 +174,24 @@ case 'p': params.pid=atoi(optarg); break; + case 'g': // below values are not partial prefixes of each other, do a relaxed match + // except r is a prefix of rw, but r is matched first + // do an exact match for r and w - there is no point in relaxed match for single letter values + if (!strncmp(optarg,"io",strlen(optarg))) + config.f.grtype=E_GR_IO; + else if (!strcmp(optarg,"r")) + config.f.grtype=E_GR_R; + else if (!strcmp(optarg,"w")) + config.f.grtype=E_GR_W; + else if (!strcmp(optarg,"rw")) + config.f.grtype=E_GR_RW; + else if (!strncmp(optarg,"sw",strlen(optarg))) + config.f.grtype=E_GR_SW; + else { + fprintf(stderr,"%s: invalid value %s for graph type\n",progname,optarg); + exit(EXIT_FAILURE); + } + break; case 'u': if (optarg[0]=='+') // always interpret as numeric uid params.user_id=atoi(optarg+1); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iotop-c-1.20/src/utils.c new/iotop-c-1.21/src/utils.c --- old/iotop-c-1.20/src/utils.c 2021-11-15 22:33:24.000000000 +0100 +++ new/iotop-c-1.21/src/utils.c 2022-01-27 20:37:46.000000000 +0100 @@ -1,7 +1,7 @@ /* SPDX-License-Identifer: GPL-2.0-or-later Copyright (C) 2014 Vyacheslav Trushkin -Copyright (C) 2020,2021 Boian Bonev +Copyright (C) 2020-2022 Boian Bonev This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iotop-c-1.20/src/view_batch.c new/iotop-c-1.21/src/view_batch.c --- old/iotop-c-1.20/src/view_batch.c 2021-11-15 22:33:24.000000000 +0100 +++ new/iotop-c-1.21/src/view_batch.c 2022-01-27 20:37:46.000000000 +0100 @@ -1,7 +1,7 @@ /* SPDX-License-Identifer: GPL-2.0-or-later Copyright (C) 2014 Vyacheslav Trushkin -Copyright (C) 2020,2021 Boian Bonev +Copyright (C) 2020-2022 Boian Bonev This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iotop-c-1.20/src/view_curses.c new/iotop-c-1.21/src/view_curses.c --- old/iotop-c-1.20/src/view_curses.c 2021-11-15 22:33:24.000000000 +0100 +++ new/iotop-c-1.21/src/view_curses.c 2022-01-27 20:37:46.000000000 +0100 @@ -1,7 +1,7 @@ /* SPDX-License-Identifer: GPL-2.0-or-later Copyright (C) 2014 Vyacheslav Trushkin -Copyright (C) 2020,2021 Boian Bonev +Copyright (C) 2020-2022 Boian Bonev This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -34,6 +34,9 @@ #define HEADER_XL_FORMAT "Total Read: %7.2f %s%s Write: %7.2f %s%s | Current Read: %7.2f %s%s Write: %7.2f %s%s" #define RED_PAIR 1 +#define CYAN_PAIR 2 + +#define mymax(a,b) (((a)>(b))?(a):(b)) static int in_ionice=0; // ionice interface flag and state vars static char ionice_id[50]; @@ -59,8 +62,9 @@ static int viewsizey=0; // how many lines we can show on screen static int dispcount=0; // how many lines we have after filters static int lastvisible=0; // last visible screen line -static int showhelp=0; // flag if help window is shown +static int noinlinehelp=0; // should inline help be allowed static int showtda=0; // flag if delayacct warning window is shown +static int has_tda=1; // flag if delayacct kernel support is enabled static WINDOW *whelp; // pop-up help window static int hx=1,hy=1,hw=2+2+3,hh=2; // help window size and position static size_t c1w=0,c2w=0,c3w=0,cdw=0; // help window column widths @@ -91,7 +95,6 @@ {.descr="Toggle showing only processes with IO activity",.k2="o",.k3="O"}, {.descr="Toggle showing processes/threads",.k2="p",.k3="P"}, {.descr="Toggle showing accumulated/current values",.k2="a",.k3="A"}, - {.descr="Toggle showing this help",.k1=" ?",.k2="h",.k3="H"}, // padded to match <page-down> {.descr="Toggle showing full command line",.k2="c",.k3="C"}, {.descr="Toggle showing TID",.k2="1"}, {.descr="Toggle showing PRIO",.k2="2"}, @@ -103,15 +106,26 @@ {.descr="Toggle showing GRAPH",.k2="8"}, {.descr="Toggle showing COMMAND",.k2="9"}, {.descr="Show all columns",.k2="0"}, + {.descr="Cycle GRAPH source (IO, R, W, R+W, SW)",.k2="g",.k3="G"}, + {.descr="Cycle showing this, inline or no help",.k1=" ?",.k2="h",.k3="H"}, // padded to match <page-down> {.descr="IOnice a process/thread",.k2="i",.k3="I"}, {.descr="Change UID and PID filters",.k2="f",.k3="F"}, {.descr="Toggle using Unicode/ASCII characters",.k2="u",.k3="U"}, - {.descr="Toggle exited processes x/inverse",.k2="x",.k3="X"}, + {.descr="Toggle exited processes xxx/inverse",.k2="x",.k3="X"}, {.descr="Toggle data freeze",.k2="s",.k3="S"}, - {.descr="Toggle task_delayacct (if available)",.k1="<ctrl-t>",.k2="",.k3=""}, + {.descr="Toggle task_delayacct (if available)",.k1="<Ctrl-T>",.k2="",.k3=""}, + {.descr="Redraw screen",.k1="<Ctrl-L>",.k2="",.k3=""}, {.descr=NULL}, }; +static const char *grtype_text[]={ + "GRAPH[IO]", + "GRAPH[R]", + "GRAPH[W]", + "GRAPH[R+W]", + "GRAPH[SW]", +}; + static const char *column_name[]={ "TID", " PRIO", @@ -120,7 +134,7 @@ "DISK WRITE", "SWAPIN", "IO", - "GRAPH", + "xxxxx[xxx]", "COMMAND", }; @@ -160,16 +174,30 @@ 0, // COMMAND }; -#define __COLUMN_NAME(i) (column_name[(i)]) +#define __COLUMN_NAME(i) (((i)==SORT_BY_GRAPH)?grtype_text[masked_grtype(0)]:column_name[(i)]) #define __SAFE_INDEX(i) ((((i)%SORT_BY_MAX)+SORT_BY_MAX)%SORT_BY_MAX) #define COLUMN_NAME(i) __COLUMN_NAME(__SAFE_INDEX(i)) #define COLUMN_L(i) COLUMN_NAME((i)-1) #define COLUMN_R(i) COLUMN_NAME((i)+1) -#define SORT_CHAR_IND(x) ((config.f.sort_by==x)?(config.f.sort_order==SORT_ASC?1:2):0) +#define SORT_CHAR_IND(x) ((masked_sort_by(0)==x)?(config.f.sort_order==SORT_ASC?1:2):0) #define SORT_CHAR(x) (((has_unicode&&unicode)?sort_dir_u:sort_dir_a)[SORT_CHAR_IND(x)]) #define TIMEDIFF_IN_S(sta,end) ((((sta)==(end))||(sta)==0)?0.0001:(((end)-(sta))/1000.0)) +inline e_grtype masked_grtype(int isforward) { + if (!has_tda) + if (config.f.grtype==E_GR_IO||config.f.grtype==E_GR_SW) + return isforward?E_GR_R:E_GR_RW; + return config.f.grtype; +} + +inline int masked_sort_by(int isforward) { + if (!has_tda) + if (config.f.sort_by==SORT_BY_IO||config.f.sort_by==SORT_BY_SWAPIN) + return isforward?SORT_BY_GRAPH:SORT_BY_WRITE; + return config.f.sort_by; +} + static inline int filter_view(struct xxxid_stats *s,int gr_width) { static const uint8_t iohist_z[HISTORY_CNT]={0}; @@ -178,10 +206,47 @@ return 1; // visible history is non-zero if (config.f.only) { - if (!config.f.hidegraph&&!memcmp(s->iohist,iohist_z,gr_width)) - return 1; - if (config.f.hidegraph&&s->blkio_val<=0) - return 1; + if (config.f.hidegraph) { + if (has_tda) { + if (s->blkio_val<=0) + return 1; + } else { + if (s->read_val+s->write_val<=0) + return 1; + } + } else { + double su=0; + int i; + + switch (masked_grtype(0)) { + case E_GR_IO: + if (!memcmp(s->iohist,iohist_z,gr_width)) + return 1; + break; + case E_GR_R: + for (i=0;i<gr_width;i++) + su+=s->readhist[i]; + if (su<=0) + return 1; + break; + case E_GR_W: + for (i=0;i<gr_width;i++) + su+=s->writehist[i]; + if (su<=0) + return 1; + break; + case E_GR_RW: + for (i=0;i<gr_width;i++) + su+=s->readhist[i]+s->writehist[i]; + if (su<=0) + return 1; + break; + case E_GR_SW: + if (!memcmp(s->sihist,iohist_z,gr_width)) + return 1; + break; + } + } } if (config.f.processes&&s->tid!=s->pid) return 1; @@ -276,7 +341,11 @@ for (p=thelp,i=1;i<hh-1;i++,p++) mvwprintw(whelp,i,0," %-*.*s %-*.*s %-*.*s - %-*.*s ",a,a,p->k1?p->k1:"",b,b,p->k2?p->k2:"",c,c,p->k3?p->k3:"",d,d,p->descr); mvwprintw(whelp,hh-1,0,"%s",(has_unicode&&unicode)?"???":"_"); - for (i=1;i<hw;i++) + wattron(whelp,A_REVERSE); + for (i=1;i<hw&&i<(int)strlen(" iotop "VERSION" ");i++) + mvwprintw(whelp,hh-1,i,"%c",(" iotop "VERSION" ")[i]); + wattroff(whelp,A_REVERSE); + for (i=1+strlen(" iotop "VERSION" ");i<hw;i++) wprintw(whelp,"%s",(has_unicode&&unicode)?"???":"_"); } @@ -298,6 +367,9 @@ mvwprintw(wtda,whh-1,0,"%s",(has_unicode&&unicode)?"???":"_"); for (i=1;i<whw;i++) wprintw(wtda,"%s",(has_unicode&&unicode)?"???":"_"); + wattron(wtda,A_REVERSE); + mvwprintw(wtda,whh-1,1," press a key to hide "); + wattroff(wtda,A_REVERSE); } static inline void view_curses(struct xxxid_stats_arr *cs,struct xxxid_stats_arr *ps,struct act_stats *act,int roll) { @@ -312,6 +384,7 @@ char str_a_read[4],str_a_write[4]; char *head1row_format=""; int promptx=0,prompty=0,show; + double maxvisible=0.0; double mx_t_r=1000.0; double mx_t_w=1000.0; double mx_a_r=1000.0; @@ -345,9 +418,9 @@ maxcmdline-=column_width[SORT_BY_READ]; if (!config.f.hidewrite) maxcmdline-=column_width[SORT_BY_WRITE]; - if (!config.f.hideswapin) + if (!config.f.hideswapin&&has_tda) maxcmdline-=column_width[SORT_BY_SWAPIN]; - if (!config.f.hideio) + if (!config.f.hideio&&has_tda) maxcmdline-=column_width[SORT_BY_IO]; gr_width=maxcmdline/4; if (gr_width<5) @@ -484,7 +557,7 @@ char t[50]; char *ts; - if (i==SORT_BY_PID) + if (i==SORT_BY_TID) wi=maxpidlen+2; if (i==SORT_BY_GRAPH) wi=gr_width+1; @@ -493,11 +566,16 @@ if (config.opts[&config.f.hidepid-config.opts+i]) continue; + // mask swapin and io columns if there is no task_delayacct + if ((&config.f.hidepid-config.opts+i==&config.f.hideswapin-config.opts)&&!has_tda) + continue; + if ((&config.f.hidepid-config.opts+i==&config.f.hideio-config.opts)&&!has_tda) + continue; wt=strlen(COLUMN_NAME(i)); if (wt>wi-1) wt=wi-1; - if (config.f.sort_by==i) + if (masked_sort_by(0)==i) attron(A_BOLD); snprintf(t,sizeof t,"%-*.*s%s",wt,wt,COLUMN_NAME(i),SORT_CHAR(i)); ts=u8strpadt(t,wi); @@ -506,18 +584,31 @@ free(ts); } else printw("%-*.*s",wi,wi,t); - if (config.f.sort_by==i) + if (masked_sort_by(0)==i) attroff(A_BOLD); } attroff(A_REVERSE); - if (dontrefresh&&(maxx-maxcmdline+(config.f.hidecmd?0:strlen(COLUMN_L(0))+1)<(size_t)maxx)) { - size_t xpos=maxx-strlen("[freezed]"); + if ((dontrefresh||!has_tda)&&(maxx-maxcmdline+(config.f.hidecmd?0:strlen(COLUMN_L(0))+1)<(size_t)maxx)) { + size_t xpos=maxx; + + if (!has_tda) + xpos-=strlen("[T]"); + if (dontrefresh) + xpos-=strlen("[freezed]"); // don't step on column descriptions if (xpos<maxx-maxcmdline+(config.f.hidecmd?0:strlen(COLUMN_L(0))+1)) xpos=maxx-maxcmdline+(config.f.hidecmd?0:strlen(COLUMN_L(0))+1); - mvprintw(ionice_line+1,xpos,"[freezed]"); + if (!has_tda) { + attron(A_REVERSE); + attron(COLOR_PAIR(RED_PAIR)); + mvprintw(ionice_line+1,xpos,"[T]"); + attroff(COLOR_PAIR(RED_PAIR)); + attroff(A_REVERSE); + } + if (dontrefresh) + mvprintw(ionice_line+1,xpos+(has_tda?0:strlen("[T]")),"[freezed]"); } // easiest place to print debug info //mvprintw(ionice_line+1,maxx-maxcmdline+strlen(COLUMN_L(0))+1," ... ",...); @@ -527,9 +618,11 @@ iotop_sort_cb(NULL,(void *)(long)((has_unicode&&unicode)?gr_width*2:gr_width)); arr_sort(cs,iotop_sort_cb); + if (maxy<10) + noinlinehelp=1; line=ionice_line+2; lastline=line; - viewsizey=maxy-1-ionice_line; + viewsizey=maxy-1-ionice_line-(noinlinehelp==0&&config.f.helptype==2?2:0); if (viewsizey<0) viewsizey=0; skip=scrollpos; @@ -544,11 +637,71 @@ if (ionice_pos>=lastvisible&&lastvisible>ionice_line+2) ionice_pos=lastvisible-1; } + // get the maximum visible value, normalize all graphs according to that (R, W and R+W only) + if (masked_grtype(0)!=E_GR_IO&&masked_grtype(0)!=E_GR_SW&&!config.f.hidegraph) { + int saveline=line; + + for (i=0;cs->sor&&i<diff_len;i++) { + struct xxxid_stats *ms=cs->sor[i],*s; + + if (ms->pid!=ms->tid) + continue; + if (ms->threads) + arr_sort(ms->threads,iotop_sort_cb); + // show only processes, if configured + for (k=-1;k<(config.f.processes?0:(ms->threads?ms->threads->length:0));k++) { + if (k<0) + s=ms; + else { + if (!ms->threads||!ms->threads->sor) + break; + s=ms->threads->sor[k]; + } + // apply filters + if (filter_view(s,(has_unicode&&unicode)?gr_width*2:gr_width)) + continue; + if (skip) { + skip--; + continue; + } + + for (j=0;j<gr_width;j++) { + if (masked_grtype(0)==E_GR_R) { + if (has_unicode&&unicode) { + maxvisible=mymax(maxvisible,s->readhist[j*2]); + maxvisible=mymax(maxvisible,s->readhist[j*2+1]); + } else + maxvisible=mymax(maxvisible,s->readhist[j]); + } + if (masked_grtype(0)==E_GR_W) { + if (has_unicode&&unicode) { + maxvisible=mymax(maxvisible,s->writehist[j*2]); + maxvisible=mymax(maxvisible,s->writehist[j*2+1]); + } else + maxvisible=mymax(maxvisible,s->writehist[j]); + } + if (masked_grtype(0)==E_GR_RW) { + if (has_unicode&&unicode) { + maxvisible=mymax(maxvisible,s->readhist[j*2]+s->writehist[j*2]); + maxvisible=mymax(maxvisible,s->readhist[j*2+1]+s->writehist[j*2+1]); + } else + maxvisible=mymax(maxvisible,s->readhist[j]+s->writehist[j]); + } + } + + if (line>maxy-1-(noinlinehelp==0&&config.f.helptype==2?2:0)) // do not draw out of screen + goto donemax; + } + } + donemax: + line=saveline; + skip=saveskip; + } for (i=0;cs->sor&&i<diff_len;i++) { int th_prio_diff,th_first,th_have_filtered,th_first_id,th_last_id; struct xxxid_stats *ms=cs->sor[i],*s; char read_str[4],write_str[4]; - char iohist[HISTORY_POS*5]; + char graphstr[HISTORY_POS*5]; double read_val,write_val; char *pw_name,*cmdline; char *pwt,*cmdt; @@ -558,7 +711,8 @@ if (ms->pid!=ms->tid) continue; if (ms->threads) - arr_sort(ms->threads,iotop_sort_cb); + if (!(masked_grtype(0)!=E_GR_IO&&masked_grtype(0)!=E_GR_SW&&!config.f.hidegraph)) + arr_sort(ms->threads,iotop_sort_cb); // check if threads use the same prio as the main process // scan for hidden threads th_first=1; @@ -628,29 +782,68 @@ hrevpos=-1; if (!config.f.hidegraph) { - *iohist=0; + *graphstr=0; for (j=0;j<gr_width;j++) { + uint8_t v1=0,v2=0; + + switch (masked_grtype(0)) { + case E_GR_IO: + if (has_unicode&&unicode) { + v1=s->iohist[j*2]; + v2=s->iohist[j*2+1]; + } else + v1=s->iohist[j]; + break; + case E_GR_R: + if (has_unicode&&unicode) { + v1=value2scale(s->readhist[j*2],maxvisible); + v2=value2scale(s->readhist[j*2+1],maxvisible); + } else + v1=value2scale(s->readhist[j*2],maxvisible); + break; + case E_GR_W: + if (has_unicode&&unicode) { + v1=value2scale(s->writehist[j*2],maxvisible); + v2=value2scale(s->writehist[j*2+1],maxvisible); + } else + v1=value2scale(s->writehist[j*2],maxvisible); + break; + case E_GR_RW: + if (has_unicode&&unicode) { + v1=value2scale(s->readhist[j*2]+s->writehist[j*2],maxvisible); + v2=value2scale(s->readhist[j*2+1]+s->writehist[j*2+1],maxvisible); + } else + v1=value2scale(s->readhist[j*2]+s->writehist[j*2],maxvisible); + break; + case E_GR_SW: + if (has_unicode&&unicode) { + v1=s->sihist[j*2]; + v2=s->sihist[j*2+1]; + } else + v1=s->sihist[j]; + break; + } if (config.f.deadx) { // +1 avoids stepping on a char with one valid and one invalid value if (((has_unicode&&unicode)?j*2+1:j)<s->exited) - strcat(iohist,"x"); + strcat(graphstr,"x"); else { if (has_unicode&&unicode) - strcat(iohist,br_graph[s->iohist[j*2]][s->iohist[j*2+1]]); + strcat(graphstr,br_graph[v1][v2]); else - strcat(iohist,as_graph[s->iohist[j]]); + strcat(graphstr,as_graph[v1]); } } else { // stepping on a char with one valid and one invalid value is not a problem with background if (has_unicode&&unicode) - strcat(iohist,br_graph[s->iohist[j*2]][s->iohist[j*2+1]]); + strcat(graphstr,br_graph[v1][v2]); else - strcat(iohist,as_graph[s->iohist[j]]); + strcat(graphstr,as_graph[v1]); if (((has_unicode&&unicode)?j*2:j)<s->exited) - hrevpos=strlen(iohist); + hrevpos=strlen(graphstr); } } - strcat(iohist," "); + strcat(graphstr," "); } if (in_ionice&&ionice_pos==line) { @@ -676,17 +869,17 @@ printw("%7.2f %-3.3s ",read_val,read_str); if (!config.f.hidewrite) printw("%7.2f %-3.3s ",write_val,write_str); - if (!config.f.hideswapin) + if (!config.f.hideswapin&&has_tda) printw("%6.2f %% ",s->swapin_val); - if (!config.f.hideio) + if (!config.f.hideio&&has_tda) printw("%6.2f %% ",s->blkio_val); if (!config.f.hidegraph&&hrevpos>0) { attron(A_REVERSE); - printw("%*.*s",hrevpos,hrevpos,iohist); + printw("%*.*s",hrevpos,hrevpos,graphstr); attroff(A_REVERSE); - printw("%s",iohist+hrevpos); + printw("%s",graphstr+hrevpos); } else - printw("%s",!config.f.hidegraph?iohist:""); + printw("%s",!config.f.hidegraph?graphstr:""); if (!config.f.hidecmd) { const char *ss=(has_unicode&&unicode)?th_lines_u[0]:th_lines_a[0]; @@ -718,13 +911,13 @@ line++; lastline=line; - if (line>maxy-1) // do not draw out of screen + if (line>maxy-1-(noinlinehelp==0&&config.f.helptype==2?2:0)) // do not draw out of screen goto donedraw; } } donedraw: lastvisible=lastline; // last selectable screen line - for (line=lastline;line<=maxy-1;line++) // always draw empty lines + for (line=lastline;line<=maxy-1-(noinlinehelp==0&&config.f.helptype==2?2:0);line++) // always draw empty lines mvhline(line,0,' ',maxx); if (in_ionice) { @@ -868,9 +1061,150 @@ if (show) move(promptx,prompty); curs_set(show); - draw_vscroll(maxx-1,head1row?2:3,maxy-1,dispcount,saveskip); + draw_vscroll(maxx-1,head1row?2:3,maxy-1-(noinlinehelp==0&&config.f.helptype==2?2:0),dispcount,saveskip); + if (config.f.helptype==2) { + attron(A_REVERSE); + + mvhline(maxy-2,0,' ',maxx); + mvhline(maxy-1,0,' ',maxx); + + attron(A_BOLD); + mvprintw(maxy-2,0,"keys: "); + attroff(A_BOLD); + + attron(A_UNDERLINE); + attron(COLOR_PAIR(CYAN_PAIR)); + printw("^L"); + attroff(COLOR_PAIR(CYAN_PAIR)); + attroff(A_UNDERLINE); + printw(": redraw "); + + attron(A_UNDERLINE); + attron(COLOR_PAIR(CYAN_PAIR)); + printw("q"); + attroff(COLOR_PAIR(CYAN_PAIR)); + attroff(A_UNDERLINE); + printw(": quit "); + + attron(A_UNDERLINE); + attron(COLOR_PAIR(CYAN_PAIR)); + printw("i"); + attroff(COLOR_PAIR(CYAN_PAIR)); + attroff(A_UNDERLINE); + printw(": ionice "); + + attron(A_UNDERLINE); + attron(COLOR_PAIR(CYAN_PAIR)); + printw("f"); + attroff(COLOR_PAIR(CYAN_PAIR)); + attroff(A_UNDERLINE); + printw(": uid/pid "); + + attron(A_UNDERLINE); + attron(COLOR_PAIR(CYAN_PAIR)); + printw("o"); + attroff(COLOR_PAIR(CYAN_PAIR)); + attroff(A_UNDERLINE); + printw(": %s ",config.f.only?"all":"active"); + + attron(A_UNDERLINE); + attron(COLOR_PAIR(CYAN_PAIR)); + printw("p"); + attroff(COLOR_PAIR(CYAN_PAIR)); + attroff(A_UNDERLINE); + printw(": %s ",config.f.processes?"threads":"procs"); + + attron(A_UNDERLINE); + attron(COLOR_PAIR(CYAN_PAIR)); + printw("a"); + attroff(COLOR_PAIR(CYAN_PAIR)); + attroff(A_UNDERLINE); + printw(": %s ",config.f.accumulated?"bandwidth":"accum"); + + attron(A_UNDERLINE); + attron(COLOR_PAIR(CYAN_PAIR)); + printw("g"); + attroff(COLOR_PAIR(CYAN_PAIR)); + attroff(A_UNDERLINE); + printw(": graph src "); + + if (has_unicode) { + attron(A_UNDERLINE); + attron(COLOR_PAIR(CYAN_PAIR)); + printw("u"); + attroff(COLOR_PAIR(CYAN_PAIR)); + attroff(A_UNDERLINE); + printw(": %s ",unicode?"ASCII":"UTF"); + } + + attron(A_UNDERLINE); + attron(COLOR_PAIR(CYAN_PAIR)); + printw("h/?"); + attroff(COLOR_PAIR(CYAN_PAIR)); + attroff(A_UNDERLINE); + printw(": help"); + + attron(A_BOLD); + mvprintw(maxy-1,0,"sort: "); + attroff(A_BOLD); + + attron(A_UNDERLINE); + attron(COLOR_PAIR(CYAN_PAIR)); + printw("r"); + attroff(COLOR_PAIR(CYAN_PAIR)); + attroff(A_UNDERLINE); + printw(": %s ",config.f.sort_order==SORT_ASC?"desc":"asc"); + + attron(A_UNDERLINE); + attron(COLOR_PAIR(CYAN_PAIR)); + printw("left/right"); + attroff(COLOR_PAIR(CYAN_PAIR)); + attroff(A_UNDERLINE); + printw(": select "); + + attron(A_BOLD); + printw("column: "); + attroff(A_BOLD); + + attron(A_UNDERLINE); + attron(COLOR_PAIR(CYAN_PAIR)); + printw("1-9"); + attroff(COLOR_PAIR(CYAN_PAIR)); + attroff(A_UNDERLINE); + printw(": toggle "); + + attron(A_UNDERLINE); + attron(COLOR_PAIR(CYAN_PAIR)); + printw("0"); + attroff(COLOR_PAIR(CYAN_PAIR)); + attroff(A_UNDERLINE); + printw(": show all "); + + attron(A_UNDERLINE); + attron(COLOR_PAIR(CYAN_PAIR)); + printw("(pg)up/dn/home/end"); + attroff(COLOR_PAIR(CYAN_PAIR)); + attroff(A_UNDERLINE); + printw(": scroll "); + + attron(A_UNDERLINE); + attron(COLOR_PAIR(CYAN_PAIR)); + printw("x"); + attroff(COLOR_PAIR(CYAN_PAIR)); + attroff(A_UNDERLINE); + printw(": %s ",config.f.deadx?"bkg":"xxx"); + + attron(A_UNDERLINE); + attron(COLOR_PAIR(CYAN_PAIR)); + printw("s"); + attroff(COLOR_PAIR(CYAN_PAIR)); + attroff(A_UNDERLINE); + printw(": %s ",dontrefresh?"unfreeze":"freeze"); + + attroff(A_REVERSE); + } wnoutrefresh(stdscr); - if (showhelp) { + if (config.f.helptype==1) { int rhh,rhw; if (hw+2>=maxx) @@ -991,9 +1325,11 @@ if (ionice_pos!=-1) ionice_col=(ionice_col+1)%3; } - if (!in_ionice&&!in_filter) + if (!in_ionice&&!in_filter) { if (++config.f.sort_by==SORT_BY_MAX) - config.f.sort_by=SORT_BY_PID; + config.f.sort_by=SORT_BY_TID; + config.f.sort_by=masked_sort_by(1); + } break; case KEY_LEFT: if (in_ionice) { @@ -1003,9 +1339,11 @@ if (ionice_pos!=-1) ionice_col=(ionice_col+3-1)%3; } - if (!in_ionice&&!in_filter) + if (!in_ionice&&!in_filter) { if (--config.f.sort_by==-1) config.f.sort_by=SORT_BY_MAX-1; + config.f.sort_by=masked_sort_by(0); + } break; case KEY_UP: if (in_ionice) { @@ -1107,13 +1445,37 @@ break; case '?': case 'h': + config.f.helptype++; + if (config.f.helptype>2) + config.f.helptype=0; + if (noinlinehelp&&config.f.helptype==2) + config.f.helptype=0; + break; case 'H': - showhelp=!showhelp; + if (config.f.helptype) + config.f.helptype--; + else + config.f.helptype=2; + if (noinlinehelp&&config.f.helptype==2) + config.f.helptype=1; break; case 'c': case 'C': config.f.fullcmdline=!config.f.fullcmdline; break; + case 'g': // roll grtype forward + config.f.grtype++; + if (config.f.grtype>E_GR_MAX) + config.f.grtype=E_GR_MIN; + config.f.grtype=masked_grtype(1); + break; + case 'G': // roll grtype backward + if (config.f.grtype>E_GR_MIN) + config.f.grtype--; + else + config.f.grtype=E_GR_MAX; + config.f.grtype=masked_grtype(0); + break; case 'i': case 'I': if (!in_filter) { @@ -1154,8 +1516,8 @@ config.f.deadx=!config.f.deadx; break; case 27: // ESC - if (showhelp&&!in_ionice&&!in_filter) - showhelp=0; + if (config.f.helptype==1&&!in_ionice&&!in_filter) + config.f.helptype=0; // unlike help window these cannot happen at the same time if (in_ionice) in_ionice=0; @@ -1272,7 +1634,7 @@ case KEY_CTRL_T: write_task_delayacct(!read_task_delayacct()); break; - case KEY_CTRL_L: + case KEY_CTRL_L: // Ctrl-L redrawwin(stdscr); case KEY_REFRESH: case KEY_RESIZE: @@ -1280,6 +1642,8 @@ default: return -1; } + if (ch!=KEY_REFRESH&&ch!=KEY_RESIZE&&showtda) + showtda=0; return 0; } @@ -1309,6 +1673,7 @@ nodelay(stdscr,TRUE); start_color(); init_pair(RED_PAIR,COLOR_RED,COLOR_BLACK); + init_pair(CYAN_PAIR,COLOR_CYAN,COLOR_BLACK); for (p=thelp;p->descr;p++) { if (p->k1&&strlen(p->k1)>c1w) @@ -1366,10 +1731,14 @@ for (;;) { uint64_t now=monotime(); - if (!read_task_delayacct()) - showtda=1; - else + if (!read_task_delayacct()) { + if (has_tda) + showtda=1; + has_tda=0; + } else { showtda=0; + has_tda=1; + } if (bef+1000*params.delay<now&&!dontrefresh) { bef=now; if (ps) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iotop-c-1.20/src/views.c new/iotop-c-1.21/src/views.c --- old/iotop-c-1.20/src/views.c 2021-11-15 22:33:24.000000000 +0100 +++ new/iotop-c-1.21/src/views.c 2022-01-27 20:37:46.000000000 +0100 @@ -1,7 +1,7 @@ /* SPDX-License-Identifer: GPL-2.0-or-later Copyright (C) 2014 Vyacheslav Trushkin -Copyright (C) 2020,2021 Boian Bonev +Copyright (C) 2020-2022 Boian Bonev This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -111,6 +111,12 @@ memcpy(c->iohist+1,p->iohist,sizeof c->iohist-sizeof *c->iohist); c->iohist[0]=value2scale(c->blkio_val,100.0); + memcpy(c->sihist+1,p->sihist,sizeof c->sihist-sizeof *c->sihist); + c->sihist[0]=value2scale(c->swapin_val,100.0); + memcpy(c->readhist+1,p->readhist,sizeof c->readhist-sizeof *c->readhist); + c->readhist[0]=rv; + memcpy(c->writehist+1,p->writehist,sizeof c->writehist-sizeof *c->writehist); + c->writehist[0]=wv; snprintf(temp,sizeof temp,"%i",c->tid); maxpidlen=maxpidlen<(int)strlen(temp)?(int)strlen(temp):maxpidlen; @@ -144,6 +150,12 @@ // shift history one step memmove(p->iohist+1,p->iohist,sizeof p->iohist-sizeof *p->iohist); p->iohist[0]=0; + memmove(p->sihist+1,p->sihist,sizeof p->sihist-sizeof *p->sihist); + p->sihist[0]=0; + memmove(p->readhist+1,p->readhist,sizeof p->readhist-sizeof *p->readhist); + p->readhist[0]=0.0; + memmove(p->writehist+1,p->writehist,sizeof p->writehist-sizeof *p->writehist); + p->writehist[0]=0.0; if (arr_add(cs,p)) { // free the data in case add fails if (p->cmdline1) free(p->cmdline1); @@ -206,7 +218,6 @@ struct xxxid_stats **ppa=(struct xxxid_stats **)a; struct xxxid_stats **ppb=(struct xxxid_stats **)b; struct xxxid_stats *pa,*pb; - int type=config.f.sort_by; static int grlen=0; int res=0; @@ -218,18 +229,76 @@ pa=*ppa; pb=*ppb; - switch (type) { + switch (masked_sort_by(0)) { case SORT_BY_GRAPH: { + double da=0,db=0; int aa=0,ab=0; int i; - if (grlen==0) - grlen=HISTORY_CNT; - for (i=0;i<grlen;i++) { - aa+=pa->iohist[i]; - ab+=pb->iohist[i]; + switch (masked_grtype(0)) { + case E_GR_IO: + if (grlen==0) + grlen=HISTORY_CNT; + for (i=0;i<grlen;i++) { + aa+=pa->iohist[i]; + ab+=pb->iohist[i]; + } + res=aa-ab; + break; + case E_GR_R: + if (grlen==0) + grlen=HISTORY_CNT; + for (i=0;i<grlen;i++) { + da+=pa->readhist[i]; + db+=pb->readhist[i]; + } + if (da>db) + res=1; + else if (da<db) + res=-1; + else + res=0; + break; + case E_GR_W: + if (grlen==0) + grlen=HISTORY_CNT; + for (i=0;i<grlen;i++) { + da+=pa->writehist[i]; + db+=pb->writehist[i]; + } + if (da>db) + res=1; + else if (da<db) + res=-1; + else + res=0; + break; + case E_GR_RW: + if (grlen==0) + grlen=HISTORY_CNT; + for (i=0;i<grlen;i++) { + da+=pa->readhist[i]; + db+=pb->readhist[i]; + da+=pa->writehist[i]; + db+=pb->writehist[i]; + } + if (da>db) + res=1; + else if (da<db) + res=-1; + else + res=0; + break; + case E_GR_SW: + if (grlen==0) + grlen=HISTORY_CNT; + for (i=0;i<grlen;i++) { + aa+=pa->sihist[i]; + ab+=pb->sihist[i]; + } + res=aa-ab; + break; } - res=aa-ab; break; } case SORT_BY_PRIO: @@ -238,7 +307,7 @@ case SORT_BY_COMMAND: res=strcmp(config.f.fullcmdline?pa->cmdline2:pa->cmdline1,config.f.fullcmdline?pb->cmdline2:pb->cmdline1); break; - case SORT_BY_PID: + case SORT_BY_TID: res=pa->tid-pb->tid; break; case SORT_BY_USER: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iotop-c-1.20/src/vmstat.c new/iotop-c-1.21/src/vmstat.c --- old/iotop-c-1.20/src/vmstat.c 2021-11-15 22:33:24.000000000 +0100 +++ new/iotop-c-1.21/src/vmstat.c 2022-01-27 20:37:46.000000000 +0100 @@ -1,7 +1,7 @@ /* SPDX-License-Identifer: GPL-2.0-or-later Copyright (C) 2014 Vyacheslav Trushkin -Copyright (C) 2020,2021 Boian Bonev +Copyright (C) 2020-2022 Boian Bonev This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/iotop-c-1.20/src/xxxid_info.c new/iotop-c-1.21/src/xxxid_info.c --- old/iotop-c-1.20/src/xxxid_info.c 2021-11-15 22:33:24.000000000 +0100 +++ new/iotop-c-1.21/src/xxxid_info.c 2022-01-27 20:37:46.000000000 +0100 @@ -1,7 +1,7 @@ /* SPDX-License-Identifer: GPL-2.0-or-later Copyright (C) 2014 Vyacheslav Trushkin -Copyright (C) 2020,2021 Boian Bonev +Copyright (C) 2020-2022 Boian Bonev This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.