From c0be31476b5672b705bb29980141046055cbf65b Mon Sep 17 00:00:00 2001 From: Sebastien GODARD Date: Sat, 15 Oct 2022 11:58:31 +0200 Subject: [PATCH] mpstat: Fix missing sample after physically hotplugging vCPU When a vCPU is physically hotplugged, mpstat with its option -H skips one line of statistics: $ ./mpstat -H -P ALL 5 5 Linux 5.4.17-2136.310.7.1.el8uek.x86_64 (localhost.localdomain) 10/10/2022 x86_64 (3 CPU) 10:11:22 AM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle 10:11:27 AM all 0.07 0.00 0.07 0.00 0.07 0.00 0.00 0.00 0.00 99.80 10:11:27 AM 0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00 10:11:27 AM 1 0.20 0.00 0.20 0.00 0.20 0.00 0.00 0.00 0.00 99.40 10:11:27 AM 2 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00 10:11:27 AM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle 10:11:32 AM all 0.00 0.00 0.07 0.00 0.07 0.00 0.00 0.00 0.00 99.87 10:11:32 AM 0 0.00 0.00 0.00 0.00 0.20 0.00 0.00 0.00 0.00 99.80 10:11:32 AM 1 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00 10:11:32 AM 2 0.00 0.00 0.20 0.00 0.00 0.00 0.00 0.00 0.00 99.80 [ 1154.848226] CPU3 has been hot-added [ 1154.862315] smpboot: Booting Node 0 Processor 3 APIC 0x3 [ 1154.863956] kvm-clock: cpu 3, msr adc010c1, secondary cpu clock [ 1154.884436] KVM setup async PF for cpu 3 [ 1154.886055] kvm-stealtime: cpu 3, msr 13b9b2040 [ 1154.887657] Will online and init hotplugged CPU: 3 10:11:32 AM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle <<<<<<< No sample for 10:11:37 >>>>>>> 10:11:42 AM all 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00 10:11:42 AM 0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00 10:11:42 AM 1 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00 10:11:42 AM 2 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00 10:11:42 AM 3 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00 This patch makes sure that we get a line of stats for every interval of time, even when a vCPU is physically hotplugged. Signed-off-by: Sebastien GODARD --- mpstat.c | 89 ++++++++++++++++++++------------------------------------ 1 file changed, 32 insertions(+), 57 deletions(-) diff --git a/mpstat.c b/mpstat.c index ab478c5..79f0439 100644 --- a/mpstat.c +++ b/mpstat.c @@ -176,10 +176,12 @@ void int_handler(int sig) * IN: * @nr_cpus Number of CPUs. This is the real number of available CPUs + 1 * because we also have to allocate a structure for CPU 'all'. - * @reset Reset the memory only when set to TRUE. + * @pos Indicate which structures should be initialized. When @pos is + * non zero, it means that only the additional, newly allocated + * structures should be initialized. *************************************************************************** */ -void salloc_mp_struct(int nr_cpus, int reset) +void salloc_mp_struct(int nr_cpus, int pos) { int i; @@ -245,14 +247,14 @@ void salloc_mp_struct(int nr_cpus, int reset) exit(4); } - if (reset == TRUE) { - for (i = 0; i < 3; i++) { - memset(st_cpu[i], 0, STATS_CPU_SIZE * nr_cpus); - memset(st_node[i], 0, STATS_CPU_SIZE * nr_cpus); - memset(st_irq[i], 0, STATS_GLOBAL_IRQ_SIZE * nr_cpus); - memset(st_irqcpu[i], 0, STATS_IRQCPU_SIZE * nr_cpus * irqcpu_nr); - memset(st_softirqcpu[i], 0, STATS_IRQCPU_SIZE * nr_cpus * softirqcpu_nr); - } + for (i = 0; i < 3; i++) { + memset(st_cpu[i] + pos, 0, STATS_CPU_SIZE * (nr_cpus - pos)); + memset(st_node[i] + pos, 0, STATS_CPU_SIZE * (nr_cpus - pos)); + memset(st_irq[i] + pos, 0, STATS_GLOBAL_IRQ_SIZE * (nr_cpus - pos)); + memset(st_irqcpu[i] + pos, 0, STATS_IRQCPU_SIZE * (nr_cpus - pos) * irqcpu_nr); + memset(st_softirqcpu[i] + pos, 0, STATS_IRQCPU_SIZE * (nr_cpus - pos) * softirqcpu_nr); + } + if (!pos) { memset(cpu_bitmap, 0, (nr_cpus >> 3) + 1); memset(node_bitmap, 0, (nr_cpus >> 3) + 1); } @@ -2144,8 +2146,24 @@ int rw_mpstat_loop(int dis_hdr, int rows) if (count && USE_OPTION_H(flags)) { /* Check if a vCPU has been physically hotplugged */ new_cpu_nr = get_cpu_nr(~0, TRUE); - if (new_cpu_nr > cpu_nr) - return new_cpu_nr; + if (new_cpu_nr > cpu_nr) { + + /* Recalculate number of interrupts per processor */ + irqcpu_nr = get_irqcpu_nr(INTERRUPTS, NR_IRQS, new_cpu_nr) + + NR_IRQCPU_PREALLOC; + /* Recalculate number of soft interrupts per processor */ + softirqcpu_nr = get_irqcpu_nr(SOFTIRQS, NR_IRQS, new_cpu_nr) + + NR_IRQCPU_PREALLOC; + + /* Reallocate cpu stats structures */ + salloc_mp_struct(new_cpu_nr + 1, cpu_nr + 1); + + /* Get NUMA node placement */ + node_nr = get_node_placement(new_cpu_nr, cpu_per_node, cpu2node); + + /* Update the highest processor number */ + cpu_nr = new_cpu_nr; + } } } while (count); @@ -2160,49 +2178,6 @@ int rw_mpstat_loop(int dis_hdr, int rows) return 0; } -/* - *************************************************************************** - * Start mpstat loop until end of count or when a vCPU has been physically - * hotplugged. - * - * IN: - * @dis_hdr Set to TRUE if the header line must always be printed. - * @rows Number of rows of screen. - *************************************************************************** - */ -void mpstat_loop(int dis_hdr, int rows) -{ - int new_cpu_nr = 1; - - while (new_cpu_nr) { - /* Main loop for reading-writing stats */ - new_cpu_nr = rw_mpstat_loop(dis_hdr, rows); - - /* Handle vCPU physical hotplug */ - if (new_cpu_nr) { - /* Update the highest processor number */ - cpu_nr = new_cpu_nr; - - /* Recalculate number of interrupts per processor */ - irqcpu_nr = get_irqcpu_nr(INTERRUPTS, NR_IRQS, cpu_nr) + - NR_IRQCPU_PREALLOC; - /* Recalculate number of soft interrupts per processor */ - softirqcpu_nr = get_irqcpu_nr(SOFTIRQS, NR_IRQS, cpu_nr) + - NR_IRQCPU_PREALLOC; - - /* - * Reallocate cpu stats structs : - * global, proc0, proc1, ..., proc$(prev_cpu_nr-1). - * global, proc0, proc1, ..., proc$(prev_cpu_nr-1), ..., proc$(cpu_nr-1). - */ - salloc_mp_struct(cpu_nr + 1, FALSE); - - /* Get NUMA node placement */ - node_nr = get_node_placement(cpu_nr, cpu_per_node, cpu2node); - } - } -} - /* *************************************************************************** * Main entry to the program @@ -2241,7 +2216,7 @@ int main(int argc, char **argv) * cpu_nr: a value of 2 means there are 2 processors (0 and 1). * In this case, we have to allocate 3 structures: global, proc0 and proc1. */ - salloc_mp_struct(cpu_nr + 1, TRUE); + salloc_mp_struct(cpu_nr + 1, 0); /* Get NUMA node placement */ node_nr = get_node_placement(cpu_nr, cpu_per_node, cpu2node); @@ -2466,7 +2441,7 @@ int main(int argc, char **argv) DISPLAY_JSON_OUTPUT(flags)); /* Main loop */ - mpstat_loop(dis_hdr, rows); + rw_mpstat_loop(dis_hdr, rows); /* Free structures */ sfree_mp_struct(); -- 2.40.0