* [PATCH 0/3] irqtop,lsirq: Miscellaneous enhancements
@ 2025-02-27 4:49 Joe Jin
2025-02-27 4:49 ` [PATCH 1/3] irqtop: add batch mode support Joe Jin
` (3 more replies)
0 siblings, 4 replies; 17+ messages in thread
From: Joe Jin @ 2025-02-27 4:49 UTC (permalink / raw)
To: Karel Zak, Zhenwei Pi, Sami Kerola; +Cc: util-linux, Joe Jin
This patchset add below new options:
'-b|--batch' : Batch mode
'-n|--number': specifies the maximum number of iterations
'-i|--input' : Read data from file
Joe Jin (3):
irqtop: add batch mode support
irqtop: add max iteration support
lsirq,irqtop: add support for reading data from given file
bash-completion/irqtop | 15 ++++-
bash-completion/lsirq | 4 ++
sys-utils/irq-common.c | 19 +++----
sys-utils/irq-common.h | 3 +-
sys-utils/irqtop.1.adoc | 9 +++
sys-utils/irqtop.c | 122 +++++++++++++++++++++++++++++++---------
sys-utils/lsirq.1.adoc | 3 +
sys-utils/lsirq.c | 28 +++++++--
8 files changed, 160 insertions(+), 43 deletions(-)
--
2.43.5
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 1/3] irqtop: add batch mode support
2025-02-27 4:49 [PATCH 0/3] irqtop,lsirq: Miscellaneous enhancements Joe Jin
@ 2025-02-27 4:49 ` Joe Jin
2025-02-27 9:25 ` Karel Zak
2025-02-28 1:34 ` zhenwei pi
2025-02-27 4:49 ` [PATCH 2/3] irqtop: add max iteration support Joe Jin
` (2 subsequent siblings)
3 siblings, 2 replies; 17+ messages in thread
From: Joe Jin @ 2025-02-27 4:49 UTC (permalink / raw)
To: Karel Zak, Zhenwei Pi, Sami Kerola; +Cc: util-linux, Joe Jin
Add batch mode support, which could be useful for sending output to
other programs or to a file.
Signed-off-by: Joe Jin <joe.jin@oracle.com>
Cc: Zhenwei Pi <pizhenwei@bytedance.com>
Cc: Sami Kerola <kerolasa@iki.fi>
---
bash-completion/irqtop | 6 +++-
sys-utils/irqtop.1.adoc | 3 ++
sys-utils/irqtop.c | 79 ++++++++++++++++++++++++++++-------------
3 files changed, 63 insertions(+), 25 deletions(-)
diff --git a/bash-completion/irqtop b/bash-completion/irqtop
index b9e454d4c..215281ee8 100644
--- a/bash-completion/irqtop
+++ b/bash-completion/irqtop
@@ -5,6 +5,9 @@ _irqtop_module()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
case $prev in
+ '-b'|'--batch')
+ return 0
+ ;;
'-c'|'--cpu-stat')
COMPREPLY=( $(compgen -W "auto enable disable" -- $cur) )
return 0
@@ -40,7 +43,8 @@ _irqtop_module()
return 0
;;
esac
- OPTS=" --cpu-stat
+ OPTS=" --batch
+ --cpu-stat
--cpu-list
--delay
--sort
diff --git a/sys-utils/irqtop.1.adoc b/sys-utils/irqtop.1.adoc
index 443e23b84..e81f4fbb6 100644
--- a/sys-utils/irqtop.1.adoc
+++ b/sys-utils/irqtop.1.adoc
@@ -25,6 +25,9 @@ The default output is subject to change. So whenever possible, you should avoid
*-o*, *--output* _list_::
Specify which output columns to print. Use *--help* to get a list of all supported columns. The default list of columns may be extended if list is specified in the format _+list_.
+*-b*, *--batch*::
+Starts irqtop in batch mode, which could be useful for sending output to other programs or to a file.
+
*-c*, *--cpu-stat* _mode_::
Show per-cpu statistics by specified mode. Available modes are: *auto*, *enable*, *disable*. The default option *auto* detects the width of window, then shows the per-cpu statistics if the width of window is large enough to show a full line of statistics.
diff --git a/sys-utils/irqtop.c b/sys-utils/irqtop.c
index 8fbedb16a..00bf8fe50 100644
--- a/sys-utils/irqtop.c
+++ b/sys-utils/irqtop.c
@@ -83,10 +83,22 @@ struct irqtop_ctl {
cpu_set_t *cpuset;
enum irqtop_cpustat_mode cpustat_mode;
+ bool batch;
bool request_exit,
softirq;
};
+#define irqtop_batch_mode(ctl) ((ctl)->batch == true)
+#define irqtop_printf(ctl, fmt, args...) \
+ do { \
+ if (irqtop_batch_mode(ctl)) \
+ fprintf(stdout, fmt, ##args); \
+ else { \
+ wprintw(ctl->win, fmt, ##args); \
+ } \
+ }while(0)
+
+
/* user's input parser */
static void parse_input(struct irqtop_ctl *ctl, struct irq_output *out, char c)
{
@@ -128,16 +140,19 @@ static int update_screen(struct irqtop_ctl *ctl, struct irq_output *out)
scols_table_enable_nowrap(cpus, 1);
}
- /* print header */
- move(0, 0);
strtime_iso(&now, ISO_TIMESTAMP, timestr, sizeof(timestr));
- wprintw(ctl->win, _("irqtop | total: %ld delta: %ld | %s | %s\n\n"),
+ if (!irqtop_batch_mode(ctl))
+ move(0, 0);
+
+ /* print header */
+ irqtop_printf(ctl, _("irqtop | total: %ld delta: %ld | %s | %s\n\n"),
stat->total_irq, stat->delta_irq, ctl->hostname, timestr);
+
/* print cpus table or not by -c option */
if (cpus) {
scols_print_table_to_string(cpus, &data);
- wprintw(ctl->win, "%s\n\n", data);
+ irqtop_printf(ctl, "%s\n\n", data);
free(data);
}
@@ -149,13 +164,15 @@ static int update_screen(struct irqtop_ctl *ctl, struct irq_output *out)
if (p) {
/* print header in reverse mode */
*p = '\0';
- attron(A_REVERSE);
- wprintw(ctl->win, "%s\n", data);
- attroff(A_REVERSE);
+ if (!irqtop_batch_mode(ctl))
+ attron(A_REVERSE);
+ irqtop_printf(ctl, "%s\n", data);
+ if (!irqtop_batch_mode(ctl))
+ attroff(A_REVERSE);
data = p + 1;
}
- wprintw(ctl->win, "%s", data);
+ irqtop_printf(ctl, "%s\n", data);
free(data0);
/* clean up */
@@ -212,7 +229,8 @@ static int event_loop(struct irqtop_ctl *ctl, struct irq_output *out)
err(EXIT_FAILURE, _("epoll_ctl failed"));
retval |= update_screen(ctl, out);
- refresh();
+ if (!irqtop_batch_mode(ctl))
+ refresh();
while (!ctl->request_exit) {
const ssize_t nr_events = epoll_wait(efd, events, MAX_EVENTS, -1);
@@ -227,10 +245,12 @@ static int event_loop(struct irqtop_ctl *ctl, struct irq_output *out)
continue;
}
if (siginfo.ssi_signo == SIGWINCH) {
- get_terminal_dimension(&ctl->cols, &ctl->rows);
+ if (!irqtop_batch_mode(ctl)) {
+ get_terminal_dimension(&ctl->cols, &ctl->rows);
#if HAVE_RESIZETERM
- resizeterm(ctl->rows, ctl->cols);
+ resizeterm(ctl->rows, ctl->cols);
#endif
+ }
}
else {
ctl->request_exit = 1;
@@ -245,7 +265,8 @@ static int event_loop(struct irqtop_ctl *ctl, struct irq_output *out)
} else
abort();
retval |= update_screen(ctl, out);
- refresh();
+ if (!irqtop_batch_mode(ctl))
+ refresh();
}
}
return retval;
@@ -260,6 +281,7 @@ static void __attribute__((__noreturn__)) usage(void)
puts(_("Interactive utility to display kernel interrupt information."));
fputs(USAGE_OPTIONS, stdout);
+ fputs(_(" -b, --batch batch mode\n"), stdout);
fputs(_(" -c, --cpu-stat <mode> show per-cpu stat (auto, enable, disable)\n"), stdout);
fputs(_(" -C, --cpu-list <list> specify cpus in list format\n"), stdout);
fputs(_(" -d, --delay <secs> delay updates\n"), stdout);
@@ -291,6 +313,7 @@ static void parse_args( struct irqtop_ctl *ctl,
{
const char *outarg = NULL;
static const struct option longopts[] = {
+ {"batch", no_argument, NULL, 'b'},
{"cpu-stat", required_argument, NULL, 'c'},
{"cpu-list", required_argument, NULL, 'C'},
{"delay", required_argument, NULL, 'd'},
@@ -304,8 +327,11 @@ static void parse_args( struct irqtop_ctl *ctl,
};
int o;
- while ((o = getopt_long(argc, argv, "c:C:d:o:s:St:hV", longopts, NULL)) != -1) {
+ while ((o = getopt_long(argc, argv, "bc:C:d:o:s:St:hV", longopts, NULL)) != -1) {
switch (o) {
+ case 'b':
+ ctl->batch = true;
+ break;
case 'c':
if (!strcmp(optarg, "auto"))
ctl->cpustat_mode = IRQTOP_CPUSTAT_AUTO;
@@ -394,16 +420,18 @@ int main(int argc, char **argv)
parse_args(&ctl, &out, argc, argv);
- is_tty = isatty(STDIN_FILENO);
- if (is_tty && tcgetattr(STDIN_FILENO, &saved_tty) == -1)
- fputs(_("terminal setting retrieval"), stdout);
+ if (ctl.batch == false) {
+ is_tty = isatty(STDIN_FILENO);
+ if (is_tty && tcgetattr(STDIN_FILENO, &saved_tty) == -1)
+ fputs(_("terminal setting retrieval"), stdout);
- ctl.win = initscr();
- get_terminal_dimension(&ctl.cols, &ctl.rows);
+ ctl.win = initscr();
+ get_terminal_dimension(&ctl.cols, &ctl.rows);
#if HAVE_RESIZETERM
- resizeterm(ctl.rows, ctl.cols);
+ resizeterm(ctl.rows, ctl.cols);
#endif
- curs_set(0);
+ curs_set(0);
+ }
ctl.hostname = xgethostname();
event_loop(&ctl, &out);
@@ -412,10 +440,13 @@ int main(int argc, char **argv)
free(ctl.hostname);
cpuset_free(ctl.cpuset);
- if (is_tty)
- tcsetattr(STDIN_FILENO, TCSAFLUSH, &saved_tty);
- delwin(ctl.win);
- endwin();
+ if (ctl.batch == false) {
+ if (is_tty)
+ tcsetattr(STDIN_FILENO, TCSAFLUSH, &saved_tty);
+
+ delwin(ctl.win);
+ endwin();
+ }
return EXIT_SUCCESS;
}
--
2.43.5
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 2/3] irqtop: add max iteration support
2025-02-27 4:49 [PATCH 0/3] irqtop,lsirq: Miscellaneous enhancements Joe Jin
2025-02-27 4:49 ` [PATCH 1/3] irqtop: add batch mode support Joe Jin
@ 2025-02-27 4:49 ` Joe Jin
2025-02-27 9:28 ` Karel Zak
2025-02-27 4:49 ` [PATCH 3/3] lsirq,irqtop: add support for reading data from given file Joe Jin
2025-02-27 7:36 ` [PATCH 0/3] irqtop,lsirq: Miscellaneous enhancements Sami Kerola
3 siblings, 1 reply; 17+ messages in thread
From: Joe Jin @ 2025-02-27 4:49 UTC (permalink / raw)
To: Karel Zak, Zhenwei Pi, Sami Kerola; +Cc: util-linux, Joe Jin
Add support for setting the number of iterations. This is useful in
non-interactive mode.
Signed-off-by: Joe Jin <joe.jin@oracle.com>
Cc: Zhenwei Pi <pizhenwei@bytedance.com>
Cc: Sami Kerola <kerolasa@iki.fi>
---
bash-completion/irqtop | 5 +++++
sys-utils/irqtop.1.adoc | 3 +++
sys-utils/irqtop.c | 19 +++++++++++++++++--
3 files changed, 25 insertions(+), 2 deletions(-)
diff --git a/bash-completion/irqtop b/bash-completion/irqtop
index 215281ee8..47b7b0af6 100644
--- a/bash-completion/irqtop
+++ b/bash-completion/irqtop
@@ -22,6 +22,10 @@ _irqtop_module()
COMPREPLY=( $(compgen -W "secs" -- $cur) )
return 0
;;
+ '-n'|'--number')
+ COMPREPLY=( $(compgen -W "the max iterations" -- $cur) )
+ return 0
+ ;;
'-s'|'--sort')
COMPREPLY=( $(compgen -W "irq total delta name" -- $cur) )
return 0
@@ -47,6 +51,7 @@ _irqtop_module()
--cpu-stat
--cpu-list
--delay
+ --number
--sort
--output
--softirq
diff --git a/sys-utils/irqtop.1.adoc b/sys-utils/irqtop.1.adoc
index e81f4fbb6..75cfe2e41 100644
--- a/sys-utils/irqtop.1.adoc
+++ b/sys-utils/irqtop.1.adoc
@@ -37,6 +37,9 @@ Specify cpus in list format to show.
*-d*, *--delay* _seconds_::
Update interrupt output every _seconds_ intervals.
+*-n*, *--number* _number_::
+Specifies the maximum _number_ of iterations before quitting.
+
*-s*, *--sort* _column_::
Specify sort criteria by column name. See *--help* output to get column names. The sort criteria may be changes in interactive mode.
diff --git a/sys-utils/irqtop.c b/sys-utils/irqtop.c
index 00bf8fe50..ba5680671 100644
--- a/sys-utils/irqtop.c
+++ b/sys-utils/irqtop.c
@@ -83,6 +83,7 @@ struct irqtop_ctl {
cpu_set_t *cpuset;
enum irqtop_cpustat_mode cpustat_mode;
+ int64_t number;
bool batch;
bool request_exit,
softirq;
@@ -180,6 +181,12 @@ static int update_screen(struct irqtop_ctl *ctl, struct irq_output *out)
if (ctl->prev_stat)
free_irqstat(ctl->prev_stat);
ctl->prev_stat = stat;
+
+ if (ctl->number > 0) {
+ ctl->number--;
+ if (ctl->number == 0)
+ ctl->request_exit = 1;
+ }
return 0;
}
@@ -285,6 +292,7 @@ static void __attribute__((__noreturn__)) usage(void)
fputs(_(" -c, --cpu-stat <mode> show per-cpu stat (auto, enable, disable)\n"), stdout);
fputs(_(" -C, --cpu-list <list> specify cpus in list format\n"), stdout);
fputs(_(" -d, --delay <secs> delay updates\n"), stdout);
+ fputs(_(" -n, --number <number> the maximum number of iterations\n"), stdout);
fputs(_(" -o, --output <list> define which output columns to use\n"), stdout);
fputs(_(" -s, --sort <column> specify sort column\n"), stdout);
fputs(_(" -S, --softirq show softirqs instead of interrupts\n"), stdout);
@@ -317,6 +325,7 @@ static void parse_args( struct irqtop_ctl *ctl,
{"cpu-stat", required_argument, NULL, 'c'},
{"cpu-list", required_argument, NULL, 'C'},
{"delay", required_argument, NULL, 'd'},
+ {"number", required_argument, NULL, 'n'},
{"sort", required_argument, NULL, 's'},
{"output", required_argument, NULL, 'o'},
{"softirq", no_argument, NULL, 'S'},
@@ -327,7 +336,7 @@ static void parse_args( struct irqtop_ctl *ctl,
};
int o;
- while ((o = getopt_long(argc, argv, "bc:C:d:o:s:St:hV", longopts, NULL)) != -1) {
+ while ((o = getopt_long(argc, argv, "bc:C:d:n:o:s:St:hV", longopts, NULL)) != -1) {
switch (o) {
case 'b':
ctl->batch = true;
@@ -367,6 +376,11 @@ static void parse_args( struct irqtop_ctl *ctl,
ctl->timer.it_value = ctl->timer.it_interval;
}
break;
+ case 'n':
+ ctl->number = str2num_or_err(optarg, 10,
+ _("failed to parse number argument"),
+ 0, INT_MAX);
+ break;
case 's':
set_sort_func_by_name(out, optarg);
break;
@@ -413,7 +427,8 @@ int main(int argc, char **argv)
};
struct irqtop_ctl ctl = {
.timer.it_interval = {3, 0},
- .timer.it_value = {3, 0}
+ .timer.it_value = {3, 0},
+ .number = -1
};
setlocale(LC_ALL, "");
--
2.43.5
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 3/3] lsirq,irqtop: add support for reading data from given file
2025-02-27 4:49 [PATCH 0/3] irqtop,lsirq: Miscellaneous enhancements Joe Jin
2025-02-27 4:49 ` [PATCH 1/3] irqtop: add batch mode support Joe Jin
2025-02-27 4:49 ` [PATCH 2/3] irqtop: add max iteration support Joe Jin
@ 2025-02-27 4:49 ` Joe Jin
2025-02-27 9:30 ` Karel Zak
2025-02-28 1:41 ` zhenwei pi
2025-02-27 7:36 ` [PATCH 0/3] irqtop,lsirq: Miscellaneous enhancements Sami Kerola
3 siblings, 2 replies; 17+ messages in thread
From: Joe Jin @ 2025-02-27 4:49 UTC (permalink / raw)
To: Karel Zak, Zhenwei Pi, Sami Kerola; +Cc: util-linux, Joe Jin
This is helpful for analyzng data saved from other system.
Signed-off-by: Joe Jin <joe.jin@oracle.com>
Cc: Zhenwei Pi <pizhenwei@bytedance.com>
Cc: Sami Kerola <kerolasa@iki.fi>
---
bash-completion/irqtop | 4 ++++
bash-completion/lsirq | 4 ++++
sys-utils/irq-common.c | 19 +++++++++----------
sys-utils/irq-common.h | 3 ++-
sys-utils/irqtop.1.adoc | 3 +++
sys-utils/irqtop.c | 28 +++++++++++++++++++++++++---
sys-utils/lsirq.1.adoc | 3 +++
sys-utils/lsirq.c | 28 ++++++++++++++++++++++++----
8 files changed, 74 insertions(+), 18 deletions(-)
diff --git a/bash-completion/irqtop b/bash-completion/irqtop
index 47b7b0af6..3bea5fc0e 100644
--- a/bash-completion/irqtop
+++ b/bash-completion/irqtop
@@ -15,6 +15,9 @@ _irqtop_module()
'-C'|'--cpu-list')
return 0
;;
+ '-i'|'--input')
+ COMPREPLY=( $(compgen -W "input file" -- $cur) )
+ ;;
'-t'|'--threshold')
return 0
;;
@@ -51,6 +54,7 @@ _irqtop_module()
--cpu-stat
--cpu-list
--delay
+ --input
--number
--sort
--output
diff --git a/bash-completion/lsirq b/bash-completion/lsirq
index 4c3c9f04f..b913eecd0 100644
--- a/bash-completion/lsirq
+++ b/bash-completion/lsirq
@@ -5,6 +5,9 @@ _lsirq_module()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
case $prev in
+ '-i'|'--input')
+ COMPREPLY=( $(compgen -W "input file" -- $cur) )
+ ;;
'-o'|'--output')
local prefix realcur OUTPUT
realcur="${cur##*,}"
@@ -35,6 +38,7 @@ _lsirq_module()
OPTS=" --json
--pairs
--noheadings
+ --input
--output
--softirq
--sort
diff --git a/sys-utils/irq-common.c b/sys-utils/irq-common.c
index f069d8a63..560dd4b82 100644
--- a/sys-utils/irq-common.c
+++ b/sys-utils/irq-common.c
@@ -233,7 +233,8 @@ static bool cpu_in_list(int cpu, size_t setsize, cpu_set_t *cpuset)
/*
* irqinfo - parse the system's interrupts
*/
-static struct irq_stat *get_irqinfo(int softirq, size_t setsize, cpu_set_t *cpuset)
+static struct irq_stat *get_irqinfo(const char *input_file, int softirq,
+ size_t setsize, cpu_set_t *cpuset)
{
FILE *irqfile;
char *line = NULL, *tmp;
@@ -247,18 +248,15 @@ static struct irq_stat *get_irqinfo(int softirq, size_t setsize, cpu_set_t *cpus
stat->irq_info = xmalloc(sizeof(*stat->irq_info) * IRQ_INFO_LEN);
stat->nr_irq_info = IRQ_INFO_LEN;
- if (softirq)
- irqfile = fopen(_PATH_PROC_SOFTIRQS, "r");
- else
- irqfile = fopen(_PATH_PROC_INTERRUPTS, "r");
+ irqfile = fopen(input_file, "r");
if (!irqfile) {
- warn(_("cannot open %s"), _PATH_PROC_INTERRUPTS);
+ warn(_("cannot open %s"), input_file);
goto free_stat;
}
/* read header firstly */
if (getline(&line, &len, irqfile) < 0) {
- warn(_("cannot read %s"), _PATH_PROC_INTERRUPTS);
+ warn(_("cannot read %s"), input_file);
goto close_file;
}
@@ -270,7 +268,7 @@ static struct irq_stat *get_irqinfo(int softirq, size_t setsize, cpu_set_t *cpus
stat->cpus = xcalloc(stat->nr_active_cpu, sizeof(struct irq_cpu));
- /* parse each line of _PATH_PROC_INTERRUPTS */
+ /* parse each line of input file */
while (getline(&line, &len, irqfile) >= 0) {
unsigned long count;
size_t index;
@@ -527,7 +525,8 @@ struct libscols_table *get_scols_cpus_table(struct irq_output *out,
return NULL;
}
-struct libscols_table *get_scols_table(struct irq_output *out,
+struct libscols_table *get_scols_table(const char *input_file,
+ struct irq_output *out,
struct irq_stat *prev,
struct irq_stat **xstat,
int softirq,
@@ -542,7 +541,7 @@ struct libscols_table *get_scols_table(struct irq_output *out,
size_t i;
/* the stats */
- stat = get_irqinfo(softirq, setsize, cpuset);
+ stat = get_irqinfo(input_file, softirq, setsize, cpuset);
if (!stat)
return NULL;
diff --git a/sys-utils/irq-common.h b/sys-utils/irq-common.h
index 02b72d752..b9cf72d2a 100644
--- a/sys-utils/irq-common.h
+++ b/sys-utils/irq-common.h
@@ -73,7 +73,8 @@ void irq_print_columns(FILE *f, int nodelta);
void set_sort_func_by_name(struct irq_output *out, const char *name);
void set_sort_func_by_key(struct irq_output *out, const char c);
-struct libscols_table *get_scols_table(struct irq_output *out,
+struct libscols_table *get_scols_table(const char *input_file,
+ struct irq_output *out,
struct irq_stat *prev,
struct irq_stat **xstat,
int softirq,
diff --git a/sys-utils/irqtop.1.adoc b/sys-utils/irqtop.1.adoc
index 75cfe2e41..715008d07 100644
--- a/sys-utils/irqtop.1.adoc
+++ b/sys-utils/irqtop.1.adoc
@@ -37,6 +37,9 @@ Specify cpus in list format to show.
*-d*, *--delay* _seconds_::
Update interrupt output every _seconds_ intervals.
+*-i*, *--input* _file_::
+Read data from _file_ (Which was created by other tools, e.g. sosreport).
+
*-n*, *--number* _number_::
Specifies the maximum _number_ of iterations before quitting.
diff --git a/sys-utils/irqtop.c b/sys-utils/irqtop.c
index ba5680671..4cf1dc79a 100644
--- a/sys-utils/irqtop.c
+++ b/sys-utils/irqtop.c
@@ -87,6 +87,8 @@ struct irqtop_ctl {
bool batch;
bool request_exit,
softirq;
+
+ char *input;
};
#define irqtop_batch_mode(ctl) ((ctl)->batch == true)
@@ -122,8 +124,9 @@ static int update_screen(struct irqtop_ctl *ctl, struct irq_output *out)
char timestr[64], *data, *data0, *p;
/* make irqs table */
- table = get_scols_table(out, ctl->prev_stat, &stat, ctl->softirq,
- ctl->threshold, ctl->setsize, ctl->cpuset);
+ table = get_scols_table(ctl->input, out, ctl->prev_stat, &stat,
+ ctl->softirq, ctl->threshold, ctl->setsize,
+ ctl->cpuset);
if (!table) {
ctl->request_exit = 1;
return 1;
@@ -292,6 +295,7 @@ static void __attribute__((__noreturn__)) usage(void)
fputs(_(" -c, --cpu-stat <mode> show per-cpu stat (auto, enable, disable)\n"), stdout);
fputs(_(" -C, --cpu-list <list> specify cpus in list format\n"), stdout);
fputs(_(" -d, --delay <secs> delay updates\n"), stdout);
+ fputs(_(" -i, --input <file> read data from file\n"), stdout);
fputs(_(" -n, --number <number> the maximum number of iterations\n"), stdout);
fputs(_(" -o, --output <list> define which output columns to use\n"), stdout);
fputs(_(" -s, --sort <column> specify sort column\n"), stdout);
@@ -325,6 +329,7 @@ static void parse_args( struct irqtop_ctl *ctl,
{"cpu-stat", required_argument, NULL, 'c'},
{"cpu-list", required_argument, NULL, 'C'},
{"delay", required_argument, NULL, 'd'},
+ {"input", required_argument, NULL, 'i'},
{"number", required_argument, NULL, 'n'},
{"sort", required_argument, NULL, 's'},
{"output", required_argument, NULL, 'o'},
@@ -336,7 +341,7 @@ static void parse_args( struct irqtop_ctl *ctl,
};
int o;
- while ((o = getopt_long(argc, argv, "bc:C:d:n:o:s:St:hV", longopts, NULL)) != -1) {
+ while ((o = getopt_long(argc, argv, "bc:C:d:i:n:o:s:St:hV", longopts, NULL)) != -1) {
switch (o) {
case 'b':
ctl->batch = true;
@@ -376,6 +381,13 @@ static void parse_args( struct irqtop_ctl *ctl,
ctl->timer.it_value = ctl->timer.it_interval;
}
break;
+ case 'i':
+ ctl->input = strdup(optarg);
+ if (!ctl->input)
+ err_oom();
+ ctl->number = 1;
+ ctl->batch = true;
+ break;
case 'n':
ctl->number = str2num_or_err(optarg, 10,
_("failed to parse number argument"),
@@ -402,6 +414,15 @@ static void parse_args( struct irqtop_ctl *ctl,
}
}
+ if (ctl->input == NULL) {
+ if (ctl->softirq == 1)
+ ctl->input = strdup(_PATH_PROC_SOFTIRQS);
+ else
+ ctl->input = strdup(_PATH_PROC_INTERRUPTS);
+ if (!ctl->input)
+ err_oom();
+ }
+
/* default */
if (!out->ncolumns) {
out->columns[out->ncolumns++] = COL_IRQ;
@@ -453,6 +474,7 @@ int main(int argc, char **argv)
free_irqstat(ctl.prev_stat);
free(ctl.hostname);
+ free(ctl.input);
cpuset_free(ctl.cpuset);
if (ctl.batch == false) {
diff --git a/sys-utils/lsirq.1.adoc b/sys-utils/lsirq.1.adoc
index 02aea16b3..dd265710c 100644
--- a/sys-utils/lsirq.1.adoc
+++ b/sys-utils/lsirq.1.adoc
@@ -25,6 +25,9 @@ The default output is subject to change. So whenever possible, you should avoid
*-n*, *--noheadings*::
Don't print headings.
+*-i*, *--input* _file_::
+Read data from _file_ (Which was created by other tools, e.g. sosreport).
+
*-o*, *--output* _list_::
Specify which output columns to print. Use *--help* to get a list of all supported columns. The default list of columns may be extended if list is specified in the format _+list_.
diff --git a/sys-utils/lsirq.c b/sys-utils/lsirq.c
index e31addaf5..45d542919 100644
--- a/sys-utils/lsirq.c
+++ b/sys-utils/lsirq.c
@@ -29,16 +29,17 @@
#include "optutils.h"
#include "strutils.h"
#include "xalloc.h"
+#include "pathnames.h"
#include "irq-common.h"
-static int print_irq_data(struct irq_output *out,
+static int print_irq_data(const char *input_file, struct irq_output *out,
int softirq, unsigned long threshold,
size_t setsize, cpu_set_t *cpuset)
{
struct libscols_table *table;
- table = get_scols_table(out, NULL, NULL, softirq, threshold, setsize, cpuset);
+ table = get_scols_table(input_file, out, NULL, NULL, softirq, threshold, setsize, cpuset);
if (!table)
return -1;
@@ -58,6 +59,7 @@ static void __attribute__((__noreturn__)) usage(void)
fputs(USAGE_OPTIONS, stdout);
fputs(_(" -J, --json use JSON output format\n"), stdout);
fputs(_(" -P, --pairs use key=\"value\" output format\n"), stdout);
+ fputs(_(" -i, --input read data from input file\n"), stdout);
fputs(_(" -n, --noheadings don't print headings\n"), stdout);
fputs(_(" -o, --output <list> define which output columns to use\n"), stdout);
fputs(_(" -s, --sort <column> specify sort column\n"), stdout);
@@ -82,6 +84,7 @@ int main(int argc, char **argv)
static const struct option longopts[] = {
{"sort", required_argument, NULL, 's'},
{"noheadings", no_argument, NULL, 'n'},
+ {"input", required_argument, NULL, 'i'},
{"output", required_argument, NULL, 'o'},
{"threshold", required_argument, NULL, 't'},
{"cpu-list", required_argument, NULL, 'C'},
@@ -103,10 +106,11 @@ int main(int argc, char **argv)
cpu_set_t *cpuset = NULL;
size_t setsize = 0;
int softirq = 0;
+ char *input = NULL;
setlocale(LC_ALL, "");
- while ((c = getopt_long(argc, argv, "no:s:t:C:ShJPV", longopts, NULL)) != -1) {
+ while ((c = getopt_long(argc, argv, "i:no:s:t:C:ShJPV", longopts, NULL)) != -1) {
err_exclusive_options(c, longopts, excl, excl_st);
switch (c) {
@@ -116,6 +120,11 @@ int main(int argc, char **argv)
case 'P':
out.pairs = 1;
break;
+ case 'i':
+ input = strdup(optarg);
+ if (!input)
+ err_oom();
+ break;
case 'n':
out.no_headings = 1;
break;
@@ -157,6 +166,15 @@ int main(int argc, char **argv)
}
}
+ if (input == NULL) {
+ if (softirq == 1)
+ input = strdup(_PATH_PROC_SOFTIRQS);
+ else
+ input = strdup(_PATH_PROC_INTERRUPTS);
+ if (!input)
+ err_oom();
+ }
+
/* default */
if (!out.ncolumns) {
out.columns[out.ncolumns++] = COL_IRQ;
@@ -171,8 +189,10 @@ int main(int argc, char **argv)
irq_column_name_to_id) < 0)
exit(EXIT_FAILURE);
- if (print_irq_data(&out, softirq, threshold, setsize, cpuset) < 0)
+ if (print_irq_data(input, &out, softirq, threshold, setsize, cpuset) < 0)
return EXIT_FAILURE;
+ free(input);
+
return EXIT_SUCCESS;
}
--
2.43.5
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH 0/3] irqtop,lsirq: Miscellaneous enhancements
2025-02-27 4:49 [PATCH 0/3] irqtop,lsirq: Miscellaneous enhancements Joe Jin
` (2 preceding siblings ...)
2025-02-27 4:49 ` [PATCH 3/3] lsirq,irqtop: add support for reading data from given file Joe Jin
@ 2025-02-27 7:36 ` Sami Kerola
2025-02-27 19:49 ` Joe Jin
3 siblings, 1 reply; 17+ messages in thread
From: Sami Kerola @ 2025-02-27 7:36 UTC (permalink / raw)
To: Joe Jin; +Cc: Karel Zak, Zhenwei Pi, util-linux
On Thu, 27 Feb 2025 at 04:49, Joe Jin <joe.jin@oracle.com> wrote:
> This patchset add below new options:
> '-b|--batch' : Batch mode
> '-n|--number': specifies the maximum number of iterations
> '-i|--input' : Read data from file
Thanks for contribution,
If batch mode is added the tool should also gain --json option for
structured output.
--
Sami Kerola
https://kerolasa.iki.fi/
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 1/3] irqtop: add batch mode support
2025-02-27 4:49 ` [PATCH 1/3] irqtop: add batch mode support Joe Jin
@ 2025-02-27 9:25 ` Karel Zak
2025-02-27 18:30 ` Joe Jin
2025-02-28 1:34 ` zhenwei pi
1 sibling, 1 reply; 17+ messages in thread
From: Karel Zak @ 2025-02-27 9:25 UTC (permalink / raw)
To: Joe Jin; +Cc: Zhenwei Pi, Sami Kerola, util-linux
On Wed, Feb 26, 2025 at 08:49:14PM GMT, Joe Jin wrote:
> +#define irqtop_batch_mode(ctl) ((ctl)->batch == true)
Do we need this macro? I think use
if (ctl->batch)
...
or
if (!ctl->batch)
...
in the code is good enough.
> +#define irqtop_printf(ctl, fmt, args...) \
> + do { \
> + if (irqtop_batch_mode(ctl)) \
> + fprintf(stdout, fmt, ##args); \
> + else { \
> + wprintw(ctl->win, fmt, ##args); \
> + } \
> + }while(0)
It would be more robust to use an inline function with vw_printw() and
vfprintf() rather than a macro with a variadic number of arguments, or
use __VA_ARGS__ in the macro.
Karel
--
Karel Zak <kzak@redhat.com>
http://karelzak.blogspot.com
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 2/3] irqtop: add max iteration support
2025-02-27 4:49 ` [PATCH 2/3] irqtop: add max iteration support Joe Jin
@ 2025-02-27 9:28 ` Karel Zak
2025-02-27 18:32 ` Joe Jin
0 siblings, 1 reply; 17+ messages in thread
From: Karel Zak @ 2025-02-27 9:28 UTC (permalink / raw)
To: Joe Jin; +Cc: Zhenwei Pi, Sami Kerola, util-linux
On Wed, Feb 26, 2025 at 08:49:15PM GMT, Joe Jin wrote:
> enum irqtop_cpustat_mode cpustat_mode;
> + int64_t number;
Can we find a better name for the variable and the option?
--nloops
--repeat
or so ;-)
Karel
--
Karel Zak <kzak@redhat.com>
http://karelzak.blogspot.com
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 3/3] lsirq,irqtop: add support for reading data from given file
2025-02-27 4:49 ` [PATCH 3/3] lsirq,irqtop: add support for reading data from given file Joe Jin
@ 2025-02-27 9:30 ` Karel Zak
2025-02-27 18:33 ` Joe Jin
2025-02-28 1:41 ` zhenwei pi
1 sibling, 1 reply; 17+ messages in thread
From: Karel Zak @ 2025-02-27 9:30 UTC (permalink / raw)
To: Joe Jin; +Cc: Zhenwei Pi, Sami Kerola, util-linux
On Wed, Feb 26, 2025 at 08:49:16PM GMT, Joe Jin wrote:
> + if (ctl->input == NULL) {
> + if (ctl->softirq == 1)
> + ctl->input = strdup(_PATH_PROC_SOFTIRQS);
> + else
> + ctl->input = strdup(_PATH_PROC_INTERRUPTS);
> + if (!ctl->input)
> + err_oom();
> + }
Please, use xstrdup(), than you do not need to care about result and
use err_oom();
Karel
--
Karel Zak <kzak@redhat.com>
http://karelzak.blogspot.com
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 1/3] irqtop: add batch mode support
2025-02-27 9:25 ` Karel Zak
@ 2025-02-27 18:30 ` Joe Jin
0 siblings, 0 replies; 17+ messages in thread
From: Joe Jin @ 2025-02-27 18:30 UTC (permalink / raw)
To: Karel Zak; +Cc: Zhenwei Pi, Sami Kerola, util-linux
On 2/27/25 01:25, Karel Zak wrote:
> On Wed, Feb 26, 2025 at 08:49:14PM GMT, Joe Jin wrote:
>> +#define irqtop_batch_mode(ctl) ((ctl)->batch == true)
> Do we need this macro? I think use
>
> if (ctl->batch)
> ...
> or
>
> if (!ctl->batch)
> ...
>
> in the code is good enough.
I'll remove the macro.
>
>> +#define irqtop_printf(ctl, fmt, args...) \
>> + do { \
>> + if (irqtop_batch_mode(ctl)) \
>> + fprintf(stdout, fmt, ##args); \
>> + else { \
>> + wprintw(ctl->win, fmt, ##args); \
>> + } \
>> + }while(0)
> It would be more robust to use an inline function with vw_printw() and
> vfprintf() rather than a macro with a variadic number of arguments, or
> use __VA_ARGS__ in the macro.
Thanks for your suggestions, I'll create an inline function.
Thanks,
Joe
>
> Karel
>
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 2/3] irqtop: add max iteration support
2025-02-27 9:28 ` Karel Zak
@ 2025-02-27 18:32 ` Joe Jin
2025-02-28 8:19 ` Karel Zak
0 siblings, 1 reply; 17+ messages in thread
From: Joe Jin @ 2025-02-27 18:32 UTC (permalink / raw)
To: Karel Zak; +Cc: Zhenwei Pi, Sami Kerola, util-linux
On 2/27/25 01:28, Karel Zak wrote:
> On Wed, Feb 26, 2025 at 08:49:15PM GMT, Joe Jin wrote:
>> enum irqtop_cpustat_mode cpustat_mode;
>> + int64_t number;
> Can we find a better name for the variable and the option?
>
> --nloops
> --repeat
How about of "--iter"?
Thanks,
Joe
>
> or so ;-)
>
> Karel
>
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 3/3] lsirq,irqtop: add support for reading data from given file
2025-02-27 9:30 ` Karel Zak
@ 2025-02-27 18:33 ` Joe Jin
0 siblings, 0 replies; 17+ messages in thread
From: Joe Jin @ 2025-02-27 18:33 UTC (permalink / raw)
To: Karel Zak; +Cc: Zhenwei Pi, Sami Kerola, util-linux
On 2/27/25 01:30, Karel Zak wrote:
> On Wed, Feb 26, 2025 at 08:49:16PM GMT, Joe Jin wrote:
>> + if (ctl->input == NULL) {
>> + if (ctl->softirq == 1)
>> + ctl->input = strdup(_PATH_PROC_SOFTIRQS);
>> + else
>> + ctl->input = strdup(_PATH_PROC_INTERRUPTS);
>> + if (!ctl->input)
>> + err_oom();
>> + }
> Please, use xstrdup(), than you do not need to care about result and
> use err_oom();
Will make change for this, thanks for your suggestions.
Thanks,
Joe
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 0/3] irqtop,lsirq: Miscellaneous enhancements
2025-02-27 7:36 ` [PATCH 0/3] irqtop,lsirq: Miscellaneous enhancements Sami Kerola
@ 2025-02-27 19:49 ` Joe Jin
0 siblings, 0 replies; 17+ messages in thread
From: Joe Jin @ 2025-02-27 19:49 UTC (permalink / raw)
To: kerolasa; +Cc: Karel Zak, Zhenwei Pi, util-linux
On 2/26/25 23:36, Sami Kerola wrote:
> On Thu, 27 Feb 2025 at 04:49, Joe Jin <joe.jin@oracle.com> wrote:
>> This patchset add below new options:
>> '-b|--batch' : Batch mode
>> '-n|--number': specifies the maximum number of iterations
>> '-i|--input' : Read data from file
> Thanks for contribution,
>
> If batch mode is added the tool should also gain --json option for
> structured output.
Will add new option for json output format support.
Thanks,
Joe
>
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 1/3] irqtop: add batch mode support
2025-02-27 4:49 ` [PATCH 1/3] irqtop: add batch mode support Joe Jin
2025-02-27 9:25 ` Karel Zak
@ 2025-02-28 1:34 ` zhenwei pi
2025-02-28 4:24 ` Joe Jin
1 sibling, 1 reply; 17+ messages in thread
From: zhenwei pi @ 2025-02-28 1:34 UTC (permalink / raw)
To: Joe Jin, Karel Zak, Sami Kerola; +Cc: util-linux
Hi Joe,
I'm a little confused about 'batch'...
Rather than the original terminal formatted style, the new change brings
'raw' style?
What about 'raw'? Hi Karel, what do you think of this?
On 2/27/25 12:49, Joe Jin wrote:
> Add batch mode support, which could be useful for sending output to
> other programs or to a file.
>
> Signed-off-by: Joe Jin <joe.jin@oracle.com>
> Cc: Zhenwei Pi <pizhenwei@bytedance.com>
> Cc: Sami Kerola <kerolasa@iki.fi>
> ---
> bash-completion/irqtop | 6 +++-
> sys-utils/irqtop.1.adoc | 3 ++
> sys-utils/irqtop.c | 79 ++++++++++++++++++++++++++++-------------
> 3 files changed, 63 insertions(+), 25 deletions(-)
>
> diff --git a/bash-completion/irqtop b/bash-completion/irqtop
> index b9e454d4c..215281ee8 100644
> --- a/bash-completion/irqtop
> +++ b/bash-completion/irqtop
> @@ -5,6 +5,9 @@ _irqtop_module()
> cur="${COMP_WORDS[COMP_CWORD]}"
> prev="${COMP_WORDS[COMP_CWORD-1]}"
> case $prev in
> + '-b'|'--batch')
> + return 0
> + ;;
> '-c'|'--cpu-stat')
> COMPREPLY=( $(compgen -W "auto enable disable" -- $cur) )
> return 0
> @@ -40,7 +43,8 @@ _irqtop_module()
> return 0
> ;;
> esac
> - OPTS=" --cpu-stat
> + OPTS=" --batch
> + --cpu-stat
> --cpu-list
> --delay
> --sort
> diff --git a/sys-utils/irqtop.1.adoc b/sys-utils/irqtop.1.adoc
> index 443e23b84..e81f4fbb6 100644
> --- a/sys-utils/irqtop.1.adoc
> +++ b/sys-utils/irqtop.1.adoc
> @@ -25,6 +25,9 @@ The default output is subject to change. So whenever possible, you should avoid
> *-o*, *--output* _list_::
> Specify which output columns to print. Use *--help* to get a list of all supported columns. The default list of columns may be extended if list is specified in the format _+list_.
>
> +*-b*, *--batch*::
> +Starts irqtop in batch mode, which could be useful for sending output to other programs or to a file.
> +
> *-c*, *--cpu-stat* _mode_::
> Show per-cpu statistics by specified mode. Available modes are: *auto*, *enable*, *disable*. The default option *auto* detects the width of window, then shows the per-cpu statistics if the width of window is large enough to show a full line of statistics.
>
> diff --git a/sys-utils/irqtop.c b/sys-utils/irqtop.c
> index 8fbedb16a..00bf8fe50 100644
> --- a/sys-utils/irqtop.c
> +++ b/sys-utils/irqtop.c
> @@ -83,10 +83,22 @@ struct irqtop_ctl {
> cpu_set_t *cpuset;
>
> enum irqtop_cpustat_mode cpustat_mode;
> + bool batch;
> bool request_exit,
> softirq;
> };
>
> +#define irqtop_batch_mode(ctl) ((ctl)->batch == true)
> +#define irqtop_printf(ctl, fmt, args...) \
> + do { \
> + if (irqtop_batch_mode(ctl)) \
> + fprintf(stdout, fmt, ##args); \
> + else { \
> + wprintw(ctl->win, fmt, ##args); \
> + } \
> + }while(0)
> +
> +
> /* user's input parser */
> static void parse_input(struct irqtop_ctl *ctl, struct irq_output *out, char c)
> {
> @@ -128,16 +140,19 @@ static int update_screen(struct irqtop_ctl *ctl, struct irq_output *out)
> scols_table_enable_nowrap(cpus, 1);
> }
>
> - /* print header */
> - move(0, 0);
> strtime_iso(&now, ISO_TIMESTAMP, timestr, sizeof(timestr));
> - wprintw(ctl->win, _("irqtop | total: %ld delta: %ld | %s | %s\n\n"),
> + if (!irqtop_batch_mode(ctl))
> + move(0, 0);
> +
> + /* print header */
> + irqtop_printf(ctl, _("irqtop | total: %ld delta: %ld | %s | %s\n\n"),
> stat->total_irq, stat->delta_irq, ctl->hostname, timestr);
>
> +
> /* print cpus table or not by -c option */
> if (cpus) {
> scols_print_table_to_string(cpus, &data);
> - wprintw(ctl->win, "%s\n\n", data);
> + irqtop_printf(ctl, "%s\n\n", data);
> free(data);
> }
>
> @@ -149,13 +164,15 @@ static int update_screen(struct irqtop_ctl *ctl, struct irq_output *out)
> if (p) {
> /* print header in reverse mode */
> *p = '\0';
> - attron(A_REVERSE);
> - wprintw(ctl->win, "%s\n", data);
> - attroff(A_REVERSE);
> + if (!irqtop_batch_mode(ctl))
> + attron(A_REVERSE);
> + irqtop_printf(ctl, "%s\n", data);
> + if (!irqtop_batch_mode(ctl))
> + attroff(A_REVERSE);
> data = p + 1;
> }
>
> - wprintw(ctl->win, "%s", data);
> + irqtop_printf(ctl, "%s\n", data);
> free(data0);
>
> /* clean up */
> @@ -212,7 +229,8 @@ static int event_loop(struct irqtop_ctl *ctl, struct irq_output *out)
> err(EXIT_FAILURE, _("epoll_ctl failed"));
>
> retval |= update_screen(ctl, out);
> - refresh();
> + if (!irqtop_batch_mode(ctl))
> + refresh();
>
> while (!ctl->request_exit) {
> const ssize_t nr_events = epoll_wait(efd, events, MAX_EVENTS, -1);
> @@ -227,10 +245,12 @@ static int event_loop(struct irqtop_ctl *ctl, struct irq_output *out)
> continue;
> }
> if (siginfo.ssi_signo == SIGWINCH) {
> - get_terminal_dimension(&ctl->cols, &ctl->rows);
> + if (!irqtop_batch_mode(ctl)) {
> + get_terminal_dimension(&ctl->cols, &ctl->rows);
> #if HAVE_RESIZETERM
> - resizeterm(ctl->rows, ctl->cols);
> + resizeterm(ctl->rows, ctl->cols);
> #endif
> + }
> }
> else {
> ctl->request_exit = 1;
> @@ -245,7 +265,8 @@ static int event_loop(struct irqtop_ctl *ctl, struct irq_output *out)
> } else
> abort();
> retval |= update_screen(ctl, out);
> - refresh();
> + if (!irqtop_batch_mode(ctl))
> + refresh();
> }
> }
> return retval;
> @@ -260,6 +281,7 @@ static void __attribute__((__noreturn__)) usage(void)
> puts(_("Interactive utility to display kernel interrupt information."));
>
> fputs(USAGE_OPTIONS, stdout);
> + fputs(_(" -b, --batch batch mode\n"), stdout);
> fputs(_(" -c, --cpu-stat <mode> show per-cpu stat (auto, enable, disable)\n"), stdout);
> fputs(_(" -C, --cpu-list <list> specify cpus in list format\n"), stdout);
> fputs(_(" -d, --delay <secs> delay updates\n"), stdout);
> @@ -291,6 +313,7 @@ static void parse_args( struct irqtop_ctl *ctl,
> {
> const char *outarg = NULL;
> static const struct option longopts[] = {
> + {"batch", no_argument, NULL, 'b'},
> {"cpu-stat", required_argument, NULL, 'c'},
> {"cpu-list", required_argument, NULL, 'C'},
> {"delay", required_argument, NULL, 'd'},
> @@ -304,8 +327,11 @@ static void parse_args( struct irqtop_ctl *ctl,
> };
> int o;
>
> - while ((o = getopt_long(argc, argv, "c:C:d:o:s:St:hV", longopts, NULL)) != -1) {
> + while ((o = getopt_long(argc, argv, "bc:C:d:o:s:St:hV", longopts, NULL)) != -1) {
> switch (o) {
> + case 'b':
> + ctl->batch = true;
> + break;
> case 'c':
> if (!strcmp(optarg, "auto"))
> ctl->cpustat_mode = IRQTOP_CPUSTAT_AUTO;
> @@ -394,16 +420,18 @@ int main(int argc, char **argv)
>
> parse_args(&ctl, &out, argc, argv);
>
> - is_tty = isatty(STDIN_FILENO);
> - if (is_tty && tcgetattr(STDIN_FILENO, &saved_tty) == -1)
> - fputs(_("terminal setting retrieval"), stdout);
> + if (ctl.batch == false) {
> + is_tty = isatty(STDIN_FILENO);
> + if (is_tty && tcgetattr(STDIN_FILENO, &saved_tty) == -1)
> + fputs(_("terminal setting retrieval"), stdout);
>
> - ctl.win = initscr();
> - get_terminal_dimension(&ctl.cols, &ctl.rows);
> + ctl.win = initscr();
> + get_terminal_dimension(&ctl.cols, &ctl.rows);
> #if HAVE_RESIZETERM
> - resizeterm(ctl.rows, ctl.cols);
> + resizeterm(ctl.rows, ctl.cols);
> #endif
> - curs_set(0);
> + curs_set(0);
> + }
>
> ctl.hostname = xgethostname();
> event_loop(&ctl, &out);
> @@ -412,10 +440,13 @@ int main(int argc, char **argv)
> free(ctl.hostname);
> cpuset_free(ctl.cpuset);
>
> - if (is_tty)
> - tcsetattr(STDIN_FILENO, TCSAFLUSH, &saved_tty);
> - delwin(ctl.win);
> - endwin();
> + if (ctl.batch == false) {
> + if (is_tty)
> + tcsetattr(STDIN_FILENO, TCSAFLUSH, &saved_tty);
> +
> + delwin(ctl.win);
> + endwin();
> + }
>
> return EXIT_SUCCESS;
> }
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 3/3] lsirq,irqtop: add support for reading data from given file
2025-02-27 4:49 ` [PATCH 3/3] lsirq,irqtop: add support for reading data from given file Joe Jin
2025-02-27 9:30 ` Karel Zak
@ 2025-02-28 1:41 ` zhenwei pi
2025-02-28 4:25 ` Joe Jin
1 sibling, 1 reply; 17+ messages in thread
From: zhenwei pi @ 2025-02-28 1:41 UTC (permalink / raw)
To: Joe Jin, Karel Zak, Sami Kerola; +Cc: util-linux
Does the '--input IRQFILE' change?
irqtop reads 'IRQFILE' and uses the current one to calculate the
increment from the previous one, I'm curious about this case ...
But I guess lsirq would work fine.
On 2/27/25 12:49, Joe Jin wrote:
> This is helpful for analyzng data saved from other system.
>
> Signed-off-by: Joe Jin <joe.jin@oracle.com>
> Cc: Zhenwei Pi <pizhenwei@bytedance.com>
> Cc: Sami Kerola <kerolasa@iki.fi>
> ---
> bash-completion/irqtop | 4 ++++
> bash-completion/lsirq | 4 ++++
> sys-utils/irq-common.c | 19 +++++++++----------
> sys-utils/irq-common.h | 3 ++-
> sys-utils/irqtop.1.adoc | 3 +++
> sys-utils/irqtop.c | 28 +++++++++++++++++++++++++---
> sys-utils/lsirq.1.adoc | 3 +++
> sys-utils/lsirq.c | 28 ++++++++++++++++++++++++----
> 8 files changed, 74 insertions(+), 18 deletions(-)
>
> diff --git a/bash-completion/irqtop b/bash-completion/irqtop
> index 47b7b0af6..3bea5fc0e 100644
> --- a/bash-completion/irqtop
> +++ b/bash-completion/irqtop
> @@ -15,6 +15,9 @@ _irqtop_module()
> '-C'|'--cpu-list')
> return 0
> ;;
> + '-i'|'--input')
> + COMPREPLY=( $(compgen -W "input file" -- $cur) )
> + ;;
> '-t'|'--threshold')
> return 0
> ;;
> @@ -51,6 +54,7 @@ _irqtop_module()
> --cpu-stat
> --cpu-list
> --delay
> + --input
> --number
> --sort
> --output
> diff --git a/bash-completion/lsirq b/bash-completion/lsirq
> index 4c3c9f04f..b913eecd0 100644
> --- a/bash-completion/lsirq
> +++ b/bash-completion/lsirq
> @@ -5,6 +5,9 @@ _lsirq_module()
> cur="${COMP_WORDS[COMP_CWORD]}"
> prev="${COMP_WORDS[COMP_CWORD-1]}"
> case $prev in
> + '-i'|'--input')
> + COMPREPLY=( $(compgen -W "input file" -- $cur) )
> + ;;
> '-o'|'--output')
> local prefix realcur OUTPUT
> realcur="${cur##*,}"
> @@ -35,6 +38,7 @@ _lsirq_module()
> OPTS=" --json
> --pairs
> --noheadings
> + --input
> --output
> --softirq
> --sort
> diff --git a/sys-utils/irq-common.c b/sys-utils/irq-common.c
> index f069d8a63..560dd4b82 100644
> --- a/sys-utils/irq-common.c
> +++ b/sys-utils/irq-common.c
> @@ -233,7 +233,8 @@ static bool cpu_in_list(int cpu, size_t setsize, cpu_set_t *cpuset)
> /*
> * irqinfo - parse the system's interrupts
> */
> -static struct irq_stat *get_irqinfo(int softirq, size_t setsize, cpu_set_t *cpuset)
> +static struct irq_stat *get_irqinfo(const char *input_file, int softirq,
> + size_t setsize, cpu_set_t *cpuset)
> {
> FILE *irqfile;
> char *line = NULL, *tmp;
> @@ -247,18 +248,15 @@ static struct irq_stat *get_irqinfo(int softirq, size_t setsize, cpu_set_t *cpus
> stat->irq_info = xmalloc(sizeof(*stat->irq_info) * IRQ_INFO_LEN);
> stat->nr_irq_info = IRQ_INFO_LEN;
>
> - if (softirq)
> - irqfile = fopen(_PATH_PROC_SOFTIRQS, "r");
> - else
> - irqfile = fopen(_PATH_PROC_INTERRUPTS, "r");
> + irqfile = fopen(input_file, "r");
> if (!irqfile) {
> - warn(_("cannot open %s"), _PATH_PROC_INTERRUPTS);
> + warn(_("cannot open %s"), input_file);
> goto free_stat;
> }
>
> /* read header firstly */
> if (getline(&line, &len, irqfile) < 0) {
> - warn(_("cannot read %s"), _PATH_PROC_INTERRUPTS);
> + warn(_("cannot read %s"), input_file);
> goto close_file;
> }
>
> @@ -270,7 +268,7 @@ static struct irq_stat *get_irqinfo(int softirq, size_t setsize, cpu_set_t *cpus
>
> stat->cpus = xcalloc(stat->nr_active_cpu, sizeof(struct irq_cpu));
>
> - /* parse each line of _PATH_PROC_INTERRUPTS */
> + /* parse each line of input file */
> while (getline(&line, &len, irqfile) >= 0) {
> unsigned long count;
> size_t index;
> @@ -527,7 +525,8 @@ struct libscols_table *get_scols_cpus_table(struct irq_output *out,
> return NULL;
> }
>
> -struct libscols_table *get_scols_table(struct irq_output *out,
> +struct libscols_table *get_scols_table(const char *input_file,
> + struct irq_output *out,
> struct irq_stat *prev,
> struct irq_stat **xstat,
> int softirq,
> @@ -542,7 +541,7 @@ struct libscols_table *get_scols_table(struct irq_output *out,
> size_t i;
>
> /* the stats */
> - stat = get_irqinfo(softirq, setsize, cpuset);
> + stat = get_irqinfo(input_file, softirq, setsize, cpuset);
> if (!stat)
> return NULL;
>
> diff --git a/sys-utils/irq-common.h b/sys-utils/irq-common.h
> index 02b72d752..b9cf72d2a 100644
> --- a/sys-utils/irq-common.h
> +++ b/sys-utils/irq-common.h
> @@ -73,7 +73,8 @@ void irq_print_columns(FILE *f, int nodelta);
> void set_sort_func_by_name(struct irq_output *out, const char *name);
> void set_sort_func_by_key(struct irq_output *out, const char c);
>
> -struct libscols_table *get_scols_table(struct irq_output *out,
> +struct libscols_table *get_scols_table(const char *input_file,
> + struct irq_output *out,
> struct irq_stat *prev,
> struct irq_stat **xstat,
> int softirq,
> diff --git a/sys-utils/irqtop.1.adoc b/sys-utils/irqtop.1.adoc
> index 75cfe2e41..715008d07 100644
> --- a/sys-utils/irqtop.1.adoc
> +++ b/sys-utils/irqtop.1.adoc
> @@ -37,6 +37,9 @@ Specify cpus in list format to show.
> *-d*, *--delay* _seconds_::
> Update interrupt output every _seconds_ intervals.
>
> +*-i*, *--input* _file_::
> +Read data from _file_ (Which was created by other tools, e.g. sosreport).
> +
> *-n*, *--number* _number_::
> Specifies the maximum _number_ of iterations before quitting.
>
> diff --git a/sys-utils/irqtop.c b/sys-utils/irqtop.c
> index ba5680671..4cf1dc79a 100644
> --- a/sys-utils/irqtop.c
> +++ b/sys-utils/irqtop.c
> @@ -87,6 +87,8 @@ struct irqtop_ctl {
> bool batch;
> bool request_exit,
> softirq;
> +
> + char *input;
> };
>
> #define irqtop_batch_mode(ctl) ((ctl)->batch == true)
> @@ -122,8 +124,9 @@ static int update_screen(struct irqtop_ctl *ctl, struct irq_output *out)
> char timestr[64], *data, *data0, *p;
>
> /* make irqs table */
> - table = get_scols_table(out, ctl->prev_stat, &stat, ctl->softirq,
> - ctl->threshold, ctl->setsize, ctl->cpuset);
> + table = get_scols_table(ctl->input, out, ctl->prev_stat, &stat,
> + ctl->softirq, ctl->threshold, ctl->setsize,
> + ctl->cpuset);
> if (!table) {
> ctl->request_exit = 1;
> return 1;
> @@ -292,6 +295,7 @@ static void __attribute__((__noreturn__)) usage(void)
> fputs(_(" -c, --cpu-stat <mode> show per-cpu stat (auto, enable, disable)\n"), stdout);
> fputs(_(" -C, --cpu-list <list> specify cpus in list format\n"), stdout);
> fputs(_(" -d, --delay <secs> delay updates\n"), stdout);
> + fputs(_(" -i, --input <file> read data from file\n"), stdout);
> fputs(_(" -n, --number <number> the maximum number of iterations\n"), stdout);
> fputs(_(" -o, --output <list> define which output columns to use\n"), stdout);
> fputs(_(" -s, --sort <column> specify sort column\n"), stdout);
> @@ -325,6 +329,7 @@ static void parse_args( struct irqtop_ctl *ctl,
> {"cpu-stat", required_argument, NULL, 'c'},
> {"cpu-list", required_argument, NULL, 'C'},
> {"delay", required_argument, NULL, 'd'},
> + {"input", required_argument, NULL, 'i'},
> {"number", required_argument, NULL, 'n'},
> {"sort", required_argument, NULL, 's'},
> {"output", required_argument, NULL, 'o'},
> @@ -336,7 +341,7 @@ static void parse_args( struct irqtop_ctl *ctl,
> };
> int o;
>
> - while ((o = getopt_long(argc, argv, "bc:C:d:n:o:s:St:hV", longopts, NULL)) != -1) {
> + while ((o = getopt_long(argc, argv, "bc:C:d:i:n:o:s:St:hV", longopts, NULL)) != -1) {
> switch (o) {
> case 'b':
> ctl->batch = true;
> @@ -376,6 +381,13 @@ static void parse_args( struct irqtop_ctl *ctl,
> ctl->timer.it_value = ctl->timer.it_interval;
> }
> break;
> + case 'i':
> + ctl->input = strdup(optarg);
> + if (!ctl->input)
> + err_oom();
> + ctl->number = 1;
> + ctl->batch = true;
> + break;
> case 'n':
> ctl->number = str2num_or_err(optarg, 10,
> _("failed to parse number argument"),
> @@ -402,6 +414,15 @@ static void parse_args( struct irqtop_ctl *ctl,
> }
> }
>
> + if (ctl->input == NULL) {
> + if (ctl->softirq == 1)
> + ctl->input = strdup(_PATH_PROC_SOFTIRQS);
> + else
> + ctl->input = strdup(_PATH_PROC_INTERRUPTS);
> + if (!ctl->input)
> + err_oom();
> + }
> +
> /* default */
> if (!out->ncolumns) {
> out->columns[out->ncolumns++] = COL_IRQ;
> @@ -453,6 +474,7 @@ int main(int argc, char **argv)
>
> free_irqstat(ctl.prev_stat);
> free(ctl.hostname);
> + free(ctl.input);
> cpuset_free(ctl.cpuset);
>
> if (ctl.batch == false) {
> diff --git a/sys-utils/lsirq.1.adoc b/sys-utils/lsirq.1.adoc
> index 02aea16b3..dd265710c 100644
> --- a/sys-utils/lsirq.1.adoc
> +++ b/sys-utils/lsirq.1.adoc
> @@ -25,6 +25,9 @@ The default output is subject to change. So whenever possible, you should avoid
> *-n*, *--noheadings*::
> Don't print headings.
>
> +*-i*, *--input* _file_::
> +Read data from _file_ (Which was created by other tools, e.g. sosreport).
> +
> *-o*, *--output* _list_::
> Specify which output columns to print. Use *--help* to get a list of all supported columns. The default list of columns may be extended if list is specified in the format _+list_.
>
> diff --git a/sys-utils/lsirq.c b/sys-utils/lsirq.c
> index e31addaf5..45d542919 100644
> --- a/sys-utils/lsirq.c
> +++ b/sys-utils/lsirq.c
> @@ -29,16 +29,17 @@
> #include "optutils.h"
> #include "strutils.h"
> #include "xalloc.h"
> +#include "pathnames.h"
>
> #include "irq-common.h"
>
> -static int print_irq_data(struct irq_output *out,
> +static int print_irq_data(const char *input_file, struct irq_output *out,
> int softirq, unsigned long threshold,
> size_t setsize, cpu_set_t *cpuset)
> {
> struct libscols_table *table;
>
> - table = get_scols_table(out, NULL, NULL, softirq, threshold, setsize, cpuset);
> + table = get_scols_table(input_file, out, NULL, NULL, softirq, threshold, setsize, cpuset);
> if (!table)
> return -1;
>
> @@ -58,6 +59,7 @@ static void __attribute__((__noreturn__)) usage(void)
> fputs(USAGE_OPTIONS, stdout);
> fputs(_(" -J, --json use JSON output format\n"), stdout);
> fputs(_(" -P, --pairs use key=\"value\" output format\n"), stdout);
> + fputs(_(" -i, --input read data from input file\n"), stdout);
> fputs(_(" -n, --noheadings don't print headings\n"), stdout);
> fputs(_(" -o, --output <list> define which output columns to use\n"), stdout);
> fputs(_(" -s, --sort <column> specify sort column\n"), stdout);
> @@ -82,6 +84,7 @@ int main(int argc, char **argv)
> static const struct option longopts[] = {
> {"sort", required_argument, NULL, 's'},
> {"noheadings", no_argument, NULL, 'n'},
> + {"input", required_argument, NULL, 'i'},
> {"output", required_argument, NULL, 'o'},
> {"threshold", required_argument, NULL, 't'},
> {"cpu-list", required_argument, NULL, 'C'},
> @@ -103,10 +106,11 @@ int main(int argc, char **argv)
> cpu_set_t *cpuset = NULL;
> size_t setsize = 0;
> int softirq = 0;
> + char *input = NULL;
>
> setlocale(LC_ALL, "");
>
> - while ((c = getopt_long(argc, argv, "no:s:t:C:ShJPV", longopts, NULL)) != -1) {
> + while ((c = getopt_long(argc, argv, "i:no:s:t:C:ShJPV", longopts, NULL)) != -1) {
> err_exclusive_options(c, longopts, excl, excl_st);
>
> switch (c) {
> @@ -116,6 +120,11 @@ int main(int argc, char **argv)
> case 'P':
> out.pairs = 1;
> break;
> + case 'i':
> + input = strdup(optarg);
> + if (!input)
> + err_oom();
> + break;
> case 'n':
> out.no_headings = 1;
> break;
> @@ -157,6 +166,15 @@ int main(int argc, char **argv)
> }
> }
>
> + if (input == NULL) {
> + if (softirq == 1)
> + input = strdup(_PATH_PROC_SOFTIRQS);
> + else
> + input = strdup(_PATH_PROC_INTERRUPTS);
> + if (!input)
> + err_oom();
> + }
> +
> /* default */
> if (!out.ncolumns) {
> out.columns[out.ncolumns++] = COL_IRQ;
> @@ -171,8 +189,10 @@ int main(int argc, char **argv)
> irq_column_name_to_id) < 0)
> exit(EXIT_FAILURE);
>
> - if (print_irq_data(&out, softirq, threshold, setsize, cpuset) < 0)
> + if (print_irq_data(input, &out, softirq, threshold, setsize, cpuset) < 0)
> return EXIT_FAILURE;
>
> + free(input);
> +
> return EXIT_SUCCESS;
> }
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 1/3] irqtop: add batch mode support
2025-02-28 1:34 ` zhenwei pi
@ 2025-02-28 4:24 ` Joe Jin
0 siblings, 0 replies; 17+ messages in thread
From: Joe Jin @ 2025-02-28 4:24 UTC (permalink / raw)
To: zhenwei pi, Karel Zak, Sami Kerola; +Cc: util-linux
On 2/27/25 17:34, zhenwei pi wrote:
> Hi Joe,
>
> I'm a little confused about 'batch'...
Most time the purpose of batch mode is to capture data continuously.
Thanks,
Joe
>
> Rather than the original terminal formatted style, the new change brings 'raw' style?
>
> What about 'raw'? Hi Karel, what do you think of this?
>
> On 2/27/25 12:49, Joe Jin wrote:
>> Add batch mode support, which could be useful for sending output to
>> other programs or to a file.
>>
>> Signed-off-by: Joe Jin <joe.jin@oracle.com>
>> Cc: Zhenwei Pi <pizhenwei@bytedance.com>
>> Cc: Sami Kerola <kerolasa@iki.fi>
>> ---
>> bash-completion/irqtop | 6 +++-
>> sys-utils/irqtop.1.adoc | 3 ++
>> sys-utils/irqtop.c | 79 ++++++++++++++++++++++++++++-------------
>> 3 files changed, 63 insertions(+), 25 deletions(-)
>>
>> diff --git a/bash-completion/irqtop b/bash-completion/irqtop
>> index b9e454d4c..215281ee8 100644
>> --- a/bash-completion/irqtop
>> +++ b/bash-completion/irqtop
>> @@ -5,6 +5,9 @@ _irqtop_module()
>> cur="${COMP_WORDS[COMP_CWORD]}"
>> prev="${COMP_WORDS[COMP_CWORD-1]}"
>> case $prev in
>> + '-b'|'--batch')
>> + return 0
>> + ;;
>> '-c'|'--cpu-stat')
>> COMPREPLY=( $(compgen -W "auto enable disable" -- $cur) )
>> return 0
>> @@ -40,7 +43,8 @@ _irqtop_module()
>> return 0
>> ;;
>> esac
>> - OPTS=" --cpu-stat
>> + OPTS=" --batch
>> + --cpu-stat
>> --cpu-list
>> --delay
>> --sort
>> diff --git a/sys-utils/irqtop.1.adoc b/sys-utils/irqtop.1.adoc
>> index 443e23b84..e81f4fbb6 100644
>> --- a/sys-utils/irqtop.1.adoc
>> +++ b/sys-utils/irqtop.1.adoc
>> @@ -25,6 +25,9 @@ The default output is subject to change. So whenever possible, you should avoid
>> *-o*, *--output* _list_::
>> Specify which output columns to print. Use *--help* to get a list of all supported columns. The default list of columns may be extended if list is specified in the format _+list_.
>> +*-b*, *--batch*::
>> +Starts irqtop in batch mode, which could be useful for sending output to other programs or to a file.
>> +
>> *-c*, *--cpu-stat* _mode_::
>> Show per-cpu statistics by specified mode. Available modes are: *auto*, *enable*, *disable*. The default option *auto* detects the width of window, then shows the per-cpu statistics if the width of window is large enough to show a full line of statistics.
>> diff --git a/sys-utils/irqtop.c b/sys-utils/irqtop.c
>> index 8fbedb16a..00bf8fe50 100644
>> --- a/sys-utils/irqtop.c
>> +++ b/sys-utils/irqtop.c
>> @@ -83,10 +83,22 @@ struct irqtop_ctl {
>> cpu_set_t *cpuset;
>> enum irqtop_cpustat_mode cpustat_mode;
>> + bool batch;
>> bool request_exit,
>> softirq;
>> };
>> +#define irqtop_batch_mode(ctl) ((ctl)->batch == true)
>> +#define irqtop_printf(ctl, fmt, args...) \
>> + do { \
>> + if (irqtop_batch_mode(ctl)) \
>> + fprintf(stdout, fmt, ##args); \
>> + else { \
>> + wprintw(ctl->win, fmt, ##args); \
>> + } \
>> + }while(0)
>> +
>> +
>> /* user's input parser */
>> static void parse_input(struct irqtop_ctl *ctl, struct irq_output *out, char c)
>> {
>> @@ -128,16 +140,19 @@ static int update_screen(struct irqtop_ctl *ctl, struct irq_output *out)
>> scols_table_enable_nowrap(cpus, 1);
>> }
>> - /* print header */
>> - move(0, 0);
>> strtime_iso(&now, ISO_TIMESTAMP, timestr, sizeof(timestr));
>> - wprintw(ctl->win, _("irqtop | total: %ld delta: %ld | %s | %s\n\n"),
>> + if (!irqtop_batch_mode(ctl))
>> + move(0, 0);
>> +
>> + /* print header */
>> + irqtop_printf(ctl, _("irqtop | total: %ld delta: %ld | %s | %s\n\n"),
>> stat->total_irq, stat->delta_irq, ctl->hostname, timestr);
>> +
>> /* print cpus table or not by -c option */
>> if (cpus) {
>> scols_print_table_to_string(cpus, &data);
>> - wprintw(ctl->win, "%s\n\n", data);
>> + irqtop_printf(ctl, "%s\n\n", data);
>> free(data);
>> }
>> @@ -149,13 +164,15 @@ static int update_screen(struct irqtop_ctl *ctl, struct irq_output *out)
>> if (p) {
>> /* print header in reverse mode */
>> *p = '\0';
>> - attron(A_REVERSE);
>> - wprintw(ctl->win, "%s\n", data);
>> - attroff(A_REVERSE);
>> + if (!irqtop_batch_mode(ctl))
>> + attron(A_REVERSE);
>> + irqtop_printf(ctl, "%s\n", data);
>> + if (!irqtop_batch_mode(ctl))
>> + attroff(A_REVERSE);
>> data = p + 1;
>> }
>> - wprintw(ctl->win, "%s", data);
>> + irqtop_printf(ctl, "%s\n", data);
>> free(data0);
>> /* clean up */
>> @@ -212,7 +229,8 @@ static int event_loop(struct irqtop_ctl *ctl, struct irq_output *out)
>> err(EXIT_FAILURE, _("epoll_ctl failed"));
>> retval |= update_screen(ctl, out);
>> - refresh();
>> + if (!irqtop_batch_mode(ctl))
>> + refresh();
>> while (!ctl->request_exit) {
>> const ssize_t nr_events = epoll_wait(efd, events, MAX_EVENTS, -1);
>> @@ -227,10 +245,12 @@ static int event_loop(struct irqtop_ctl *ctl, struct irq_output *out)
>> continue;
>> }
>> if (siginfo.ssi_signo == SIGWINCH) {
>> - get_terminal_dimension(&ctl->cols, &ctl->rows);
>> + if (!irqtop_batch_mode(ctl)) {
>> + get_terminal_dimension(&ctl->cols, &ctl->rows);
>> #if HAVE_RESIZETERM
>> - resizeterm(ctl->rows, ctl->cols);
>> + resizeterm(ctl->rows, ctl->cols);
>> #endif
>> + }
>> }
>> else {
>> ctl->request_exit = 1;
>> @@ -245,7 +265,8 @@ static int event_loop(struct irqtop_ctl *ctl, struct irq_output *out)
>> } else
>> abort();
>> retval |= update_screen(ctl, out);
>> - refresh();
>> + if (!irqtop_batch_mode(ctl))
>> + refresh();
>> }
>> }
>> return retval;
>> @@ -260,6 +281,7 @@ static void __attribute__((__noreturn__)) usage(void)
>> puts(_("Interactive utility to display kernel interrupt information."));
>> fputs(USAGE_OPTIONS, stdout);
>> + fputs(_(" -b, --batch batch mode\n"), stdout);
>> fputs(_(" -c, --cpu-stat <mode> show per-cpu stat (auto, enable, disable)\n"), stdout);
>> fputs(_(" -C, --cpu-list <list> specify cpus in list format\n"), stdout);
>> fputs(_(" -d, --delay <secs> delay updates\n"), stdout);
>> @@ -291,6 +313,7 @@ static void parse_args( struct irqtop_ctl *ctl,
>> {
>> const char *outarg = NULL;
>> static const struct option longopts[] = {
>> + {"batch", no_argument, NULL, 'b'},
>> {"cpu-stat", required_argument, NULL, 'c'},
>> {"cpu-list", required_argument, NULL, 'C'},
>> {"delay", required_argument, NULL, 'd'},
>> @@ -304,8 +327,11 @@ static void parse_args( struct irqtop_ctl *ctl,
>> };
>> int o;
>> - while ((o = getopt_long(argc, argv, "c:C:d:o:s:St:hV", longopts, NULL)) != -1) {
>> + while ((o = getopt_long(argc, argv, "bc:C:d:o:s:St:hV", longopts, NULL)) != -1) {
>> switch (o) {
>> + case 'b':
>> + ctl->batch = true;
>> + break;
>> case 'c':
>> if (!strcmp(optarg, "auto"))
>> ctl->cpustat_mode = IRQTOP_CPUSTAT_AUTO;
>> @@ -394,16 +420,18 @@ int main(int argc, char **argv)
>> parse_args(&ctl, &out, argc, argv);
>> - is_tty = isatty(STDIN_FILENO);
>> - if (is_tty && tcgetattr(STDIN_FILENO, &saved_tty) == -1)
>> - fputs(_("terminal setting retrieval"), stdout);
>> + if (ctl.batch == false) {
>> + is_tty = isatty(STDIN_FILENO);
>> + if (is_tty && tcgetattr(STDIN_FILENO, &saved_tty) == -1)
>> + fputs(_("terminal setting retrieval"), stdout);
>> - ctl.win = initscr();
>> - get_terminal_dimension(&ctl.cols, &ctl.rows);
>> + ctl.win = initscr();
>> + get_terminal_dimension(&ctl.cols, &ctl.rows);
>> #if HAVE_RESIZETERM
>> - resizeterm(ctl.rows, ctl.cols);
>> + resizeterm(ctl.rows, ctl.cols);
>> #endif
>> - curs_set(0);
>> + curs_set(0);
>> + }
>> ctl.hostname = xgethostname();
>> event_loop(&ctl, &out);
>> @@ -412,10 +440,13 @@ int main(int argc, char **argv)
>> free(ctl.hostname);
>> cpuset_free(ctl.cpuset);
>> - if (is_tty)
>> - tcsetattr(STDIN_FILENO, TCSAFLUSH, &saved_tty);
>> - delwin(ctl.win);
>> - endwin();
>> + if (ctl.batch == false) {
>> + if (is_tty)
>> + tcsetattr(STDIN_FILENO, TCSAFLUSH, &saved_tty);
>> +
>> + delwin(ctl.win);
>> + endwin();
>> + }
>> return EXIT_SUCCESS;
>> }
>
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 3/3] lsirq,irqtop: add support for reading data from given file
2025-02-28 1:41 ` zhenwei pi
@ 2025-02-28 4:25 ` Joe Jin
0 siblings, 0 replies; 17+ messages in thread
From: Joe Jin @ 2025-02-28 4:25 UTC (permalink / raw)
To: zhenwei pi, Karel Zak, Sami Kerola; +Cc: util-linux
On 2/27/25 17:41, zhenwei pi wrote:
> Does the '--input IRQFILE' change?
>
> irqtop reads 'IRQFILE' and uses the current one to calculate the increment from the previous one, I'm curious about this case ...
>
> But I guess lsirq would work fine.
Make sense, I'll remove this option from irqtop.
Thanks,
Joe
>
> On 2/27/25 12:49, Joe Jin wrote:
>> This is helpful for analyzng data saved from other system.
>>
>> Signed-off-by: Joe Jin <joe.jin@oracle.com>
>> Cc: Zhenwei Pi <pizhenwei@bytedance.com>
>> Cc: Sami Kerola <kerolasa@iki.fi>
>> ---
>> bash-completion/irqtop | 4 ++++
>> bash-completion/lsirq | 4 ++++
>> sys-utils/irq-common.c | 19 +++++++++----------
>> sys-utils/irq-common.h | 3 ++-
>> sys-utils/irqtop.1.adoc | 3 +++
>> sys-utils/irqtop.c | 28 +++++++++++++++++++++++++---
>> sys-utils/lsirq.1.adoc | 3 +++
>> sys-utils/lsirq.c | 28 ++++++++++++++++++++++++----
>> 8 files changed, 74 insertions(+), 18 deletions(-)
>>
>> diff --git a/bash-completion/irqtop b/bash-completion/irqtop
>> index 47b7b0af6..3bea5fc0e 100644
>> --- a/bash-completion/irqtop
>> +++ b/bash-completion/irqtop
>> @@ -15,6 +15,9 @@ _irqtop_module()
>> '-C'|'--cpu-list')
>> return 0
>> ;;
>> + '-i'|'--input')
>> + COMPREPLY=( $(compgen -W "input file" -- $cur) )
>> + ;;
>> '-t'|'--threshold')
>> return 0
>> ;;
>> @@ -51,6 +54,7 @@ _irqtop_module()
>> --cpu-stat
>> --cpu-list
>> --delay
>> + --input
>> --number
>> --sort
>> --output
>> diff --git a/bash-completion/lsirq b/bash-completion/lsirq
>> index 4c3c9f04f..b913eecd0 100644
>> --- a/bash-completion/lsirq
>> +++ b/bash-completion/lsirq
>> @@ -5,6 +5,9 @@ _lsirq_module()
>> cur="${COMP_WORDS[COMP_CWORD]}"
>> prev="${COMP_WORDS[COMP_CWORD-1]}"
>> case $prev in
>> + '-i'|'--input')
>> + COMPREPLY=( $(compgen -W "input file" -- $cur) )
>> + ;;
>> '-o'|'--output')
>> local prefix realcur OUTPUT
>> realcur="${cur##*,}"
>> @@ -35,6 +38,7 @@ _lsirq_module()
>> OPTS=" --json
>> --pairs
>> --noheadings
>> + --input
>> --output
>> --softirq
>> --sort
>> diff --git a/sys-utils/irq-common.c b/sys-utils/irq-common.c
>> index f069d8a63..560dd4b82 100644
>> --- a/sys-utils/irq-common.c
>> +++ b/sys-utils/irq-common.c
>> @@ -233,7 +233,8 @@ static bool cpu_in_list(int cpu, size_t setsize, cpu_set_t *cpuset)
>> /*
>> * irqinfo - parse the system's interrupts
>> */
>> -static struct irq_stat *get_irqinfo(int softirq, size_t setsize, cpu_set_t *cpuset)
>> +static struct irq_stat *get_irqinfo(const char *input_file, int softirq,
>> + size_t setsize, cpu_set_t *cpuset)
>> {
>> FILE *irqfile;
>> char *line = NULL, *tmp;
>> @@ -247,18 +248,15 @@ static struct irq_stat *get_irqinfo(int softirq, size_t setsize, cpu_set_t *cpus
>> stat->irq_info = xmalloc(sizeof(*stat->irq_info) * IRQ_INFO_LEN);
>> stat->nr_irq_info = IRQ_INFO_LEN;
>> - if (softirq)
>> - irqfile = fopen(_PATH_PROC_SOFTIRQS, "r");
>> - else
>> - irqfile = fopen(_PATH_PROC_INTERRUPTS, "r");
>> + irqfile = fopen(input_file, "r");
>> if (!irqfile) {
>> - warn(_("cannot open %s"), _PATH_PROC_INTERRUPTS);
>> + warn(_("cannot open %s"), input_file);
>> goto free_stat;
>> }
>> /* read header firstly */
>> if (getline(&line, &len, irqfile) < 0) {
>> - warn(_("cannot read %s"), _PATH_PROC_INTERRUPTS);
>> + warn(_("cannot read %s"), input_file);
>> goto close_file;
>> }
>> @@ -270,7 +268,7 @@ static struct irq_stat *get_irqinfo(int softirq, size_t setsize, cpu_set_t *cpus
>> stat->cpus = xcalloc(stat->nr_active_cpu, sizeof(struct irq_cpu));
>> - /* parse each line of _PATH_PROC_INTERRUPTS */
>> + /* parse each line of input file */
>> while (getline(&line, &len, irqfile) >= 0) {
>> unsigned long count;
>> size_t index;
>> @@ -527,7 +525,8 @@ struct libscols_table *get_scols_cpus_table(struct irq_output *out,
>> return NULL;
>> }
>> -struct libscols_table *get_scols_table(struct irq_output *out,
>> +struct libscols_table *get_scols_table(const char *input_file,
>> + struct irq_output *out,
>> struct irq_stat *prev,
>> struct irq_stat **xstat,
>> int softirq,
>> @@ -542,7 +541,7 @@ struct libscols_table *get_scols_table(struct irq_output *out,
>> size_t i;
>> /* the stats */
>> - stat = get_irqinfo(softirq, setsize, cpuset);
>> + stat = get_irqinfo(input_file, softirq, setsize, cpuset);
>> if (!stat)
>> return NULL;
>> diff --git a/sys-utils/irq-common.h b/sys-utils/irq-common.h
>> index 02b72d752..b9cf72d2a 100644
>> --- a/sys-utils/irq-common.h
>> +++ b/sys-utils/irq-common.h
>> @@ -73,7 +73,8 @@ void irq_print_columns(FILE *f, int nodelta);
>> void set_sort_func_by_name(struct irq_output *out, const char *name);
>> void set_sort_func_by_key(struct irq_output *out, const char c);
>> -struct libscols_table *get_scols_table(struct irq_output *out,
>> +struct libscols_table *get_scols_table(const char *input_file,
>> + struct irq_output *out,
>> struct irq_stat *prev,
>> struct irq_stat **xstat,
>> int softirq,
>> diff --git a/sys-utils/irqtop.1.adoc b/sys-utils/irqtop.1.adoc
>> index 75cfe2e41..715008d07 100644
>> --- a/sys-utils/irqtop.1.adoc
>> +++ b/sys-utils/irqtop.1.adoc
>> @@ -37,6 +37,9 @@ Specify cpus in list format to show.
>> *-d*, *--delay* _seconds_::
>> Update interrupt output every _seconds_ intervals.
>> +*-i*, *--input* _file_::
>> +Read data from _file_ (Which was created by other tools, e.g. sosreport).
>> +
>> *-n*, *--number* _number_::
>> Specifies the maximum _number_ of iterations before quitting.
>> diff --git a/sys-utils/irqtop.c b/sys-utils/irqtop.c
>> index ba5680671..4cf1dc79a 100644
>> --- a/sys-utils/irqtop.c
>> +++ b/sys-utils/irqtop.c
>> @@ -87,6 +87,8 @@ struct irqtop_ctl {
>> bool batch;
>> bool request_exit,
>> softirq;
>> +
>> + char *input;
>> };
>> #define irqtop_batch_mode(ctl) ((ctl)->batch == true)
>> @@ -122,8 +124,9 @@ static int update_screen(struct irqtop_ctl *ctl, struct irq_output *out)
>> char timestr[64], *data, *data0, *p;
>> /* make irqs table */
>> - table = get_scols_table(out, ctl->prev_stat, &stat, ctl->softirq,
>> - ctl->threshold, ctl->setsize, ctl->cpuset);
>> + table = get_scols_table(ctl->input, out, ctl->prev_stat, &stat,
>> + ctl->softirq, ctl->threshold, ctl->setsize,
>> + ctl->cpuset);
>> if (!table) {
>> ctl->request_exit = 1;
>> return 1;
>> @@ -292,6 +295,7 @@ static void __attribute__((__noreturn__)) usage(void)
>> fputs(_(" -c, --cpu-stat <mode> show per-cpu stat (auto, enable, disable)\n"), stdout);
>> fputs(_(" -C, --cpu-list <list> specify cpus in list format\n"), stdout);
>> fputs(_(" -d, --delay <secs> delay updates\n"), stdout);
>> + fputs(_(" -i, --input <file> read data from file\n"), stdout);
>> fputs(_(" -n, --number <number> the maximum number of iterations\n"), stdout);
>> fputs(_(" -o, --output <list> define which output columns to use\n"), stdout);
>> fputs(_(" -s, --sort <column> specify sort column\n"), stdout);
>> @@ -325,6 +329,7 @@ static void parse_args( struct irqtop_ctl *ctl,
>> {"cpu-stat", required_argument, NULL, 'c'},
>> {"cpu-list", required_argument, NULL, 'C'},
>> {"delay", required_argument, NULL, 'd'},
>> + {"input", required_argument, NULL, 'i'},
>> {"number", required_argument, NULL, 'n'},
>> {"sort", required_argument, NULL, 's'},
>> {"output", required_argument, NULL, 'o'},
>> @@ -336,7 +341,7 @@ static void parse_args( struct irqtop_ctl *ctl,
>> };
>> int o;
>> - while ((o = getopt_long(argc, argv, "bc:C:d:n:o:s:St:hV", longopts, NULL)) != -1) {
>> + while ((o = getopt_long(argc, argv, "bc:C:d:i:n:o:s:St:hV", longopts, NULL)) != -1) {
>> switch (o) {
>> case 'b':
>> ctl->batch = true;
>> @@ -376,6 +381,13 @@ static void parse_args( struct irqtop_ctl *ctl,
>> ctl->timer.it_value = ctl->timer.it_interval;
>> }
>> break;
>> + case 'i':
>> + ctl->input = strdup(optarg);
>> + if (!ctl->input)
>> + err_oom();
>> + ctl->number = 1;
>> + ctl->batch = true;
>> + break;
>> case 'n':
>> ctl->number = str2num_or_err(optarg, 10,
>> _("failed to parse number argument"),
>> @@ -402,6 +414,15 @@ static void parse_args( struct irqtop_ctl *ctl,
>> }
>> }
>> + if (ctl->input == NULL) {
>> + if (ctl->softirq == 1)
>> + ctl->input = strdup(_PATH_PROC_SOFTIRQS);
>> + else
>> + ctl->input = strdup(_PATH_PROC_INTERRUPTS);
>> + if (!ctl->input)
>> + err_oom();
>> + }
>> +
>> /* default */
>> if (!out->ncolumns) {
>> out->columns[out->ncolumns++] = COL_IRQ;
>> @@ -453,6 +474,7 @@ int main(int argc, char **argv)
>> free_irqstat(ctl.prev_stat);
>> free(ctl.hostname);
>> + free(ctl.input);
>> cpuset_free(ctl.cpuset);
>> if (ctl.batch == false) {
>> diff --git a/sys-utils/lsirq.1.adoc b/sys-utils/lsirq.1.adoc
>> index 02aea16b3..dd265710c 100644
>> --- a/sys-utils/lsirq.1.adoc
>> +++ b/sys-utils/lsirq.1.adoc
>> @@ -25,6 +25,9 @@ The default output is subject to change. So whenever possible, you should avoid
>> *-n*, *--noheadings*::
>> Don't print headings.
>> +*-i*, *--input* _file_::
>> +Read data from _file_ (Which was created by other tools, e.g. sosreport).
>> +
>> *-o*, *--output* _list_::
>> Specify which output columns to print. Use *--help* to get a list of all supported columns. The default list of columns may be extended if list is specified in the format _+list_.
>> diff --git a/sys-utils/lsirq.c b/sys-utils/lsirq.c
>> index e31addaf5..45d542919 100644
>> --- a/sys-utils/lsirq.c
>> +++ b/sys-utils/lsirq.c
>> @@ -29,16 +29,17 @@
>> #include "optutils.h"
>> #include "strutils.h"
>> #include "xalloc.h"
>> +#include "pathnames.h"
>> #include "irq-common.h"
>> -static int print_irq_data(struct irq_output *out,
>> +static int print_irq_data(const char *input_file, struct irq_output *out,
>> int softirq, unsigned long threshold,
>> size_t setsize, cpu_set_t *cpuset)
>> {
>> struct libscols_table *table;
>> - table = get_scols_table(out, NULL, NULL, softirq, threshold, setsize, cpuset);
>> + table = get_scols_table(input_file, out, NULL, NULL, softirq, threshold, setsize, cpuset);
>> if (!table)
>> return -1;
>> @@ -58,6 +59,7 @@ static void __attribute__((__noreturn__)) usage(void)
>> fputs(USAGE_OPTIONS, stdout);
>> fputs(_(" -J, --json use JSON output format\n"), stdout);
>> fputs(_(" -P, --pairs use key=\"value\" output format\n"), stdout);
>> + fputs(_(" -i, --input read data from input file\n"), stdout);
>> fputs(_(" -n, --noheadings don't print headings\n"), stdout);
>> fputs(_(" -o, --output <list> define which output columns to use\n"), stdout);
>> fputs(_(" -s, --sort <column> specify sort column\n"), stdout);
>> @@ -82,6 +84,7 @@ int main(int argc, char **argv)
>> static const struct option longopts[] = {
>> {"sort", required_argument, NULL, 's'},
>> {"noheadings", no_argument, NULL, 'n'},
>> + {"input", required_argument, NULL, 'i'},
>> {"output", required_argument, NULL, 'o'},
>> {"threshold", required_argument, NULL, 't'},
>> {"cpu-list", required_argument, NULL, 'C'},
>> @@ -103,10 +106,11 @@ int main(int argc, char **argv)
>> cpu_set_t *cpuset = NULL;
>> size_t setsize = 0;
>> int softirq = 0;
>> + char *input = NULL;
>> setlocale(LC_ALL, "");
>> - while ((c = getopt_long(argc, argv, "no:s:t:C:ShJPV", longopts, NULL)) != -1) {
>> + while ((c = getopt_long(argc, argv, "i:no:s:t:C:ShJPV", longopts, NULL)) != -1) {
>> err_exclusive_options(c, longopts, excl, excl_st);
>> switch (c) {
>> @@ -116,6 +120,11 @@ int main(int argc, char **argv)
>> case 'P':
>> out.pairs = 1;
>> break;
>> + case 'i':
>> + input = strdup(optarg);
>> + if (!input)
>> + err_oom();
>> + break;
>> case 'n':
>> out.no_headings = 1;
>> break;
>> @@ -157,6 +166,15 @@ int main(int argc, char **argv)
>> }
>> }
>> + if (input == NULL) {
>> + if (softirq == 1)
>> + input = strdup(_PATH_PROC_SOFTIRQS);
>> + else
>> + input = strdup(_PATH_PROC_INTERRUPTS);
>> + if (!input)
>> + err_oom();
>> + }
>> +
>> /* default */
>> if (!out.ncolumns) {
>> out.columns[out.ncolumns++] = COL_IRQ;
>> @@ -171,8 +189,10 @@ int main(int argc, char **argv)
>> irq_column_name_to_id) < 0)
>> exit(EXIT_FAILURE);
>> - if (print_irq_data(&out, softirq, threshold, setsize, cpuset) < 0)
>> + if (print_irq_data(input, &out, softirq, threshold, setsize, cpuset) < 0)
>> return EXIT_FAILURE;
>> + free(input);
>> +
>> return EXIT_SUCCESS;
>> }
>
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 2/3] irqtop: add max iteration support
2025-02-27 18:32 ` Joe Jin
@ 2025-02-28 8:19 ` Karel Zak
0 siblings, 0 replies; 17+ messages in thread
From: Karel Zak @ 2025-02-28 8:19 UTC (permalink / raw)
To: Joe Jin; +Cc: Zhenwei Pi, Sami Kerola, util-linux
On Thu, Feb 27, 2025 at 10:32:11AM GMT, Joe Jin wrote:
> On 2/27/25 01:28, Karel Zak wrote:
> > On Wed, Feb 26, 2025 at 08:49:15PM GMT, Joe Jin wrote:
> >> enum irqtop_cpustat_mode cpustat_mode;
> >> + int64_t number;
> > Can we find a better name for the variable and the option?
> >
> > --nloops
> > --repeat
>
> How about of "--iter"?
Yes, better than --number :-)
Karel
--
Karel Zak <kzak@redhat.com>
http://karelzak.blogspot.com
^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2025-02-28 8:19 UTC | newest]
Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-02-27 4:49 [PATCH 0/3] irqtop,lsirq: Miscellaneous enhancements Joe Jin
2025-02-27 4:49 ` [PATCH 1/3] irqtop: add batch mode support Joe Jin
2025-02-27 9:25 ` Karel Zak
2025-02-27 18:30 ` Joe Jin
2025-02-28 1:34 ` zhenwei pi
2025-02-28 4:24 ` Joe Jin
2025-02-27 4:49 ` [PATCH 2/3] irqtop: add max iteration support Joe Jin
2025-02-27 9:28 ` Karel Zak
2025-02-27 18:32 ` Joe Jin
2025-02-28 8:19 ` Karel Zak
2025-02-27 4:49 ` [PATCH 3/3] lsirq,irqtop: add support for reading data from given file Joe Jin
2025-02-27 9:30 ` Karel Zak
2025-02-27 18:33 ` Joe Jin
2025-02-28 1:41 ` zhenwei pi
2025-02-28 4:25 ` Joe Jin
2025-02-27 7:36 ` [PATCH 0/3] irqtop,lsirq: Miscellaneous enhancements Sami Kerola
2025-02-27 19:49 ` Joe Jin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox