[PATCH] irqtop: support -C/--cpu-list

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Specify cpus list format to show by -C/--cpu-list parameters, for
example, on an AMD server with 192 CPUs, to show statistics on NUMA
node 1:
  ~# ./irqtop -d 1 -C 48-95,144-191

Signed-off-by: zhenwei pi <pizhenwei@xxxxxxxxxxxxx>
---
 bash-completion/irqtop  |  4 ++++
 sys-utils/irq-common.c  | 46 ++++++++++++++++++++++++++++++-----------
 sys-utils/irq-common.h  |  9 ++++++--
 sys-utils/irqtop.1.adoc |  3 +++
 sys-utils/irqtop.c      | 29 +++++++++++++++++++++++---
 sys-utils/lsirq.c       |  2 +-
 6 files changed, 75 insertions(+), 18 deletions(-)

diff --git a/bash-completion/irqtop b/bash-completion/irqtop
index a3812acbb..7688f673c 100644
--- a/bash-completion/irqtop
+++ b/bash-completion/irqtop
@@ -9,6 +9,9 @@ _irqtop_module()
 			COMPREPLY=( $(compgen -W "auto enable disable" -- $cur) )
 			return 0
 			;;
+		'-C'|'--cpu-list')
+			return 0
+			;;
 		'-d'|'--delay')
 			COMPREPLY=( $(compgen -W "secs" -- $cur) )
 			return 0
@@ -35,6 +38,7 @@ _irqtop_module()
 			;;
 	esac
 	OPTS="	--cpu-stat
+		--cpu-list
 		--delay
 		--sort
 		--output
diff --git a/sys-utils/irq-common.c b/sys-utils/irq-common.c
index aa10f7e05..1bdcfad31 100644
--- a/sys-utils/irq-common.c
+++ b/sys-utils/irq-common.c
@@ -23,6 +23,7 @@
 #include <errno.h>
 #include <limits.h>
 #include <locale.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -228,10 +229,19 @@ static char *remove_repeated_spaces(char *str)
 	return str;
 }
 
+static bool cpu_in_list(int cpu, size_t setsize, cpu_set_t *cpuset)
+{
+	/* no -C/--cpu-list specified, use all the CPUs */
+	if (!cpuset)
+		return true;
+
+	return CPU_ISSET_S(cpu, setsize, cpuset);
+}
+
 /*
  * irqinfo - parse the system's interrupts
  */
-static struct irq_stat *get_irqinfo(int softirq)
+static struct irq_stat *get_irqinfo(int softirq, size_t setsize, cpu_set_t *cpuset)
 {
 	FILE *irqfile;
 	char *line = NULL, *tmp;
@@ -292,9 +302,11 @@ static struct irq_stat *get_irqinfo(int softirq)
 
 			if (sscanf(tmp, " %10lu", &count) != 1)
 				continue;
-			curr->total += count;
-			cpu->total += count;
-			stat->total_irq += count;
+			if (cpu_in_list(index, setsize, cpuset)) {
+				curr->total += count;
+				cpu->total += count;
+				stat->total_irq += count;
+			}
 
 			tmp += 11;
 		}
@@ -422,13 +434,15 @@ void set_sort_func_by_key(struct irq_output *out, char c)
 
 struct libscols_table *get_scols_cpus_table(struct irq_output *out,
 					struct irq_stat *prev,
-					struct irq_stat *curr)
+					struct irq_stat *curr,
+					size_t setsize,
+					cpu_set_t *cpuset)
 {
 	struct libscols_table *table;
 	struct libscols_column *cl;
 	struct libscols_line *ln;
 	char colname[sizeof(stringify_value(LONG_MAX))];
-	size_t i;
+	size_t i, j;
 
 	if (prev) {
 		for (i = 0; i < curr->nr_active_cpu; i++) {
@@ -454,6 +468,8 @@ struct libscols_table *get_scols_cpus_table(struct irq_output *out,
 		scols_table_new_column(table, "", 0, SCOLS_FL_RIGHT);
 
 	for (i = 0; i < curr->nr_active_cpu; i++) {
+		if (!cpu_in_list(i, setsize, cpuset))
+			continue;
 		snprintf(colname, sizeof(colname), "cpu%zu", i);
 		cl = scols_table_new_column(table, colname, 0, SCOLS_FL_RIGHT);
 		if (cl == NULL) {
@@ -469,12 +485,14 @@ struct libscols_table *get_scols_cpus_table(struct irq_output *out,
 	if (!ln || (!out->json && scols_line_set_data(ln, 0, "%irq:") != 0))
 		goto err;
 
-	for (i = 0; i < curr->nr_active_cpu; i++) {
+	for (i = 0, j = 0; i < curr->nr_active_cpu; i++) {
 		struct irq_cpu *cpu = &curr->cpus[i];
 		char *str;
 
+		if (!cpu_in_list(i, setsize, cpuset))
+			continue;
 		xasprintf(&str, "%0.1f", (double)((long double) cpu->total / (long double) curr->total_irq * 100.0));
-		if (str && scols_line_refer_data(ln, i + 1, str) != 0)
+		if (str && scols_line_refer_data(ln, ++j, str) != 0)
 			goto err;
 	}
 
@@ -484,14 +502,16 @@ struct libscols_table *get_scols_cpus_table(struct irq_output *out,
 	if (!ln || (!out->json && scols_line_set_data(ln, 0, _("%delta:")) != 0))
 		goto err;
 
-	for (i = 0; i < curr->nr_active_cpu; i++) {
+	for (i = 0, j = 0; i < curr->nr_active_cpu; i++) {
 		struct irq_cpu *cpu = &curr->cpus[i];
 		char *str;
 
+		if (!cpu_in_list(i, setsize, cpuset))
+			continue;
 		if (!curr->delta_irq)
 			continue;
 		xasprintf(&str, "%0.1f", (double)((long double) cpu->delta / (long double) curr->delta_irq * 100.0));
-		if (str && scols_line_refer_data(ln, i + 1, str) != 0)
+		if (str && scols_line_refer_data(ln, ++j, str) != 0)
 			goto err;
 	}
 
@@ -504,7 +524,9 @@ struct libscols_table *get_scols_cpus_table(struct irq_output *out,
 struct libscols_table *get_scols_table(struct irq_output *out,
 					      struct irq_stat *prev,
 					      struct irq_stat **xstat,
-					      int softirq)
+					      int softirq,
+					      size_t setsize,
+					      cpu_set_t *cpuset)
 {
 	struct libscols_table *table;
 	struct irq_info *result;
@@ -513,7 +535,7 @@ struct libscols_table *get_scols_table(struct irq_output *out,
 	size_t i;
 
 	/* the stats */
-	stat = get_irqinfo(softirq);
+	stat = get_irqinfo(softirq, setsize, cpuset);
 	if (!stat)
 		return NULL;
 
diff --git a/sys-utils/irq-common.h b/sys-utils/irq-common.h
index c4f1fa3a2..04c43207e 100644
--- a/sys-utils/irq-common.h
+++ b/sys-utils/irq-common.h
@@ -3,6 +3,7 @@
 
 #include "c.h"
 #include "nls.h"
+#include "cpuset.h"
 
 /* supported columns */
 enum {
@@ -63,10 +64,14 @@ void set_sort_func_by_key(struct irq_output *out, const char c);
 struct libscols_table *get_scols_table(struct irq_output *out,
                                               struct irq_stat *prev,
                                               struct irq_stat **xstat,
-                                              int softirq);
+                                              int softirq,
+                                              size_t setsize,
+                                              cpu_set_t *cpuset);
 
 struct libscols_table *get_scols_cpus_table(struct irq_output *out,
                                         struct irq_stat *prev,
-                                        struct irq_stat *curr);
+                                        struct irq_stat *curr,
+                                        size_t setsize,
+                                        cpu_set_t *cpuset);
 
 #endif /* UTIL_LINUX_H_IRQ_COMMON */
diff --git a/sys-utils/irqtop.1.adoc b/sys-utils/irqtop.1.adoc
index 3f215d2f0..a310ded9d 100644
--- a/sys-utils/irqtop.1.adoc
+++ b/sys-utils/irqtop.1.adoc
@@ -28,6 +28,9 @@ Specify which output columns to print. Use *--help* to get a list of all support
 *-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 enouth to show a full line of statistics.
 
+*-C*, *--cpu-list* _list_::
+Specify cpus in list format to show.
+
 *-d*, *--delay* _seconds_::
 Update interrupt output every _seconds_ intervals.
 
diff --git a/sys-utils/irqtop.c b/sys-utils/irqtop.c
index adf75591b..eb0e6bc66 100644
--- a/sys-utils/irqtop.c
+++ b/sys-utils/irqtop.c
@@ -57,6 +57,7 @@
 #include <libsmartcols.h>
 
 #include "closestream.h"
+#include "cpuset.h"
 #include "monotonic.h"
 #include "pathnames.h"
 #include "strutils.h"
@@ -83,6 +84,8 @@ struct irqtop_ctl {
 
 	struct itimerspec timer;
 	struct irq_stat	*prev_stat;
+	size_t setsize;
+	cpu_set_t *cpuset;
 
 	enum irqtop_cpustat_mode cpustat_mode;
 	unsigned int request_exit:1;
@@ -111,7 +114,8 @@ 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);
+	table = get_scols_table(out, ctl->prev_stat, &stat, ctl->softirq, ctl->setsize,
+				ctl->cpuset);
 	if (!table) {
 		ctl->request_exit = 1;
 		return 1;
@@ -122,7 +126,8 @@ static int update_screen(struct irqtop_ctl *ctl, struct irq_output *out)
 
 	/* make cpus table */
 	if (ctl->cpustat_mode != IRQTOP_CPUSTAT_DISABLE) {
-		cpus = get_scols_cpus_table(out, ctl->prev_stat, stat);
+		cpus = get_scols_cpus_table(out, ctl->prev_stat, stat, ctl->setsize,
+					    ctl->cpuset);
 		scols_table_reduce_termwidth(cpus, 1);
 		if (ctl->cpustat_mode == IRQTOP_CPUSTAT_AUTO)
 			scols_table_enable_nowrap(cpus, 1);
@@ -261,6 +266,7 @@ static void __attribute__((__noreturn__)) usage(void)
 
 	fputs(USAGE_OPTIONS, 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);
 	fputs(_(" -o, --output <list>  define which output columns to use\n"), stdout);
 	fputs(_(" -s, --sort <column>  specify sort column\n"), stdout);
@@ -290,6 +296,7 @@ static void parse_args(	struct irqtop_ctl *ctl,
 	const char *outarg = NULL;
 	static const struct option longopts[] = {
 		{"cpu-stat", required_argument, NULL, 'c'},
+		{"cpu-list", required_argument, NULL, 'C'},
 		{"delay", required_argument, NULL, 'd'},
 		{"sort", required_argument, NULL, 's'},
 		{"output", required_argument, NULL, 'o'},
@@ -300,7 +307,7 @@ static void parse_args(	struct irqtop_ctl *ctl,
 	};
 	int o;
 
-	while ((o = getopt_long(argc, argv, "c:d:o:s:ShV", longopts, NULL)) != -1) {
+	while ((o = getopt_long(argc, argv, "c:C:d:o:s:ShV", longopts, NULL)) != -1) {
 		switch (o) {
 		case 'c':
 			if (!strcmp(optarg, "auto"))
@@ -312,6 +319,21 @@ static void parse_args(	struct irqtop_ctl *ctl,
 			else
 				errx(EXIT_FAILURE, _("unsupported mode '%s'"), optarg);
 			break;
+		case 'C':
+			{
+				int ncpus = get_max_number_of_cpus();
+				if (ncpus <= 0)
+					errx(EXIT_FAILURE, _("cannot determine NR_CPUS; aborting"));
+
+				ctl->cpuset = cpuset_alloc(ncpus, &ctl->setsize, NULL);
+				if (!ctl->cpuset)
+					err(EXIT_FAILURE, _("cpuset_alloc failed"));
+
+				if (cpulist_parse(optarg, ctl->cpuset, ctl->setsize, 0))
+					errx(EXIT_FAILURE, _("failed to parse CPU list: %s"),
+						optarg);
+			}
+			break;
 		case 'd':
 			{
 				struct timeval delay;
@@ -388,6 +410,7 @@ int main(int argc, char **argv)
 
 	free_irqstat(ctl.prev_stat);
 	free(ctl.hostname);
+	cpuset_free(ctl.cpuset);
 
 	if (is_tty)
 		tcsetattr(STDIN_FILENO, TCSAFLUSH, &saved_tty);
diff --git a/sys-utils/lsirq.c b/sys-utils/lsirq.c
index 1a90efe21..375476dca 100644
--- a/sys-utils/lsirq.c
+++ b/sys-utils/lsirq.c
@@ -42,7 +42,7 @@ static int print_irq_data(struct irq_output *out, int softirq)
 {
 	struct libscols_table *table;
 
-	table = get_scols_table(out, NULL, NULL, softirq);
+	table = get_scols_table(out, NULL, NULL, softirq, 0, NULL);
 	if (!table)
 		return -1;
 
-- 
2.25.1




[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux