* [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
* 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 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 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 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
* [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
* 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 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 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
* [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 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 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 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 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 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 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
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