Util-Linux package development
 help / color / mirror / Atom feed
* Re: [PATCH 3/3] lsirq,irqtop: add support for reading data from given file
From: zhenwei pi @ 2025-02-28  1:41 UTC (permalink / raw)
  To: Joe Jin, Karel Zak, Sami Kerola; +Cc: util-linux
In-Reply-To: <20250227044916.89925-4-joe.jin@oracle.com>

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

* Re: [PATCH 1/3] irqtop: add batch mode support
From: Joe Jin @ 2025-02-28  4:24 UTC (permalink / raw)
  To: zhenwei pi, Karel Zak, Sami Kerola; +Cc: util-linux
In-Reply-To: <75000d2c-8f17-46b2-aabc-9cc5a3c97e2e@bytedance.com>

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

* Re: [PATCH 3/3] lsirq,irqtop: add support for reading data from given file
From: Joe Jin @ 2025-02-28  4:25 UTC (permalink / raw)
  To: zhenwei pi, Karel Zak, Sami Kerola; +Cc: util-linux
In-Reply-To: <da045963-e7d3-4edf-b3b9-783483a8920d@bytedance.com>

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

* Re: [PATCH 2/3] irqtop: add max iteration support
From: Karel Zak @ 2025-02-28  8:19 UTC (permalink / raw)
  To: Joe Jin; +Cc: Zhenwei Pi, Sami Kerola, util-linux
In-Reply-To: <df430d5e-3973-4553-80ee-1ae3bb868a22@oracle.com>

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

* [PATCH V2 0/4] irqtop,lsirq: Miscellaneous enhancements
From: Joe Jin @ 2025-02-28 16:13 UTC (permalink / raw)
  To: Karel Zak, Zhenwei Pi, Sami Kerola; +Cc: util-linux, Joe Jin

This patchset add below new options for irqtop:
 '-b|--batch' : Batch mode
 '-n|--iter'  : Specifies the maximum number of iterations
 '-J|--json'  : Json ouput format

Add below for lsirq:
 '-i|--input' : Read data from file

v2:
  - Removed macro irqtop_batch_mode.
  - Replaced macro irqtop_printf() to inline function
  - Changed option '--number' to '--iter'
  - Replace strdup() to xstrdup()
  - Added json output format for irqtop.
  - Remove irqtop input file support.

Joe Jin (4):
  irqtop: add batch mode support
  irqtop: add max iteration support
  irqtop: support json output format
  lsirq: add support for reading data from given file

 bash-completion/irqtop  |  12 +++-
 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      | 124 +++++++++++++++++++++++++++++++---------
 sys-utils/lsirq.1.adoc  |   3 +
 sys-utils/lsirq.c       |  24 ++++++--
 8 files changed, 155 insertions(+), 43 deletions(-)

-- 
2.43.5


^ permalink raw reply

* [PATCH V2 1/4] irqtop: add batch mode support
From: Joe Jin @ 2025-02-28 16:13 UTC (permalink / raw)
  To: Karel Zak, Zhenwei Pi, Sami Kerola; +Cc: util-linux, Joe Jin
In-Reply-To: <20250228161334.82987-1-joe.jin@oracle.com>

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>
Cc: Karel Zak <kzak@redhat.com>
---
 bash-completion/irqtop  |  6 ++-
 sys-utils/irqtop.1.adoc |  3 ++
 sys-utils/irqtop.c      | 89 ++++++++++++++++++++++++++++++-----------
 3 files changed, 73 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..81a137be0 100644
--- a/sys-utils/irqtop.c
+++ b/sys-utils/irqtop.c
@@ -83,10 +83,32 @@ struct irqtop_ctl {
 	cpu_set_t *cpuset;
 
 	enum irqtop_cpustat_mode cpustat_mode;
+	bool	batch;
 	bool	request_exit,
 		softirq;
 };
 
+static inline int irqtop_printf(struct irqtop_ctl *ctl, const char *fmt, ...)
+{
+	int ret = 0;
+	va_list args;
+
+	if (!ctl)
+		return -1;
+
+	va_start(args, fmt);
+	if (ctl->batch)
+		ret = vprintf(fmt, args);
+	else
+		ret = vw_printw(ctl->win, fmt, args);
+	va_end(args);
+
+	if (!ctl->batch && ret == OK)
+		wrefresh(ctl->win);
+
+	return ret;
+}
+
 /* user's input parser */
 static void parse_input(struct irqtop_ctl *ctl, struct irq_output *out, char c)
 {
@@ -128,16 +150,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 (!ctl->batch)
+		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 +174,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 (!ctl->batch)
+			attron(A_REVERSE);
+		irqtop_printf(ctl, "%s\n", data);
+		if (!ctl->batch)
+			attroff(A_REVERSE);
 		data = p + 1;
 	}
 
-	wprintw(ctl->win, "%s", data);
+	irqtop_printf(ctl, "%s\n\n", data);
 	free(data0);
 
 	/* clean up */
@@ -212,7 +239,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 (!ctl->batch)
+		refresh();
 
 	while (!ctl->request_exit) {
 		const ssize_t nr_events = epoll_wait(efd, events, MAX_EVENTS, -1);
@@ -227,10 +255,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 (!ctl->batch) {
+						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 +275,8 @@ static int event_loop(struct irqtop_ctl *ctl, struct irq_output *out)
 			} else
 				abort();
 			retval |= update_screen(ctl, out);
-			refresh();
+			if (!ctl->batch)
+				refresh();
 		}
 	}
 	return retval;
@@ -260,6 +291,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 +323,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 +337,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 = 1;
+			break;
 		case 'c':
 			if (!strcmp(optarg, "auto"))
 				ctl->cpustat_mode = IRQTOP_CPUSTAT_AUTO;
@@ -394,16 +430,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) {
+		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 +450,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) {
+		if (is_tty)
+			tcsetattr(STDIN_FILENO, TCSAFLUSH, &saved_tty);
+
+		delwin(ctl.win);
+		endwin();
+	}
 
 	return EXIT_SUCCESS;
 }
-- 
2.43.5


^ permalink raw reply related

* [PATCH V2 2/4] irqtop: add max iteration support
From: Joe Jin @ 2025-02-28 16:13 UTC (permalink / raw)
  To: Karel Zak, Zhenwei Pi, Sami Kerola; +Cc: util-linux, Joe Jin
In-Reply-To: <20250228161334.82987-1-joe.jin@oracle.com>

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>
Cc: Karel Zak <kzak@redhat.com>
---
 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..d18ef99bb 100644
--- a/bash-completion/irqtop
+++ b/bash-completion/irqtop
@@ -22,6 +22,10 @@ _irqtop_module()
 			COMPREPLY=( $(compgen -W "secs" -- $cur) )
 			return 0
 			;;
+		'-n'|'--iter')
+			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
+		--iter
 		--sort
 		--output
 		--softirq
diff --git a/sys-utils/irqtop.1.adoc b/sys-utils/irqtop.1.adoc
index e81f4fbb6..75930f5cf 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*, *--iter* _number_::
+Specifies the maximum 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 81a137be0..17c7d72cb 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	iter;
 	bool	batch;
 	bool	request_exit,
 		softirq;
@@ -190,6 +191,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->iter > 0) {
+		ctl->iter--;
+		if (ctl->iter == 0)
+			ctl->request_exit = 1;
+	}
 	return 0;
 }
 
@@ -295,6 +302,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, --iter <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);
@@ -327,6 +335,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'},
+		{"iter", required_argument, NULL, 'n'},
 		{"sort", required_argument, NULL, 's'},
 		{"output", required_argument, NULL, 'o'},
 		{"softirq", no_argument, NULL, 'S'},
@@ -337,7 +346,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 = 1;
@@ -377,6 +386,11 @@ static void parse_args(	struct irqtop_ctl *ctl,
 				ctl->timer.it_value = ctl->timer.it_interval;
 			}
 			break;
+		case 'n':
+			ctl->iter = str2num_or_err(optarg, 10,
+					_("failed to parse iter argument"),
+					0, INT_MAX);
+			break;
 		case 's':
 			set_sort_func_by_name(out, optarg);
 			break;
@@ -423,7 +437,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},
+		.iter = -1
 	};
 
 	setlocale(LC_ALL, "");
-- 
2.43.5


^ permalink raw reply related

* [PATCH V2 3/4] irqtop: support json output format
From: Joe Jin @ 2025-02-28 16:13 UTC (permalink / raw)
  To: Karel Zak, Zhenwei Pi, Sami Kerola; +Cc: util-linux, Joe Jin
In-Reply-To: <20250228161334.82987-1-joe.jin@oracle.com>

Signed-off-by: Joe Jin <joe.jin@oracle.com>
Cc: Zhenwei Pi <pizhenwei@bytedance.com>
Cc: Sami Kerola <kerolasa@iki.fi>
Cc: Karel Zak <kzak@redhat.com>
---
 bash-completion/irqtop  | 1 +
 sys-utils/irqtop.1.adoc | 3 +++
 sys-utils/irqtop.c      | 8 +++++++-
 3 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/bash-completion/irqtop b/bash-completion/irqtop
index d18ef99bb..5faf122e5 100644
--- a/bash-completion/irqtop
+++ b/bash-completion/irqtop
@@ -48,6 +48,7 @@ _irqtop_module()
 			;;
 	esac
 	OPTS="	--batch
+		--json
 		--cpu-stat
 		--cpu-list
 		--delay
diff --git a/sys-utils/irqtop.1.adoc b/sys-utils/irqtop.1.adoc
index 75930f5cf..880ee1906 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.
 
+*-J*, *--json*::
+Use JSON output format. irqtop will run in batch mode.
+
 *-n*, *--iter* _number_::
 Specifies the maximum iterations before quitting.
 
diff --git a/sys-utils/irqtop.c b/sys-utils/irqtop.c
index 17c7d72cb..48b65201f 100644
--- a/sys-utils/irqtop.c
+++ b/sys-utils/irqtop.c
@@ -302,6 +302,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(_(" -J, --json  use JSON output format (will run in batch mode)\n"), stdout);
 	fputs(_(" -n, --iter <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);
@@ -336,6 +337,7 @@ static void parse_args(	struct irqtop_ctl *ctl,
 		{"cpu-list", required_argument, NULL, 'C'},
 		{"delay", required_argument, NULL, 'd'},
 		{"iter", required_argument, NULL, 'n'},
+		{"json", no_argument, NULL, 'J'},
 		{"sort", required_argument, NULL, 's'},
 		{"output", required_argument, NULL, 'o'},
 		{"softirq", no_argument, NULL, 'S'},
@@ -346,7 +348,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:Jn:o:s:St:hV", longopts, NULL)) != -1) {
 		switch (o) {
 		case 'b':
 			ctl->batch = 1;
@@ -386,6 +388,10 @@ static void parse_args(	struct irqtop_ctl *ctl,
 				ctl->timer.it_value = ctl->timer.it_interval;
 			}
 			break;
+		case 'J':
+			out->json = 1;
+			ctl->batch = 1;
+			break;
 		case 'n':
 			ctl->iter = str2num_or_err(optarg, 10,
 					_("failed to parse iter argument"),
-- 
2.43.5


^ permalink raw reply related

* [PATCH V2 4/4] lsirq: add support for reading data from given file
From: Joe Jin @ 2025-02-28 16:13 UTC (permalink / raw)
  To: Karel Zak, Zhenwei Pi, Sami Kerola; +Cc: util-linux, Joe Jin
In-Reply-To: <20250228161334.82987-1-joe.jin@oracle.com>

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>
Cc: Karel Zak <kzak@redhat.com>
---
 bash-completion/lsirq  |  4 ++++
 sys-utils/irq-common.c | 19 +++++++++----------
 sys-utils/irq-common.h |  3 ++-
 sys-utils/irqtop.c     | 12 ++++++++++--
 sys-utils/lsirq.1.adoc |  3 +++
 sys-utils/lsirq.c      | 24 ++++++++++++++++++++----
 6 files changed, 48 insertions(+), 17 deletions(-)

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.c b/sys-utils/irqtop.c
index 48b65201f..6d001cb10 100644
--- a/sys-utils/irqtop.c
+++ b/sys-utils/irqtop.c
@@ -130,10 +130,18 @@ static int update_screen(struct irqtop_ctl *ctl, struct irq_output *out)
 	struct irq_stat *stat;
 	time_t now = time(NULL);
 	char timestr[64], *data, *data0, *p;
+	char *input_file;
 
 	/* make irqs table */
-	table = get_scols_table(out, ctl->prev_stat, &stat, ctl->softirq,
-				ctl->threshold, ctl->setsize, ctl->cpuset);
+	if (ctl->softirq)
+		input_file = xstrdup(_PATH_PROC_SOFTIRQS);
+	else
+		input_file = xstrdup(_PATH_PROC_INTERRUPTS);
+
+	table = get_scols_table(input_file, out, ctl->prev_stat, &stat,
+				ctl->softirq, ctl->threshold, ctl->setsize,
+				ctl->cpuset);
+	free(input_file);
 	if (!table) {
 		ctl->request_exit = 1;
 		return 1;
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..fa2dcaaf3 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_file = 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,9 @@ int main(int argc, char **argv)
 		case 'P':
 			out.pairs = 1;
 			break;
+		case 'i':
+			input_file = xstrdup(optarg);
+			break;
 		case 'n':
 			out.no_headings = 1;
 			break;
@@ -157,6 +164,13 @@ int main(int argc, char **argv)
 		}
 	}
 
+	if (input_file == NULL) {
+		if (softirq == 1)
+			input_file = xstrdup(_PATH_PROC_SOFTIRQS);
+		else
+			input_file = xstrdup(_PATH_PROC_INTERRUPTS);
+	}
+
 	/* default */
 	if (!out.ncolumns) {
 		out.columns[out.ncolumns++] = COL_IRQ;
@@ -171,8 +185,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_file, &out, softirq, threshold, setsize, cpuset) < 0)
 		return EXIT_FAILURE;
 
+	free(input_file);
+
 	return EXIT_SUCCESS;
 }
-- 
2.43.5


^ permalink raw reply related

* Re: [PATCH V2 2/4] irqtop: add max iteration support
From: zhenwei pi @ 2025-03-03  9:39 UTC (permalink / raw)
  To: Joe Jin, Karel Zak, Sami Kerola; +Cc: util-linux
In-Reply-To: <20250228161334.82987-3-joe.jin@oracle.com>



On 3/1/25 00:13, Joe Jin wrote:
> 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>
> Cc: Karel Zak <kzak@redhat.com>
> ---
>   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..d18ef99bb 100644
> --- a/bash-completion/irqtop
> +++ b/bash-completion/irqtop
> @@ -22,6 +22,10 @@ _irqtop_module()
>   			COMPREPLY=( $(compgen -W "secs" -- $cur) )
>   			return 0
>   			;;
> +		'-n'|'--iter')
> +			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
> +		--iter
>   		--sort
>   		--output
>   		--softirq
> diff --git a/sys-utils/irqtop.1.adoc b/sys-utils/irqtop.1.adoc
> index e81f4fbb6..75930f5cf 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*, *--iter* _number_::
> +Specifies the maximum 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 81a137be0..17c7d72cb 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	iter;
>   	bool	batch;
>   	bool	request_exit,
>   		softirq;
> @@ -190,6 +191,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->iter > 0) {
> +		ctl->iter--;
> +		if (ctl->iter == 0)
> +			ctl->request_exit = 1;
> +	}
>   	return 0;
>   }

If ctl->iter is initialized as int64_max, then we have codes like:

if (--ctl->iter == 0) {
     ctl->request_exit = 1;
}

>   
> @@ -295,6 +302,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, --iter <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);
> @@ -327,6 +335,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'},
> +		{"iter", required_argument, NULL, 'n'},
>   		{"sort", required_argument, NULL, 's'},
>   		{"output", required_argument, NULL, 'o'},
>   		{"softirq", no_argument, NULL, 'S'},
> @@ -337,7 +346,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 = 1;
> @@ -377,6 +386,11 @@ static void parse_args(	struct irqtop_ctl *ctl,
>   				ctl->timer.it_value = ctl->timer.it_interval;
>   			}
>   			break;
> +		case 'n':
> +			ctl->iter = str2num_or_err(optarg, 10,
> +					_("failed to parse iter argument"),
> +					0, INT_MAX);
> +			break;
>   		case 's':
>   			set_sort_func_by_name(out, optarg);
>   			break;
> @@ -423,7 +437,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},
> +		.iter = -1
>   	};
>   
>   	setlocale(LC_ALL, "");


^ permalink raw reply

* Re: [PATCH V2 0/4] irqtop,lsirq: Miscellaneous enhancements
From: Karel Zak @ 2025-03-03 10:16 UTC (permalink / raw)
  To: Joe Jin; +Cc: Zhenwei Pi, Sami Kerola, util-linux
In-Reply-To: <20250228161334.82987-1-joe.jin@oracle.com>

On Fri, Feb 28, 2025 at 08:13:30AM GMT, Joe Jin wrote:
> This patchset add below new options for irqtop:
>  '-b|--batch' : Batch mode
>  '-n|--iter'  : Specifies the maximum number of iterations
>  '-J|--json'  : Json ouput format
> 
> Add below for lsirq:
>  '-i|--input' : Read data from file
> 
> v2:
>   - Removed macro irqtop_batch_mode.
>   - Replaced macro irqtop_printf() to inline function
>   - Changed option '--number' to '--iter'
>   - Replace strdup() to xstrdup()
>   - Added json output format for irqtop.
>   - Remove irqtop input file support.
> 
> Joe Jin (4):
>   irqtop: add batch mode support
>   irqtop: add max iteration support
>   irqtop: support json output format
>   lsirq: add support for reading data from given file
> 
>  bash-completion/irqtop  |  12 +++-
>  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      | 124 +++++++++++++++++++++++++++++++---------
>  sys-utils/lsirq.1.adoc  |   3 +
>  sys-utils/lsirq.c       |  24 ++++++--
>  8 files changed, 155 insertions(+), 43 deletions(-)

Thanks for the update. I have created a PR
(https://github.com/util-linux/util-linux/pull/3435) to test it with
CI tests.

    Karel

-- 
 Karel Zak  <kzak@redhat.com>
 http://karelzak.blogspot.com


^ permalink raw reply

* [PATCH] column: replace a mistaken word in an error message
From: Benno Schulenberg @ 2025-03-03 10:21 UTC (permalink / raw)
  To: util-linux

Signed-off-by: Benno Schulenberg <bensberg@telfort.nl>
---
 text-utils/column.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/text-utils/column.c b/text-utils/column.c
index 85a303455..470c2729a 100644
--- a/text-utils/column.c
+++ b/text-utils/column.c
@@ -1065,7 +1065,7 @@ int main(int argc, char **argv)
 			free(ctl.input_separator);
 			ctl.input_separator = mbs_to_wcs(optarg);
 			if (!ctl.input_separator)
-				err(EXIT_FAILURE, _("failed to use input separator"));
+				err(EXIT_FAILURE, _("failed to parse input separator"));
 			ctl.greedy = 0;
 			break;
 		case 'T':
-- 
2.48.1


^ permalink raw reply related

* Re: [PATCH] column: replace a mistaken word in an error message
From: Karel Zak @ 2025-03-03 11:32 UTC (permalink / raw)
  To: Benno Schulenberg; +Cc: util-linux
In-Reply-To: <20250303102137.4020-1-bensberg@telfort.nl>

On Mon, Mar 03, 2025 at 11:21:37AM GMT, Benno Schulenberg wrote:
>  text-utils/column.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

Applied, thanks.

Benno, I'd like to release -rc2 ASAP. This means passing the task to
the translators. Do you think we need more time before rc2 to clean up
the strings?

The cleanup can continue in the master branch, but the changes will
not go into v2.41. I have no problem with this, but I'd like to be
considerate of your work and the translators.

    Karel

-- 
 Karel Zak  <kzak@redhat.com>
 http://karelzak.blogspot.com


^ permalink raw reply

* Re: [PATCH] column: replace a mistaken word in an error message
From: Benno Schulenberg @ 2025-03-03 12:12 UTC (permalink / raw)
  To: Karel Zak; +Cc: util-linux
In-Reply-To: <mtr3urghiu2ezk2uprqwuvkgfxktdb3md5vc4zwbidgxeckzny@2n7vycofqgom>


[-- Attachment #1.1: Type: text/plain, Size: 649 bytes --]


Op 03-03-2025 om 12:32 schreef Karel Zak:
> Benno, I'd like to release -rc2 ASAP. This means passing the task to
> the translators. Do you think we need more time before rc2 to clean up
> the strings?

No, no extra time needed.  You can go ahead with -rc2.

(I still have 900 strings to look at, but won't have much
time this week, and can't look further ahead than that.)

> The cleanup can continue in the master branch, but the changes will
> not go into v2.41. I have no problem with this, but I'd like to be
> considerate of your work and the translators.

Thanks.  As you say, any other cleanup will be for 2.42.


Benno


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

^ permalink raw reply

* Re: [PATCH] agetty: Implement netlink based IP address lookup
From: Karel Zak @ 2025-03-03 14:49 UTC (permalink / raw)
  To: Stanislav Brabec; +Cc: util-linux
In-Reply-To: <20250216212450.61706-1-sbrabec@suse.cz>

On Sun, Feb 16, 2025 at 10:24:50PM GMT, Stanislav Brabec wrote:
> The new netlink based IP address lokup implements a new issue file escape \i.
> This lookup is based on netlink messages only. It evaluates all addresses
> reported in the netlink messages and it attempts to print only the best of them.
> As it is not possible to discriminate the "best" IP address, it reports all
> reasonably usable addresses.

I believe your code is a good start.

> Migrate \4 and \6 from getifaddrs() to netlink as well, and then completely drop
> getifaddrs() based code.

Yes, but it would be nice to make the code more readable and extendable :-)

My suggestion:

- Move the code to lib/netlink-ifaces.c.

- Add #ifdef TEST_PROGRAM with test main() and test_netlink to
  lib/Makemodule.am (see for example lib/linux_version.c).

- Use include/debug.h and UL_NETLINK_DEBUG= environment variable (see
  lib/loopdev.c, LOOPDEV_DEBUG_* and loopdev_init_debug()).

- Use a prefix for public functions (e.g., ul_iface_*).

- Create a set of small functions for basic operations:
  - Add and remove interface (e.g., add_interface()).
  - Add and remove address.
  - Get the best address.

I also suggest using include/list.h for the lists, but you might find
it challenging at first. Ideally, define next() functions for while()
loops (e.g., ul_iface_next_interface() and ul_iface_next_addr()). See
for example libfdisk/src/table.c:fdisk_table_next_partition().
However, I'll understand if you think it's overkill.

The include/list.h provides a sort function, so it would be possible
to sort the lists by "quality", making the first address in the list
the best.

> It could be useful to implement:
> - configurable limit for the maximum number of interfaces that could be
>   reported.

I believe the limit could be quite large by default (512?) since it's
just one malloc() for each address.

> - the interface regexp match

Yes, just another small function ul_iface_match_interface(), and if it
will be sorted than you get the best one :-)

\4{~eth[0-9]} or \4{match="~eth[0-9]"} if you want to support more
options in the { }.

 - agetty already supports \foo{ } arguments, see get_escape_argument()
 - lib/strutils.c:ul_optstr_next() can parse options list  {a="aaa",b="bbb"}

> - an interface template for fine tuning of the output

You can introduce printf()-like \4{format="%iface:%addr} (like git-log)

> - better control over the output: e. g. disable printing of IPv4 or IPv6
>   addresses, disable printing of temporary addresses or link-local addresses
> - cross-protocol checks: e. g. disable reporting of link-local IPv6 address for
>   an IPv4-only interface

:-)

> The new network comparison code could potentially render obsolete string based
> issue comparison (implemented in 6522d88). There are ifaces_list_change_4 and
> ifaces_list_change_6 variables ready for this purpose.

Hmm... the global variables used deeply within the netlink message
parser do not look very elegant. Maybe introduce a separate struct,
ul_ifaces_status, and use it as a global variable in agetty.c,
then call process_netlink_msg() with this struct as an argument.

> +struct ip_quality_item {
> +	enum ip_quality_item_value quality;
> +	int len;
> +	__u32 ifa_valid; /* IP addres lifetime */

uint32_t if possible ;-)

> +	struct ip_quality_item *next;
> +	char addr[];
> +};
> +struct iface_quality_item {
> +	__u32 ifa_index;
> +	struct ip_quality_item *ip_quality_list_4;
> +	struct ip_quality_item *ip_quality_list_6;
> +	struct iface_quality_item *next;
> +};
> +static struct iface_quality_item *ifaces_list = NULL;
> +bool ifaces_list_change_4;
> +bool ifaces_list_change_6;
> +bool ifaces_skip_dump = false;

Do we need the _quality_ in the sctruct names? What about ul_iface and
ul_iface_addr ?

 ...

> +			debug_net("+ allocating new interface\n");
> +			ifaceq = malloc(sizeof(struct iface_quality_item));

 if (!ifaceq)
    return;

> +			ifaceq->ifa_index = ifaddr->ifa_index;
> +			ifaceq->ip_quality_list_4 = NULL;
> +			ifaceq->ip_quality_list_6 = NULL;
> +			ifaceq->next = NULL;
> +			*ifaceq_prev_next = ifaceq;


process_netlink_msg_part() will be simpler and more readable if you
move the basic tasks to small functions like add_interface() :-)

> +		} else {
> +			/* Should never happen */
> +			debug_net("- interface not found\n");
> +			return;
> +		}
> +	}
> +	if (family == AF_INET) {
> +		ipq_prev_next = &(ifaceq->ip_quality_list_4);
> +		ifaces_list_change = &ifaces_list_change_4;
> +	}
> +	if (family == AF_INET6) {
> +		ipq_prev_next = &(ifaceq->ip_quality_list_6);
> +		ifaces_list_change = &ifaces_list_change_6;
> +	}

I guess static analyzers won't like this part; ipq_prev_next is
uninitialized if the family is something else.

 
    Karel

-- 
 Karel Zak  <kzak@redhat.com>
 http://karelzak.blogspot.com


^ permalink raw reply

* Re: [PATCH] agetty: Implement netlink based IP address lookup
From: Stanislav Brabec @ 2025-03-04  0:01 UTC (permalink / raw)
  To: Karel Zak; +Cc: util-linux
In-Reply-To: <tnzflf25amkje3xdgf7avon5smn3xlbng44xxegwpsjjqp4tvy@4vfjbliaoiq3>

Karel Zak wrote:
> On Sun, Feb 16, 2025 at 10:24:50PM GMT, Stanislav Brabec wrote:
>
> My suggestion:
>
> - Move the code to lib/netlink-ifaces.c.
>
> - Add #ifdef TEST_PROGRAM with test main() and test_netlink to
>    lib/Makemodule.am (see for example lib/linux_version.c).
>
> - Use include/debug.h and UL_NETLINK_DEBUG= environment variable (see
>    lib/loopdev.c, LOOPDEV_DEBUG_* and loopdev_init_debug()).
>
> - Use a prefix for public functions (e.g., ul_iface_*).
Makes sense.
> - Create a set of small functions for basic operations:
>    - Add and remove interface (e.g., add_interface()).
>    - Add and remove address.
>    - Get the best address.
It could be done. Just add and delete interface shares lot of code, so 
it could be one function.
> I also suggest using include/list.h for the lists, but you might find
> it challenging at first. Ideally, define next() functions for while()
> loops (e.g., ul_iface_next_interface() and ul_iface_next_addr()). See
> for example libfdisk/src/table.c:fdisk_table_next_partition().
> However, I'll understand if you think it's overkill.
>
> The include/list.h provides a sort function, so it would be possible
> to sort the lists by "quality", making the first address in the list
> the best.
Sounds good. I'll look at it.
>> It could be useful to implement:
>> - configurable limit for the maximum number of interfaces that could be
>>    reported.
> I believe the limit could be quite large by default (512?) since it's
> just one malloc() for each address.
Not for agetty. 512 interfaces surely ovefloods all terminals screen and 
maybe even scrollback memory.
And if you have 512 network interfaces (e. g. modem servers at DSL 
providers), then you probably will not want to report all those 
interfaces IP addresses. But yes, the code could simply support it.

>> - the interface regexp match
> Yes, just another small function ul_iface_match_interface(), and if it
> will be sorted than you get the best one :-)
>
> \4{~eth[0-9]} or \4{match="~eth[0-9]"} if you want to support more
> options in the { }.
Sounds like a good syntax.
>   - agetty already supports \foo{ } arguments, see get_escape_argument()
>   - lib/strutils.c:ul_optstr_next() can parse options list  {a="aaa",b="bbb"}
I see.
>> - an interface template for fine tuning of the output
> You can introduce printf()-like \4{format="%iface:%addr} (like git-log)
>
>> - better control over the output: e. g. disable printing of IPv4 or IPv6
>>    addresses, disable printing of temporary addresses or link-local addresses
>> - cross-protocol checks: e. g. disable reporting of link-local IPv6 address for
>>    an IPv4-only interface
> :-)
>
>> The new network comparison code could potentially render obsolete string based
>> issue comparison (implemented in 6522d88). There are ifaces_list_change_4 and
>> ifaces_list_change_6 variables ready for this purpose.
> Hmm... the global variables used deeply within the netlink message
> parser do not look very elegant. Maybe introduce a separate struct,
> ul_ifaces_status, and use it as a global variable in agetty.c,
> then call process_netlink_msg() with this struct as an argument.
>
>> +struct ip_quality_item {
>> +	enum ip_quality_item_value quality;
>> +	int len;
>> +	__u32 ifa_valid; /* IP addres lifetime */
> uint32_t if possible ;-)
The kernel ifa_valid is declared as __u32. If uint32_t is always equal, 
I'll use it.
> Do we need the _quality_ in the sctruct names? What about ul_iface and
> ul_iface_addr ?
> process_netlink_msg_part() will be simpler and more readable if you
> move the basic tasks to small functions like add_interface() :-)
Actually, if we introduce generic library functions, then other 
consumers may want to do something else than quality evaluation.
I can imagine a generic structure with pointer to custom data. And the 
function will have a callback that will perform the needed operation.

>> +		} else {
>> +			/* Should never happen */
>> +			debug_net("- interface not found\n");
>> +			return;
>> +		}
>> +	}
>> +	if (family == AF_INET) {
>> +		ipq_prev_next = &(ifaceq->ip_quality_list_4);
>> +		ifaces_list_change = &ifaces_list_change_4;
>> +	}
>> +	if (family == AF_INET6) {
>> +		ipq_prev_next = &(ifaceq->ip_quality_list_6);
>> +		ifaces_list_change = &ifaces_list_change_6;
>> +	}
> I guess static analyzers won't like this part; ipq_prev_next is
> uninitialized if the family is something else.
Should never happen, as we use RTMGRP_IPV4_IFADDR or RTMGRP_IPV6_IFADDR 
for netlink_groups. But yes, better safe than sorry.

-- 
Best Regards / S pozdravem,

Stanislav Brabec
software developer
---------------------------------------------------------------------
SUSE LINUX, s. r. o.                         e-mail: sbrabec@suse.com
Křižíkova 148/34 (Corso IIa)                    tel: +420 284 084 060
186 00 Praha 8-Karlín                          fax:  +420 284 084 001
Czech Republic                                    http://www.suse.cz/
PGP: 830B 40D5 9E05 35D8 5E27 6FA3 717C 209F A04F CD76


^ permalink raw reply

* Re: [PATCH V2 0/4] irqtop,lsirq: Miscellaneous enhancements
From: Joe Jin @ 2025-03-04  1:38 UTC (permalink / raw)
  To: Karel Zak; +Cc: Zhenwei Pi, Sami Kerola, util-linux
In-Reply-To: <ycaevmuxkamyr6m2um4kqxhx5xh7jtcr2xoeadfz2v6cmcmrrf@lgpkcja4h7rk>

On 3/3/25 02:16, Karel Zak wrote:
> On Fri, Feb 28, 2025 at 08:13:30AM GMT, Joe Jin wrote:
>> This patchset add below new options for irqtop:
>>  '-b|--batch' : Batch mode
>>  '-n|--iter'  : Specifies the maximum number of iterations
>>  '-J|--json'  : Json ouput format
>>
>> Add below for lsirq:
>>  '-i|--input' : Read data from file
>>
>> v2:
>>   - Removed macro irqtop_batch_mode.
>>   - Replaced macro irqtop_printf() to inline function
>>   - Changed option '--number' to '--iter'
>>   - Replace strdup() to xstrdup()
>>   - Added json output format for irqtop.
>>   - Remove irqtop input file support.
>>
>> Joe Jin (4):
>>   irqtop: add batch mode support
>>   irqtop: add max iteration support
>>   irqtop: support json output format
>>   lsirq: add support for reading data from given file
>>
>>  bash-completion/irqtop  |  12 +++-
>>  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      | 124 +++++++++++++++++++++++++++++++---------
>>  sys-utils/lsirq.1.adoc  |   3 +
>>  sys-utils/lsirq.c       |  24 ++++++--
>>  8 files changed, 155 insertions(+), 43 deletions(-)
> Thanks for the update. I have created a PR
> (https://github.com/util-linux/util-linux/pull/3435) to test it with
> CI tests.

Thanks so much!


>     Karel
>


^ permalink raw reply

* Re: [PATCH V2 2/4] irqtop: add max iteration support
From: Joe Jin @ 2025-03-04  1:39 UTC (permalink / raw)
  To: zhenwei pi, Karel Zak, Sami Kerola; +Cc: util-linux
In-Reply-To: <db814aa0-e91b-4a37-81fb-4c849c4a6c0d@bytedance.com>

On 3/3/25 01:39, zhenwei pi wrote:
>
>
> On 3/1/25 00:13, Joe Jin wrote:
>> 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>
>> Cc: Karel Zak <kzak@redhat.com>
>> ---
>>   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..d18ef99bb 100644
>> --- a/bash-completion/irqtop
>> +++ b/bash-completion/irqtop
>> @@ -22,6 +22,10 @@ _irqtop_module()
>>               COMPREPLY=( $(compgen -W "secs" -- $cur) )
>>               return 0
>>               ;;
>> +        '-n'|'--iter')
>> +            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
>> +        --iter
>>           --sort
>>           --output
>>           --softirq
>> diff --git a/sys-utils/irqtop.1.adoc b/sys-utils/irqtop.1.adoc
>> index e81f4fbb6..75930f5cf 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*, *--iter* _number_::
>> +Specifies the maximum 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 81a137be0..17c7d72cb 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    iter;
>>       bool    batch;
>>       bool    request_exit,
>>           softirq;
>> @@ -190,6 +191,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->iter > 0) {
>> +        ctl->iter--;
>> +        if (ctl->iter == 0)
>> +            ctl->request_exit = 1;
>> +    }
>>       return 0;
>>   }
>
> If ctl->iter is initialized as int64_max, then we have codes like:
>
> if (--ctl->iter == 0) {
>     ctl->request_exit = 1;
> }

Yes they are exactly same.
As Karel has queued for CI test, maybe keep current code?

Thanks,
Joe
>
>>   @@ -295,6 +302,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, --iter <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);
>> @@ -327,6 +335,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'},
>> +        {"iter", required_argument, NULL, 'n'},
>>           {"sort", required_argument, NULL, 's'},
>>           {"output", required_argument, NULL, 'o'},
>>           {"softirq", no_argument, NULL, 'S'},
>> @@ -337,7 +346,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 = 1;
>> @@ -377,6 +386,11 @@ static void parse_args(    struct irqtop_ctl *ctl,
>>                   ctl->timer.it_value = ctl->timer.it_interval;
>>               }
>>               break;
>> +        case 'n':
>> +            ctl->iter = str2num_or_err(optarg, 10,
>> +                    _("failed to parse iter argument"),
>> +                    0, INT_MAX);
>> +            break;
>>           case 's':
>>               set_sort_func_by_name(out, optarg);
>>               break;
>> @@ -423,7 +437,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},
>> +        .iter = -1
>>       };
>>         setlocale(LC_ALL, "");
>


^ permalink raw reply

* Re: Re: [PATCH V2 2/4] irqtop: add max iteration support
From: zhenwei pi @ 2025-03-04  3:49 UTC (permalink / raw)
  To: Joe Jin, Karel Zak, Sami Kerola; +Cc: util-linux
In-Reply-To: <5c7df987-2c12-4716-ad7a-f553e6c01a1f@oracle.com>

>>
>> If ctl->iter is initialized as int64_max, then we have codes like:
>>
>> if (--ctl->iter == 0) {
>>      ctl->request_exit = 1;
>> }
> 
> Yes they are exactly same.
> As Karel has queued for CI test, maybe keep current code?
> 
> Thanks,
> Joe

Fine.

^ permalink raw reply

* Re: Re: [PATCH V2 0/4] irqtop,lsirq: Miscellaneous enhancements
From: zhenwei pi @ 2025-03-04  3:50 UTC (permalink / raw)
  To: Joe Jin, Karel Zak; +Cc: Sami Kerola, util-linux
In-Reply-To: <d0410820-4713-4823-8a99-023223bc17d6@oracle.com>

This series looks good to me!

Reviewed-by: zhenwei pi <pizhenwei@bytedance.com>

On 3/4/25 09:38, Joe Jin wrote:
> On 3/3/25 02:16, Karel Zak wrote:
>> On Fri, Feb 28, 2025 at 08:13:30AM GMT, Joe Jin wrote:
>>> This patchset add below new options for irqtop:
>>>   '-b|--batch' : Batch mode
>>>   '-n|--iter'  : Specifies the maximum number of iterations
>>>   '-J|--json'  : Json ouput format
>>>
>>> Add below for lsirq:
>>>   '-i|--input' : Read data from file
>>>
>>> v2:
>>>    - Removed macro irqtop_batch_mode.
>>>    - Replaced macro irqtop_printf() to inline function
>>>    - Changed option '--number' to '--iter'
>>>    - Replace strdup() to xstrdup()
>>>    - Added json output format for irqtop.
>>>    - Remove irqtop input file support.
>>>
>>> Joe Jin (4):
>>>    irqtop: add batch mode support
>>>    irqtop: add max iteration support
>>>    irqtop: support json output format
>>>    lsirq: add support for reading data from given file
>>>
>>>   bash-completion/irqtop  |  12 +++-
>>>   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      | 124 +++++++++++++++++++++++++++++++---------
>>>   sys-utils/lsirq.1.adoc  |   3 +
>>>   sys-utils/lsirq.c       |  24 ++++++--
>>>   8 files changed, 155 insertions(+), 43 deletions(-)
>> Thanks for the update. I have created a PR
>> (https://github.com/util-linux/util-linux/pull/3435) to test it with
>> CI tests.
> 
> Thanks so much!
> 
> 
>>      Karel
>>
> 


^ permalink raw reply

* Re: [PATCH V2 0/4] irqtop,lsirq: Miscellaneous enhancements
From: Joe Jin @ 2025-03-04  4:12 UTC (permalink / raw)
  To: pi zhenwei; +Cc: Zak Karel, Kerola Sami, util-linux@vger.kernel.org



> 在 2025年3月3日,19:50,zhenwei pi <pizhenwei@bytedance.com> 写道:
> 
> This series looks good to me!
> 
> Reviewed-by: zhenwei pi <pizhenwei@bytedance.com>

Thanks so much for your review!


> 
>> On 3/4/25 09:38, Joe Jin wrote:
>>> On 3/3/25 02:16, Karel Zak wrote:
>>> On Fri, Feb 28, 2025 at 08:13:30AM GMT, Joe Jin wrote:
>>>> This patchset add below new options for irqtop:
>>>>  '-b|--batch' : Batch mode
>>>>  '-n|--iter'  : Specifies the maximum number of iterations
>>>>  '-J|--json'  : Json ouput format
>>>> 
>>>> Add below for lsirq:
>>>>  '-i|--input' : Read data from file
>>>> 
>>>> v2:
>>>>   - Removed macro irqtop_batch_mode.
>>>>   - Replaced macro irqtop_printf() to inline function
>>>>   - Changed option '--number' to '--iter'
>>>>   - Replace strdup() to xstrdup()
>>>>   - Added json output format for irqtop.
>>>>   - Remove irqtop input file support.
>>>> 
>>>> Joe Jin (4):
>>>>   irqtop: add batch mode support
>>>>   irqtop: add max iteration support
>>>>   irqtop: support json output format
>>>>   lsirq: add support for reading data from given file
>>>> 
>>>>  bash-completion/irqtop  |  12 +++-
>>>>  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      | 124 +++++++++++++++++++++++++++++++---------
>>>>  sys-utils/lsirq.1.adoc  |   3 +
>>>>  sys-utils/lsirq.c       |  24 ++++++--
>>>>  8 files changed, 155 insertions(+), 43 deletions(-)
>>> Thanks for the update. I have created a PR
>>> (https://github.com/util-linux/util-linux/pull/3435) to test it with
>>> CI tests.
>> Thanks so much!
>>>     Karel
>>> 
> 

^ permalink raw reply

* Re: [PATCH V2 0/4] irqtop,lsirq: Miscellaneous enhancements
From: Karel Zak @ 2025-03-04 10:58 UTC (permalink / raw)
  To: Joe Jin; +Cc: Zhenwei Pi, Sami Kerola, util-linux
In-Reply-To: <20250228161334.82987-1-joe.jin@oracle.com>

On Fri, Feb 28, 2025 at 08:13:30AM GMT, Joe Jin wrote:
> v2:
>   - Removed macro irqtop_batch_mode.
>   - Replaced macro irqtop_printf() to inline function
>   - Changed option '--number' to '--iter'
>   - Replace strdup() to xstrdup()
>   - Added json output format for irqtop.
>   - Remove irqtop input file support.
> 
> Joe Jin (4):
>   irqtop: add batch mode support
>   irqtop: add max iteration support
>   irqtop: support json output format
>   lsirq: add support for reading data from given file
> 
>  bash-completion/irqtop  |  12 +++-
>  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      | 124 +++++++++++++++++++++++++++++++---------
>  sys-utils/lsirq.1.adoc  |   3 +
>  sys-utils/lsirq.c       |  24 ++++++--
>  8 files changed, 155 insertions(+), 43 deletions(-)

 Applied, thanks.

    Karel

-- 
 Karel Zak  <kzak@redhat.com>
 http://karelzak.blogspot.com


^ permalink raw reply

* [PATCH] lscpu: Print ISA information in summary
From: Sunil V L @ 2025-03-04 14:42 UTC (permalink / raw)
  To: util-linux; +Cc: Sunil V L

The ISA information for RISC-V is an important information to understand
the different extensions supported by the CPU. Print this information in
the summary.

Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
---
 sys-utils/lscpu-cputype.c | 1 +
 sys-utils/lscpu.c         | 3 +++
 2 files changed, 4 insertions(+)

diff --git a/sys-utils/lscpu-cputype.c b/sys-utils/lscpu-cputype.c
index 739dd99c5..bdb33ac78 100644
--- a/sys-utils/lscpu-cputype.c
+++ b/sys-utils/lscpu-cputype.c
@@ -233,6 +233,7 @@ static const struct cpuinfo_pattern type_patterns[] =
 	DEF_PAT_CPUTYPE( "family",		PAT_FAMILY,	family),
 	DEF_PAT_CPUTYPE( "features",		PAT_FEATURES,	flags),		/* s390 */
 	DEF_PAT_CPUTYPE( "flags",		PAT_FLAGS,	flags),		/* x86 */
+	DEF_PAT_CPUTYPE( "isa",			PAT_ISA,	isa),		/* riscv */
 	DEF_PAT_CPUTYPE( "marchid",		PAT_FAMILY,	family),	/* riscv */
 	DEF_PAT_CPUTYPE( "max thread id",	PAT_MAX_THREAD_ID, mtid),	/* s390 */
 	DEF_PAT_CPUTYPE( "mimpid",		PAT_MODEL,	model),		/* riscv */
diff --git a/sys-utils/lscpu.c b/sys-utils/lscpu.c
index ffec37206..9f00b1757 100644
--- a/sys-utils/lscpu.c
+++ b/sys-utils/lscpu.c
@@ -954,6 +954,9 @@ print_summary_cputype(struct lscpu_cxt *cxt,
 
 	if (ct->flags)
 		add_summary_s(tb, sec, _("Flags:"), ct->flags);
+
+	if (ct->isa)
+		add_summary_s(tb, sec, _("ISA:"), ct->isa);
 }
 
 /*
-- 
2.43.0


^ permalink raw reply related

* [PATCH 1/2] lsmem: increase the available width for the summary text labels
From: Benno Schulenberg @ 2025-03-04 16:08 UTC (permalink / raw)
  To: util-linux

This allows the subsequent numbers to get vertically aligned for
most translations too.

Signed-off-by: Benno Schulenberg <bensberg@telfort.nl>
---
 sys-utils/lsmem.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/sys-utils/lsmem.c b/sys-utils/lsmem.c
index 94150e49d..9aa674581 100644
--- a/sys-utils/lsmem.c
+++ b/sys-utils/lsmem.c
@@ -306,22 +306,22 @@ static void fill_scols_table(struct lsmem *lsmem)
 static void print_summary(struct lsmem *lsmem)
 {
 	if (lsmem->bytes) {
-		printf("%-23s %15"PRId64"\n",_("Memory block size:"), lsmem->block_size);
-		printf("%-23s %15"PRId64"\n",_("Total online memory:"), lsmem->mem_online);
-		printf("%-23s %15"PRId64"\n",_("Total offline memory:"), lsmem->mem_offline);
+		printf("%-32s %15"PRId64"\n",_("Memory block size:"), lsmem->block_size);
+		printf("%-32s %15"PRId64"\n",_("Total online memory:"), lsmem->mem_online);
+		printf("%-32s %15"PRId64"\n",_("Total offline memory:"), lsmem->mem_offline);
 	} else {
 		char *p;
 
 		if ((p = size_to_human_string(SIZE_SUFFIX_1LETTER, lsmem->block_size)))
-			printf("%-23s %5s\n",_("Memory block size:"), p);
+			printf("%-32s %5s\n",_("Memory block size:"), p);
 		free(p);
 
 		if ((p = size_to_human_string(SIZE_SUFFIX_1LETTER, lsmem->mem_online)))
-			printf("%-23s %5s\n",_("Total online memory:"), p);
+			printf("%-32s %5s\n",_("Total online memory:"), p);
 		free(p);
 
 		if ((p = size_to_human_string(SIZE_SUFFIX_1LETTER, lsmem->mem_offline)))
-			printf("%-23s %5s\n",_("Total offline memory:"), p);
+			printf("%-32s %5s\n",_("Total offline memory:"), p);
 		free(p);
 	}
 }
-- 
2.48.1


^ permalink raw reply related

* [PATCH 2/2] hardlink: replace a strange word in an error message
From: Benno Schulenberg @ 2025-03-04 16:08 UTC (permalink / raw)
  To: util-linux
In-Reply-To: <20250304160806.10374-1-bensberg@telfort.nl>

Signed-off-by: Benno Schulenberg <bensberg@telfort.nl>
---
 misc-utils/hardlink.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/misc-utils/hardlink.c b/misc-utils/hardlink.c
index 6ac4a3306..ae8215901 100644
--- a/misc-utils/hardlink.c
+++ b/misc-utils/hardlink.c
@@ -1484,7 +1484,7 @@ int main(int argc, char *argv[])
 		rc = ul_fileeq_init(&fileeq, opts.method);
 	}
 	if (rc < 0)
-		err(EXIT_FAILURE, _("failed to initialize files comparior"));
+		err(EXIT_FAILURE, _("failed to initialize files comparer"));
 
 	/* default I/O size */
 	if (!opts.io_size) {
-- 
2.48.1


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox