]> granicus.if.org Git - sysstat/blobdiff - pr_stats.c
sar/sadc: Add stable identifier support for disks statistics
[sysstat] / pr_stats.c
index d81fb59abf6da2cd19c10c423684b30c7b3ce419..72c9a67cdcf8b287051e35755f891d354689b28e 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * pr_stats.c: Functions used by sar to display statistics
- * (C) 1999-2017 by Sebastien GODARD (sysstat <at> orange.fr)
+ * (C) 1999-2019 by Sebastien GODARD (sysstat <at> orange.fr)
  *
  ***************************************************************************
  * This program is free software; you can redistribute it and/or modify it *
 #endif
 
 extern unsigned int flags;
-extern unsigned int dm_major;
-extern int  dis;
+extern int  dish;
 extern char timestamp[][TIMESTAMP_LEN];
 extern unsigned long avg_count;
 
-
 /*
  ***************************************************************************
  * Display current activity header line.
  *
  * IN:
- * @timestamp  Timestamp for previous stat sample.
+ * @p_timestamp        Timestamp for previous stat sample.
  * @a          Activity structure.
  * @pos                Index in @.hdr_line string, 0 being the first one (header
  *             are delimited by the '|' character).
@@ -58,7 +56,7 @@ extern unsigned long avg_count;
  * @vwidth     Column width for stats values.
  ***************************************************************************
  */
-void print_hdr_line(char *timestamp, struct activity *a, int pos, int iwidth, int vwidth)
+void print_hdr_line(char *p_timestamp, struct activity *a, int pos, int iwidth, int vwidth)
 {
        char hline[HEADER_LINE_LEN] = "";
        char *hl, *tk, *it = NULL;
@@ -72,7 +70,7 @@ void print_hdr_line(char *timestamp, struct activity *a, int pos, int iwidth, in
                /* Bad @pos arg given to function */
                return;
 
-       printf("\n%-11s", timestamp);
+       printf("\n%-11s", p_timestamp);
 
        if (strchr(hl, '&')) {
                j = strcspn(hl, "&");
@@ -126,93 +124,78 @@ __print_funct_t print_cpu_stats(struct activity *a, int prev, int curr,
                                unsigned long long itv)
 {
        int i;
-       unsigned long long tot_jiffies[3];
-       unsigned long long deltot_jiffies;
+       unsigned long long deltot_jiffies = 1;
        struct stats_cpu *scc, *scp;
+       unsigned char offline_cpu_bitmap[BITMAP_SIZE(NR_CPUS)] = {0};
 
-       if (dis) {
+       if (dish) {
                print_hdr_line(timestamp[!curr], a, FIRST + DISPLAY_CPU_ALL(a->opt_flags), 7, 9);
        }
 
-       for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
+       /*
+        * @nr[curr] cannot normally be greater than @nr_ini
+        * (since @nr_ini counts up all CPU, even those offline).
+        * If this happens, it may be because the machine has been
+        * restarted with more CPU and no LINUX_RESTART has been
+        * inserted in file.
+        * No problem here with @nr_allocated. Having been able to
+        * read @nr[curr] structures shows that buffers are large enough.
+        */
+       if (a->nr[curr] > a->nr_ini) {
+               a->nr_ini = a->nr[curr];
+       }
 
-               /*
-                * The size of a->buf[...] CPU structure may be different from the default
-                * sizeof(struct stats_cpu) value if data have been read from a file!
-                * That's why we don't use a syntax like:
-                * scc = (struct stats_cpu *) a->buf[...] + i;
-                */
-               scc = (struct stats_cpu *) ((char *) a->buf[curr] + i * a->msize);
-               scp = (struct stats_cpu *) ((char *) a->buf[prev] + i * a->msize);
+       /*
+        * Compute CPU "all" as sum of all individual CPU (on SMP machines)
+        * and look for offline CPU.
+        */
+       if (a->nr_ini > 1) {
+               deltot_jiffies = get_global_cpu_statistics(a, prev, curr,
+                                                          flags, offline_cpu_bitmap);
+       }
+
+       /*
+        * Now display CPU statistics (including CPU "all"),
+        * except for offline CPU or CPU that the user doesn't want to see.
+        */
+       for (i = 0; (i < a->nr_ini) && (i < a->bitmap->b_size + 1); i++) {
 
                /*
-                * Note: a->nr is in [1, NR_CPUS + 1].
+                * Should current CPU (including CPU "all") be displayed?
+                * Note: @nr[curr] is in [1, NR_CPUS + 1].
                 * Bitmap size is provided for (NR_CPUS + 1) CPUs.
                 * Anyway, NR_CPUS may vary between the version of sysstat
                 * used by sadc to create a file, and the version of sysstat
                 * used by sar to read it...
                 */
-
-               /* Should current CPU (including CPU "all") be displayed? */
-               if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
-                       /* No */
+               if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))) ||
+                   offline_cpu_bitmap[i >> 3] & (1 << (i & 0x07)))
+                       /* Don't display CPU */
                        continue;
 
-               /*
-                * Yes: Compute the total number of jiffies spent by current processor.
-                * NB: Don't add cpu_guest/cpu_guest_nice because cpu_user/cpu_nice
-                * already include them.
-                */
-               tot_jiffies[curr] = scc->cpu_user + scc->cpu_nice +
-                                   scc->cpu_sys + scc->cpu_idle +
-                                   scc->cpu_iowait + scc->cpu_hardirq +
-                                   scc->cpu_steal + scc->cpu_softirq;
-               tot_jiffies[prev] = scp->cpu_user + scp->cpu_nice +
-                                   scp->cpu_sys + scp->cpu_idle +
-                                   scp->cpu_iowait + scp->cpu_hardirq +
-                                   scp->cpu_steal + scp->cpu_softirq;
-
-               /* Total number of jiffies spent on the interval */
-               deltot_jiffies = get_interval(tot_jiffies[prev], tot_jiffies[curr]);
+               scc = (struct stats_cpu *) ((char *) a->buf[curr] + i * a->msize);
+               scp = (struct stats_cpu *) ((char *) a->buf[prev] + i * a->msize);
 
                printf("%-11s", timestamp[curr]);
 
-               if (!i) {
+               if (i == 0) {
                        /* This is CPU "all" */
                        cprintf_in(IS_STR, " %s", "    all", 0);
-               }
-               else {
-                       cprintf_in(IS_INT, " %7d", "", i - 1);
 
-                       /*
-                        * If the CPU is offline then it is omited from /proc/stat:
-                        * All the fields couldn't have been read and the sum of them is zero.
-                        * (Remember that guest/guest_nice times are already included in
-                        * user/nice modes.)
-                        */
-                       if (tot_jiffies[curr] == 0) {
+                       if (a->nr_ini == 1) {
                                /*
-                                * Set current struct fields (which have been set to zero)
-                                * to values from previous iteration. Hence their values won't
-                                * jump from zero when the CPU comes back online.
+                                * This is a UP machine. In this case
+                                * interval has still not been calculated.
                                 */
-                               *scc = *scp;
-
-                               /* %user, %nice, %system, %iowait, %steal, ..., %idle */
-                               cprintf_pc(DISPLAY_UNIT(flags), 6, 9, 2,
-                                          0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
-
-                               if (DISPLAY_CPU_ALL(a->opt_flags)) {
-                                       /*
-                                        * Four additional fields to display:
-                                        * %irq, %soft, %guest, %gnice.
-                                        */
-                                       cprintf_pc(DISPLAY_UNIT(flags), 4, 9, 2,
-                                                  0.0, 0.0, 0.0, 0.0);
-                               }
-                               printf("\n");
-                               continue;
+                               deltot_jiffies = get_per_cpu_interval(scc, scp);
                        }
+                       if (!deltot_jiffies) {
+                               /* CPU "all" cannot be tickless */
+                               deltot_jiffies = 1;
+                       }
+               }
+               else {
+                       cprintf_in(IS_INT, " %7d", "", i - 1);
 
                        /* Recalculate interval for current proc */
                        deltot_jiffies = get_per_cpu_interval(scc, scp);
@@ -235,8 +218,8 @@ __print_funct_t print_cpu_stats(struct activity *a, int prev, int curr,
                                 * %irq, %soft, %guest, %gnice.
                                 */
                                else if (DISPLAY_CPU_ALL(a->opt_flags)) {
-                                       cprintf_pc(DISPLAY_UNIT(flags), 4, 9, 2,
-                                                  0.0, 0.0, 0.0, 100.0);
+                                       cprintf_pc(DISPLAY_UNIT(flags), 5, 9, 2,
+                                                  0.0, 0.0, 0.0, 0.0, 100.0);
                                        printf("\n");
                                }
                                continue;
@@ -300,7 +283,7 @@ __print_funct_t print_pcsw_stats(struct activity *a, int prev, int curr,
                *spc = (struct stats_pcsw *) a->buf[curr],
                *spp = (struct stats_pcsw *) a->buf[prev];
 
-       if (dis) {
+       if (dish) {
                print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
        }
 
@@ -328,17 +311,21 @@ __print_funct_t print_irq_stats(struct activity *a, int prev, int curr,
        int i;
        struct stats_irq *sic, *sip;
 
-       if (dis) {
+       if (dish || DISPLAY_ZERO_OMIT(flags)) {
                print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
        }
 
-       for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
+       for (i = 0; (i < a->nr[curr]) && (i < a->bitmap->b_size + 1); i++) {
 
+               /*
+                * If @nr[curr] > @nr[prev] then we consider that previous
+                * interrupt value was 0.
+                */
                sic = (struct stats_irq *) ((char *) a->buf[curr] + i * a->msize);
                sip = (struct stats_irq *) ((char *) a->buf[prev] + i * a->msize);
 
                /*
-                * Note: a->nr is in [0, NR_IRQS + 1].
+                * Note: @nr[curr] gives the number of interrupts read (1 .. NR_IRQS + 1).
                 * Bitmap size is provided for (NR_IRQS + 1) interrupts.
                 * Anyway, NR_IRQS may vary between the version of sysstat
                 * used by sadc to create a file, and the version of sysstat
@@ -348,6 +335,9 @@ __print_funct_t print_irq_stats(struct activity *a, int prev, int curr,
                /* Should current interrupt (including int "sum") be displayed? */
                if (a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))) {
 
+                       if (DISPLAY_ZERO_OMIT(flags) && !memcmp(sip, sic, STATS_IRQ_SIZE))
+                               continue;
+
                        /* Yes: Display it */
                        printf("%-11s", timestamp[curr]);
                        if (!i) {
@@ -382,7 +372,7 @@ __print_funct_t print_swap_stats(struct activity *a, int prev, int curr,
                *ssc = (struct stats_swap *) a->buf[curr],
                *ssp = (struct stats_swap *) a->buf[prev];
 
-       if (dis) {
+       if (dish) {
                print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
        }
 
@@ -411,7 +401,7 @@ __print_funct_t print_paging_stats(struct activity *a, int prev, int curr,
                *spc = (struct stats_paging *) a->buf[curr],
                *spp = (struct stats_paging *) a->buf[prev];
 
-       if (dis) {
+       if (dish) {
                print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
        }
 
@@ -453,7 +443,7 @@ __print_funct_t print_io_stats(struct activity *a, int prev, int curr,
                *sic = (struct stats_io *) a->buf[curr],
                *sip = (struct stats_io *) a->buf[prev];
 
-       if (dis) {
+       if (dish) {
                print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
        }
 
@@ -464,17 +454,21 @@ __print_funct_t print_io_stats(struct activity *a, int prev, int curr,
         * We display 0.0 in this case though we should rather tell
         * the user that the value cannot be calculated here.
         */
-       cprintf_f(NO_UNIT, 5, 9, 2,
+       cprintf_f(NO_UNIT, 7, 9, 2,
                  sic->dk_drive < sip->dk_drive ? 0.0 :
                  S_VALUE(sip->dk_drive, sic->dk_drive, itv),
                  sic->dk_drive_rio < sip->dk_drive_rio ? 0.0 :
                  S_VALUE(sip->dk_drive_rio, sic->dk_drive_rio, itv),
                  sic->dk_drive_wio < sip->dk_drive_wio ? 0.0 :
                  S_VALUE(sip->dk_drive_wio, sic->dk_drive_wio, itv),
+                 sic->dk_drive_dio < sip->dk_drive_dio ? 0.0 :
+                 S_VALUE(sip->dk_drive_dio, sic->dk_drive_dio, itv),
                  sic->dk_drive_rblk < sip->dk_drive_rblk ? 0.0 :
                  S_VALUE(sip->dk_drive_rblk, sic->dk_drive_rblk, itv),
                  sic->dk_drive_wblk < sip->dk_drive_wblk ? 0.0 :
-                 S_VALUE(sip->dk_drive_wblk, sic->dk_drive_wblk, itv));
+                 S_VALUE(sip->dk_drive_wblk, sic->dk_drive_wblk, itv),
+                 sic->dk_drive_dblk < sip->dk_drive_dblk ? 0.0 :
+                 S_VALUE(sip->dk_drive_dblk, sic->dk_drive_dblk, itv));
        printf("\n");
 }
 
@@ -513,6 +507,7 @@ void stub_print_memory_stats(struct activity *a, int prev, int curr, int dispavg
                avg_tlskb = 0,
                avg_caskb = 0;
        int unit = NO_UNIT;
+       unsigned long long nousedmem;
 
        if (DISPLAY_UNIT(flags)) {
                /* Default values unit is kB */
@@ -520,20 +515,24 @@ void stub_print_memory_stats(struct activity *a, int prev, int curr, int dispavg
        }
 
        if (DISPLAY_MEMORY(a->opt_flags)) {
-               if (dis) {
+               if (dish) {
                        print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
                }
 
                if (!dispavg) {
                        /* Display instantaneous values */
+                       nousedmem = smc->frmkb + smc->bufkb + smc->camkb + smc->slabkb;
+                       if (nousedmem > smc->tlmkb) {
+                               nousedmem = smc->tlmkb;
+                       }
                        printf("%-11s", timestamp[curr]);
                        cprintf_u64(unit, 3, 9,
                                    (unsigned long long) smc->frmkb,
                                    (unsigned long long) smc->availablekb,
-                                   (unsigned long long) (smc->tlmkb - smc->frmkb));
+                                   (unsigned long long) (smc->tlmkb - nousedmem));
                        cprintf_pc(DISPLAY_UNIT(flags), 1, 9, 2,
                                   smc->tlmkb ?
-                                  SP_VALUE(smc->frmkb, smc->tlmkb, smc->tlmkb)
+                                  SP_VALUE(nousedmem, smc->tlmkb, smc->tlmkb)
                                   : 0.0);
                        cprintf_u64(unit, 3, 9,
                                    (unsigned long long) smc->bufkb,
@@ -581,14 +580,15 @@ void stub_print_memory_stats(struct activity *a, int prev, int curr, int dispavg
                }
                else {
                        /* Display average values */
+                       nousedmem = avg_frmkb + avg_bufkb + avg_camkb + avg_slabkb;
                        printf("%-11s", timestamp[curr]);
                        cprintf_f(unit, 3, 9, 0,
                                  (double) avg_frmkb / avg_count,
                                  (double) avg_availablekb / avg_count,
-                                 (double) smc->tlmkb - ((double) avg_frmkb / avg_count));
+                                 (double) smc->tlmkb - ((double) nousedmem / avg_count));
                        cprintf_pc(DISPLAY_UNIT(flags), 1, 9, 2,
                                   smc->tlmkb ?
-                                  SP_VALUE((double) (avg_frmkb / avg_count), smc->tlmkb, smc->tlmkb)
+                                  SP_VALUE((double) (nousedmem / avg_count), smc->tlmkb, smc->tlmkb)
                                   : 0.0);
                        cprintf_f(unit, 3, 9, 0,
                                  (double) avg_bufkb / avg_count,
@@ -623,7 +623,7 @@ void stub_print_memory_stats(struct activity *a, int prev, int curr, int dispavg
        }
 
        if (DISPLAY_SWAP(a->opt_flags)) {
-               if (dis) {
+               if (dish) {
                        print_hdr_line(timestamp[!curr], a, SECOND, 0, 9);
                }
 
@@ -739,7 +739,7 @@ void stub_print_ktables_stats(struct activity *a, int curr, int dispavg)
                avg_pty_nr      = 0;
 
 
-       if (dis) {
+       if (dish) {
                print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
        }
 
@@ -834,7 +834,7 @@ void stub_print_queue_stats(struct activity *a, int curr, int dispavg)
                avg_load_avg_15   = 0,
                avg_procs_blocked = 0;
 
-       if (dis) {
+       if (dish) {
                print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
        }
 
@@ -929,38 +929,72 @@ __print_funct_t print_avg_queue_stats(struct activity *a, int prev, int curr,
 __print_funct_t print_serial_stats(struct activity *a, int prev, int curr,
                                   unsigned long long itv)
 {
-       int i;
+       int i, j, j0, found;
        struct stats_serial *ssc, *ssp;
 
-       if (dis) {
+       if (dish || DISPLAY_ZERO_OMIT(flags)) {
                print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
        }
 
-       for (i = 0; i < a->nr; i++) {
-
+       for (i = 0; i < a->nr[curr]; i++) {
                ssc = (struct stats_serial *) ((char *) a->buf[curr] + i * a->msize);
-               ssp = (struct stats_serial *) ((char *) a->buf[prev] + i * a->msize);
-
-               if (ssc->line == 0)
-                       continue;
 
-               printf("%-11s", timestamp[curr]);
-               cprintf_in(IS_INT, "       %3d", "", ssc->line - 1);
-
-               if ((ssc->line == ssp->line) || WANT_SINCE_BOOT(flags)) {
-                       cprintf_f(NO_UNIT, 6, 9, 2,
-                                 S_VALUE(ssp->rx,      ssc->rx,      itv),
-                                 S_VALUE(ssp->tx,      ssc->tx,      itv),
-                                 S_VALUE(ssp->frame,   ssc->frame,   itv),
-                                 S_VALUE(ssp->parity,  ssc->parity,  itv),
-                                 S_VALUE(ssp->brk,     ssc->brk,     itv),
-                                 S_VALUE(ssp->overrun, ssc->overrun, itv));
-                       printf("\n");
+               if (WANT_SINCE_BOOT(flags)) {
+                       /*
+                        * We want to display statistics since boot time.
+                        * Take the first structure from buf[prev]: This is a
+                        * structure that only contains 0 (it has been set to 0
+                        * when it has been allocated), and which exists since
+                        * there is the same number of allocated structures for
+                        * buf[prev] and bur[curr] (even if nothing has been read).
+                        */
+                       ssp = (struct stats_serial *) ((char *) a->buf[prev]);
+                       found = TRUE;
                }
                else {
-                       printf("       N/A       N/A       N/A       N/A"
-                              "       N/A       N/A\n");
+                       found = FALSE;
+
+                       if (a->nr[prev] > 0) {
+                               /* Look for corresponding serial line in previous iteration */
+                               j = i;
+
+                               if (j >= a->nr[prev]) {
+                                       j = a->nr[prev] - 1;
+                               }
+
+                               j0 = j;
+
+                               do {
+                                       ssp = (struct stats_serial *) ((char *) a->buf[prev] + j * a->msize);
+                                       if (ssc->line == ssp->line) {
+                                               found = TRUE;
+                                               break;
+                                       }
+                                       if (++j >= a->nr[prev]) {
+                                               j = 0;
+                                       }
+                               }
+                               while (j != j0);
+                       }
                }
+
+               if (!found)
+                       continue;
+
+               if (DISPLAY_ZERO_OMIT(flags) && !memcmp(ssp, ssc, STATS_SERIAL_SIZE))
+                       continue;
+
+               printf("%-11s", timestamp[curr]);
+               cprintf_in(IS_INT, "       %3d", "", ssc->line);
+
+               cprintf_f(NO_UNIT, 6, 9, 2,
+                         S_VALUE(ssp->rx,      ssc->rx,      itv),
+                         S_VALUE(ssp->tx,      ssc->tx,      itv),
+                         S_VALUE(ssp->frame,   ssc->frame,   itv),
+                         S_VALUE(ssp->parity,  ssc->parity,  itv),
+                         S_VALUE(ssp->brk,     ssc->brk,     itv),
+                         S_VALUE(ssp->overrun, ssc->overrun, itv));
+               printf("\n");
        }
 }
 
@@ -981,7 +1015,7 @@ __print_funct_t print_disk_stats(struct activity *a, int prev, int curr,
        int i, j;
        struct stats_disk *sdc, *sdp, sdpzero;
        struct ext_disk_stats xds;
-       char *dev_name, *persist_dev_name;
+       char *dev_name;
        int unit = NO_UNIT;
 
        memset(&sdpzero, 0, STATS_DISK_SIZE);
@@ -991,67 +1025,68 @@ __print_funct_t print_disk_stats(struct activity *a, int prev, int curr,
                unit = UNIT_KILOBYTE;
        }
 
-       if (dis) {
-               print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
+       if (dish || DISPLAY_ZERO_OMIT(flags)) {
+               print_hdr_line(timestamp[!curr], a, FIRST, DISPLAY_HUMAN_READ(flags) ? -1 : 0, 9);
        }
 
-       for (i = 0; i < a->nr; i++) {
-
+       for (i = 0; i < a->nr[curr]; i++) {
                sdc = (struct stats_disk *) ((char *) a->buf[curr] + i * a->msize);
 
-               if (!(sdc->major + sdc->minor))
-                       continue;
-
-               j = check_disk_reg(a, curr, prev, i);
+               if (!WANT_SINCE_BOOT(flags)) {
+                       j = check_disk_reg(a, curr, prev, i);
+               }
+               else {
+                       j = -1;
+               }
                if (j < 0) {
-                       /* This is a newly registered interface. Previous stats are zero */
+                       /*
+                        * This is a newly registered device or we want stats since boot time.
+                        * Previous stats are zero.
+                        */
                        sdp = &sdpzero;
                }
                else {
                        sdp = (struct stats_disk *) ((char *) a->buf[prev] + j * a->msize);
                }
 
-               /* Compute service time, etc. */
-               compute_ext_disk_stats(sdc, sdp, itv, &xds);
+               if (DISPLAY_ZERO_OMIT(flags) && !memcmp(sdp, sdc, STATS_DISK_SIZE))
+                       continue;
 
-               dev_name = NULL;
-               persist_dev_name = NULL;
+               /* Get device name */
+               dev_name = get_sa_devname(sdc->major, sdc->minor, sdc->wwn, sdc->part_nr, flags);
 
-               if (DISPLAY_PERSIST_NAME_S(flags)) {
-                       persist_dev_name = get_persistent_name_from_pretty(get_devname(sdc->major, sdc->minor, TRUE));
+               if (a->item_list != NULL) {
+                       /* A list of devices has been entered on the command line */
+                       if (!search_list_item(a->item_list, dev_name))
+                               /* Device not found */
+                               continue;
                }
 
-               if (persist_dev_name) {
-                       dev_name = persist_dev_name;
-               }
-               else {
-                       if ((USE_PRETTY_OPTION(flags)) && (sdc->major == dm_major)) {
-                               dev_name = transform_devmapname(sdc->major, sdc->minor);
-                       }
-
-                       if (!dev_name) {
-                               dev_name = get_devname(sdc->major, sdc->minor,
-                                                      USE_PRETTY_OPTION(flags));
-                       }
-               }
+               /* Compute service time, etc. */
+               compute_ext_disk_stats(sdc, sdp, itv, &xds);
 
                printf("%-11s", timestamp[curr]);
 
-               cprintf_in(IS_STR, " %9s", dev_name, 0);
+               if (!DISPLAY_HUMAN_READ(flags)) {
+                       cprintf_in(IS_STR, " %9s", dev_name, 0);
+               }
                cprintf_f(NO_UNIT, 1, 9, 2,
                          S_VALUE(sdp->nr_ios, sdc->nr_ios,  itv));
-               cprintf_f(unit, 2, 9, 2,
+               cprintf_f(unit, 3, 9, 2,
                          S_VALUE(sdp->rd_sect, sdc->rd_sect, itv) / 2,
-                         S_VALUE(sdp->wr_sect, sdc->wr_sect, itv) / 2);
+                         S_VALUE(sdp->wr_sect, sdc->wr_sect, itv) / 2,
+                         S_VALUE(sdp->dc_sect, sdc->dc_sect, itv) / 2);
                /* See iostat for explanations */
                cprintf_f(unit, 1, 9, 2,
                          xds.arqsz / 2);
-               cprintf_f(NO_UNIT, 3, 9, 2,
+               cprintf_f(NO_UNIT, 2, 9, 2,
                          S_VALUE(sdp->rq_ticks, sdc->rq_ticks, itv) / 1000.0,
-                         xds.await,
-                         xds.svctm);
+                         xds.await);
                cprintf_pc(DISPLAY_UNIT(flags), 1, 9, 2,
                           xds.util / 10.0);
+               if (DISPLAY_HUMAN_READ(flags)) {
+                       cprintf_in(IS_STR, " %s", dev_name, 0);
+               }
                printf("\n");
        }
 }
@@ -1082,29 +1117,45 @@ __print_funct_t print_net_dev_stats(struct activity *a, int prev, int curr,
                unit = UNIT_BYTE;
        }
 
-       if (dis) {
-               print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
+       if (dish || DISPLAY_ZERO_OMIT(flags)) {
+               print_hdr_line(timestamp[!curr], a, FIRST, DISPLAY_HUMAN_READ(flags) ? -1 : 0, 9);
        }
 
-       for (i = 0; i < a->nr; i++) {
-
+       for (i = 0; i < a->nr[curr]; i++) {
                sndc = (struct stats_net_dev *) ((char *) a->buf[curr] + i * a->msize);
 
-               if (!strcmp(sndc->interface, ""))
-                       break;
+               if (a->item_list != NULL) {
+                       /* A list of devices has been entered on the command line */
+                       if (!search_list_item(a->item_list, sndc->interface))
+                               /* Device not found */
+                               continue;
+               }
 
-               j = check_net_dev_reg(a, curr, prev, i);
+               if (!WANT_SINCE_BOOT(flags)) {
+                       j = check_net_dev_reg(a, curr, prev, i);
+               }
+               else {
+                       j = -1;
+               }
                if (j < 0) {
-                       /* This is a newly registered interface. Previous stats are zero */
+                       /*
+                        * This is a newly registered interface or we want stats since boot time.
+                        * Previous stats are zero.
+                        */
                        sndp = &sndzero;
                }
                else {
                        sndp = (struct stats_net_dev *) ((char *) a->buf[prev] + j * a->msize);
                }
 
+               if (DISPLAY_ZERO_OMIT(flags) && !memcmp(sndp, sndc, STATS_NET_DEV_SIZE2CMP))
+                       continue;
+
                printf("%-11s", timestamp[curr]);
-               cprintf_in(IS_STR, " %9s", sndc->interface, 0);
 
+               if (!DISPLAY_HUMAN_READ(flags)) {
+                       cprintf_in(IS_STR, " %9s", sndc->interface, 0);
+               }
                rxkb = S_VALUE(sndp->rx_bytes, sndc->rx_bytes, itv);
                txkb = S_VALUE(sndp->tx_bytes, sndc->tx_bytes, itv);
 
@@ -1120,6 +1171,9 @@ __print_funct_t print_net_dev_stats(struct activity *a, int prev, int curr,
                          S_VALUE(sndp->multicast,     sndc->multicast,     itv));
                ifutil = compute_ifutil(sndc, rxkb, txkb);
                cprintf_pc(DISPLAY_UNIT(flags), 1, 9, 2, ifutil);
+               if (DISPLAY_HUMAN_READ(flags)) {
+                       cprintf_in(IS_STR, " %s", sndc->interface, 0);
+               }
                printf("\n");
        }
 }
@@ -1143,29 +1197,45 @@ __print_funct_t print_net_edev_stats(struct activity *a, int prev, int curr,
 
        memset(&snedzero, 0, STATS_NET_EDEV_SIZE);
 
-       if (dis) {
-               print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
+       if (dish || DISPLAY_ZERO_OMIT(flags)) {
+               print_hdr_line(timestamp[!curr], a, FIRST, DISPLAY_HUMAN_READ(flags) ? -1 : 0, 9);
        }
 
-       for (i = 0; i < a->nr; i++) {
-
+       for (i = 0; i < a->nr[curr]; i++) {
                snedc = (struct stats_net_edev *) ((char *) a->buf[curr] + i * a->msize);
 
-               if (!strcmp(snedc->interface, ""))
-                       break;
+               if (a->item_list != NULL) {
+                       /* A list of devices has been entered on the command line */
+                       if (!search_list_item(a->item_list, snedc->interface))
+                               /* Device not found */
+                               continue;
+               }
 
-               j = check_net_edev_reg(a, curr, prev, i);
+               if (!WANT_SINCE_BOOT(flags)) {
+                       j = check_net_edev_reg(a, curr, prev, i);
+               }
+               else {
+                       j = -1;
+               }
                if (j < 0) {
-                       /* This is a newly registered interface. Previous stats are zero */
+                       /*
+                        * This is a newly registered interface or we want stats since boot time.
+                        * Previous stats are zero.
+                        */
                        snedp = &snedzero;
                }
                else {
                        snedp = (struct stats_net_edev *) ((char *) a->buf[prev] + j * a->msize);
                }
 
+               if (DISPLAY_ZERO_OMIT(flags) && !memcmp(snedp, snedc, STATS_NET_EDEV_SIZE2CMP))
+                       continue;
+
                printf("%-11s", timestamp[curr]);
-               cprintf_in(IS_STR, " %9s", snedc->interface, 0);
 
+               if (!DISPLAY_HUMAN_READ(flags)) {
+                       cprintf_in(IS_STR, " %9s", snedc->interface, 0);
+               }
                cprintf_f(NO_UNIT, 9, 9, 2,
                          S_VALUE(snedp->rx_errors,         snedc->rx_errors,         itv),
                          S_VALUE(snedp->tx_errors,         snedc->tx_errors,         itv),
@@ -1176,6 +1246,9 @@ __print_funct_t print_net_edev_stats(struct activity *a, int prev, int curr,
                          S_VALUE(snedp->rx_frame_errors,   snedc->rx_frame_errors,   itv),
                          S_VALUE(snedp->rx_fifo_errors,    snedc->rx_fifo_errors,    itv),
                          S_VALUE(snedp->tx_fifo_errors,    snedc->tx_fifo_errors,    itv));
+               if (DISPLAY_HUMAN_READ(flags)) {
+                       cprintf_in(IS_STR, " %s", snedc->interface, 0);
+               }
                printf("\n");
        }
 }
@@ -1198,7 +1271,7 @@ __print_funct_t print_net_nfs_stats(struct activity *a, int prev, int curr,
                *snnc = (struct stats_net_nfs *) a->buf[curr],
                *snnp = (struct stats_net_nfs *) a->buf[prev];
 
-       if (dis) {
+       if (dish) {
                print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
        }
 
@@ -1231,7 +1304,7 @@ __print_funct_t print_net_nfsd_stats(struct activity *a, int prev, int curr,
                *snndc = (struct stats_net_nfsd *) a->buf[curr],
                *snndp = (struct stats_net_nfsd *) a->buf[prev];
 
-       if (dis) {
+       if (dish) {
                print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
        }
 
@@ -1274,7 +1347,7 @@ void stub_print_net_sock_stats(struct activity *a, int curr, int dispavg)
                avg_frag_inuse = 0,
                avg_tcp_tw     = 0;
 
-       if (dis) {
+       if (dish) {
                print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
        }
 
@@ -1368,7 +1441,7 @@ __print_funct_t print_net_ip_stats(struct activity *a, int prev, int curr,
                *snic = (struct stats_net_ip *) a->buf[curr],
                *snip = (struct stats_net_ip *) a->buf[prev];
 
-       if (dis) {
+       if (dish) {
                print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
        }
 
@@ -1403,7 +1476,7 @@ __print_funct_t print_net_eip_stats(struct activity *a, int prev, int curr,
                *sneic = (struct stats_net_eip *) a->buf[curr],
                *sneip = (struct stats_net_eip *) a->buf[prev];
 
-       if (dis) {
+       if (dish) {
                print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
        }
 
@@ -1438,7 +1511,7 @@ __print_funct_t print_net_icmp_stats(struct activity *a, int prev, int curr,
                *snic = (struct stats_net_icmp *) a->buf[curr],
                *snip = (struct stats_net_icmp *) a->buf[prev];
 
-       if (dis) {
+       if (dish) {
                print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
        }
 
@@ -1479,7 +1552,7 @@ __print_funct_t print_net_eicmp_stats(struct activity *a, int prev, int curr,
                *sneic = (struct stats_net_eicmp *) a->buf[curr],
                *sneip = (struct stats_net_eicmp *) a->buf[prev];
 
-       if (dis) {
+       if (dish) {
                print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
        }
 
@@ -1518,7 +1591,7 @@ __print_funct_t print_net_tcp_stats(struct activity *a, int prev, int curr,
                *sntc = (struct stats_net_tcp *) a->buf[curr],
                *sntp = (struct stats_net_tcp *) a->buf[prev];
 
-       if (dis) {
+       if (dish) {
                print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
        }
 
@@ -1549,7 +1622,7 @@ __print_funct_t print_net_etcp_stats(struct activity *a, int prev, int curr,
                *snetc = (struct stats_net_etcp *) a->buf[curr],
                *snetp = (struct stats_net_etcp *) a->buf[prev];
 
-       if (dis) {
+       if (dish) {
                print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
        }
 
@@ -1581,7 +1654,7 @@ __print_funct_t print_net_udp_stats(struct activity *a, int prev, int curr,
                *snuc = (struct stats_net_udp *) a->buf[curr],
                *snup = (struct stats_net_udp *) a->buf[prev];
 
-       if (dis) {
+       if (dish) {
                print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
        }
 
@@ -1615,7 +1688,7 @@ void stub_print_net_sock6_stats(struct activity *a, int curr, int dispavg)
                avg_raw6_inuse  = 0,
                avg_frag6_inuse = 0;
 
-       if (dis) {
+       if (dish) {
                print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
        }
 
@@ -1702,7 +1775,7 @@ __print_funct_t print_net_ip6_stats(struct activity *a, int prev, int curr,
                *snic = (struct stats_net_ip6 *) a->buf[curr],
                *snip = (struct stats_net_ip6 *) a->buf[prev];
 
-       if (dis) {
+       if (dish) {
                print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
        }
 
@@ -1739,7 +1812,7 @@ __print_funct_t print_net_eip6_stats(struct activity *a, int prev, int curr,
                *sneic = (struct stats_net_eip6 *) a->buf[curr],
                *sneip = (struct stats_net_eip6 *) a->buf[prev];
 
-       if (dis) {
+       if (dish) {
                print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
        }
 
@@ -1777,7 +1850,7 @@ __print_funct_t print_net_icmp6_stats(struct activity *a, int prev, int curr,
                *snic = (struct stats_net_icmp6 *) a->buf[curr],
                *snip = (struct stats_net_icmp6 *) a->buf[prev];
 
-       if (dis) {
+       if (dish) {
                print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
        }
 
@@ -1821,7 +1894,7 @@ __print_funct_t print_net_eicmp6_stats(struct activity *a, int prev, int curr,
                *sneic = (struct stats_net_eicmp6 *) a->buf[curr],
                *sneip = (struct stats_net_eicmp6 *) a->buf[prev];
 
-       if (dis) {
+       if (dish) {
                print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
        }
 
@@ -1859,7 +1932,7 @@ __print_funct_t print_net_udp6_stats(struct activity *a, int prev, int curr,
                *snuc = (struct stats_net_udp6 *) a->buf[curr],
                *snup = (struct stats_net_udp6 *) a->buf[prev];
 
-       if (dis) {
+       if (dish) {
                print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
        }
 
@@ -1887,24 +1960,26 @@ void stub_print_pwr_cpufreq_stats(struct activity *a, int curr, int dispavg)
 {
        int i;
        struct stats_pwr_cpufreq *spc;
+       static __nr_t nr_alloc = 0;
        static unsigned long long
                *avg_cpufreq = NULL;
 
-       if (!avg_cpufreq) {
+       if (!avg_cpufreq || (a->nr[curr] > nr_alloc)) {
                /* Allocate array of CPU frequency */
-               if ((avg_cpufreq = (unsigned long long *) malloc(sizeof(unsigned long long) * a->nr))
-                   == NULL) {
-                       perror("malloc");
-                       exit(4);
+               SREALLOC(avg_cpufreq, unsigned long long, sizeof(unsigned long long) * a->nr[curr]);
+               if (a->nr[curr] > nr_alloc) {
+                       /* Init additional space allocated */
+                       memset(avg_cpufreq + nr_alloc, 0,
+                              sizeof(unsigned long long) * (a->nr[curr] - nr_alloc));
                }
-               memset(avg_cpufreq, 0, sizeof(unsigned long long) * a->nr);
+               nr_alloc = a->nr[curr];
        }
 
-       if (dis) {
+       if (dish) {
                print_hdr_line(timestamp[!curr], a, FIRST, 7, 9);
        }
 
-       for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
+       for (i = 0; (i < a->nr[curr]) && (i < a->bitmap->b_size + 1); i++) {
 
                /*
                 * The size of a->buf[...] CPU structure may be different from the default
@@ -1914,8 +1989,12 @@ void stub_print_pwr_cpufreq_stats(struct activity *a, int curr, int dispavg)
                 */
                spc = (struct stats_pwr_cpufreq *) ((char *) a->buf[curr] + i * a->msize);
 
+               if (!spc->cpufreq)
+                       /* This CPU is offline: Don't display it */
+                       continue;
+
                /*
-                * Note: a->nr is in [1, NR_CPUS + 1].
+                * Note: @nr[curr] is in [1, NR_CPUS + 1].
                 * Bitmap size is provided for (NR_CPUS + 1) CPUs.
                 * Anyway, NR_CPUS may vary between the version of sysstat
                 * used by sadc to create a file, and the version of sysstat
@@ -1923,45 +2002,44 @@ void stub_print_pwr_cpufreq_stats(struct activity *a, int curr, int dispavg)
                 */
 
                /* Should current CPU (including CPU "all") be displayed? */
-               if (a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))) {
+               if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
+                       /* No */
+                       continue;
 
-                       /* Yes: Display it */
-                       printf("%-11s", timestamp[curr]);
+               printf("%-11s", timestamp[curr]);
 
-                       if (!i) {
-                               /* This is CPU "all" */
-                               cprintf_in(IS_STR, "%s", "     all", 0);
-                       }
-                       else {
-                               cprintf_in(IS_INT, "     %3d", "", i - 1);
-                       }
+               if (!i) {
+                       /* This is CPU "all" */
+                       cprintf_in(IS_STR, "%s", "     all", 0);
+               }
+               else {
+                       cprintf_in(IS_INT, "     %3d", "", i - 1);
+               }
 
-                       if (!dispavg) {
-                               /* Display instantaneous values */
-                               cprintf_f(NO_UNIT, 1, 9, 2,
-                                         ((double) spc->cpufreq) / 100);
-                               printf("\n");
-                               /*
-                                * Will be used to compute the average.
-                                * Note: overflow unlikely to happen but not impossible...
-                                */
-                               avg_cpufreq[i] += spc->cpufreq;
-                       }
-                       else {
-                               /* Display average values */
-                               cprintf_f(NO_UNIT, 1, 9, 2,
-                                         (double) avg_cpufreq[i] / (100 * avg_count));
-                               printf("\n");
-                       }
+               if (!dispavg) {
+                       /* Display instantaneous values */
+                       cprintf_f(NO_UNIT, 1, 9, 2,
+                                 ((double) spc->cpufreq) / 100);
+                       printf("\n");
+                       /*
+                        * Will be used to compute the average.
+                        * Note: Overflow unlikely to happen but not impossible...
+                        */
+                       avg_cpufreq[i] += spc->cpufreq;
+               }
+               else {
+                       /* Display average values */
+                       cprintf_f(NO_UNIT, 1, 9, 2,
+                                 (double) avg_cpufreq[i] / (100 * avg_count));
+                       printf("\n");
                }
        }
 
-       if (dispavg) {
+       if (dispavg && avg_cpufreq) {
                /* Array of CPU frequency no longer needed: Free it! */
-               if (avg_cpufreq) {
-                       free(avg_cpufreq);
-                       avg_cpufreq = NULL;
-               }
+               free(avg_cpufreq);
+               avg_cpufreq = NULL;
+               nr_alloc = 0;
        }
 }
 
@@ -2014,30 +2092,30 @@ void stub_print_pwr_fan_stats(struct activity *a, int curr, int dispavg)
 {
        int i;
        struct stats_pwr_fan *spc;
+       static __nr_t nr_alloc = 0;
        static double *avg_fan = NULL;
        static double *avg_fan_min = NULL;
 
        /* Allocate arrays of fan RPMs */
-       if (!avg_fan) {
-               if ((avg_fan = (double *) malloc(sizeof(double) * a->nr)) == NULL) {
-                       perror("malloc");
-                       exit(4);
+       if (!avg_fan || (a->nr[curr] > nr_alloc)) {
+               SREALLOC(avg_fan, double, sizeof(double) * a->nr[curr]);
+               SREALLOC(avg_fan_min, double, sizeof(double) * a->nr[curr]);
+
+               if (a->nr[curr] > nr_alloc) {
+                       /* Init additional space allocated */
+                       memset(avg_fan + nr_alloc, 0,
+                              sizeof(double) * (a->nr[curr] - nr_alloc));
+                       memset(avg_fan_min + nr_alloc, 0,
+                              sizeof(double) * (a->nr[curr] - nr_alloc));
                }
-               memset(avg_fan, 0, sizeof(double) * a->nr);
-       }
-       if (!avg_fan_min) {
-               if ((avg_fan_min = (double *) malloc(sizeof(double) * a->nr)) == NULL) {
-                       perror("malloc");
-                       exit(4);
-               }
-               memset(avg_fan_min, 0, sizeof(double) * a->nr);
+               nr_alloc = a->nr[curr];
        }
 
-       if (dis) {
+       if (dish) {
                print_hdr_line(timestamp[!curr], a, FIRST, -2, 9);
        }
 
-       for (i = 0; i < a->nr; i++) {
+       for (i = 0; i < a->nr[curr]; i++) {
                spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
 
                printf("%-11s", timestamp[curr]);
@@ -2061,15 +2139,12 @@ void stub_print_pwr_fan_stats(struct activity *a, int curr, int dispavg)
                cprintf_in(IS_STR, " %s\n", spc->device, 0);
        }
 
-       if (dispavg) {
-               if (avg_fan) {
-                       free(avg_fan);
-                       avg_fan = NULL;
-               }
-               if (avg_fan_min) {
-                       free(avg_fan_min);
-                       avg_fan_min = NULL;
-               }
+       if (dispavg && avg_fan) {
+               free(avg_fan);
+               free(avg_fan_min);
+               avg_fan = NULL;
+               avg_fan_min = NULL;
+               nr_alloc = 0;
        }
 }
 
@@ -2122,37 +2197,33 @@ void stub_print_pwr_temp_stats(struct activity *a, int curr, int dispavg)
 {
        int i;
        struct stats_pwr_temp *spc;
+       static __nr_t nr_alloc = 0;
        static double *avg_temp = NULL;
        static double *avg_temp_min = NULL, *avg_temp_max = NULL;
 
        /* Allocate arrays of temperatures */
-       if (!avg_temp) {
-               if ((avg_temp = (double *) malloc(sizeof(double) * a->nr)) == NULL) {
-                       perror("malloc");
-                       exit(4);
+       if (!avg_temp || (a->nr[curr] > nr_alloc)) {
+               SREALLOC(avg_temp, double, sizeof(double) * a->nr[curr]);
+               SREALLOC(avg_temp_min, double, sizeof(double) * a->nr[curr]);
+               SREALLOC(avg_temp_max, double, sizeof(double) * a->nr[curr]);
+
+               if (a->nr[curr] > nr_alloc) {
+                       /* Init additional space allocated */
+                       memset(avg_temp + nr_alloc, 0,
+                              sizeof(double) * (a->nr[curr] - nr_alloc));
+                       memset(avg_temp_min + nr_alloc, 0,
+                              sizeof(double) * (a->nr[curr] - nr_alloc));
+                       memset(avg_temp_max + nr_alloc, 0,
+                              sizeof(double) * (a->nr[curr] - nr_alloc));
                }
-               memset(avg_temp, 0, sizeof(double) * a->nr);
-       }
-       if (!avg_temp_min) {
-               if ((avg_temp_min = (double *) malloc(sizeof(double) * a->nr)) == NULL) {
-                       perror("malloc");
-                       exit(4);
-               }
-               memset(avg_temp_min, 0, sizeof(double) * a->nr);
-       }
-       if (!avg_temp_max) {
-               if ((avg_temp_max = (double *) malloc(sizeof(double) * a->nr)) == NULL) {
-                       perror("malloc");
-                       exit(4);
-               }
-               memset(avg_temp_max, 0, sizeof(double) * a->nr);
+               nr_alloc = a->nr[curr];
        }
 
-       if (dis) {
+       if (dish) {
                print_hdr_line(timestamp[!curr], a, FIRST, -2, 9);
        }
 
-       for (i = 0; i < a->nr; i++) {
+       for (i = 0; i < a->nr[curr]; i++) {
                spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
 
                printf("%-11s", timestamp[curr]);
@@ -2182,19 +2253,14 @@ void stub_print_pwr_temp_stats(struct activity *a, int curr, int dispavg)
                cprintf_in(IS_STR, " %s\n", spc->device, 0);
        }
 
-       if (dispavg) {
-               if (avg_temp) {
-                       free(avg_temp);
-                       avg_temp = NULL;
-               }
-               if (avg_temp_min) {
-                       free(avg_temp_min);
-                       avg_temp_min = NULL;
-               }
-               if (avg_temp_max) {
-                       free(avg_temp_max);
-                       avg_temp_max = NULL;
-               }
+       if (dispavg && avg_temp) {
+               free(avg_temp);
+               free(avg_temp_min);
+               free(avg_temp_max);
+               avg_temp = NULL;
+               avg_temp_min = NULL;
+               avg_temp_max = NULL;
+               nr_alloc = 0;
        }
 }
 
@@ -2247,37 +2313,33 @@ void stub_print_pwr_in_stats(struct activity *a, int curr, int dispavg)
 {
        int i;
        struct stats_pwr_in *spc;
+       static __nr_t nr_alloc = 0;
        static double *avg_in = NULL;
        static double *avg_in_min = NULL, *avg_in_max = NULL;
 
        /* Allocate arrays of voltage inputs */
-       if (!avg_in) {
-               if ((avg_in = (double *) malloc(sizeof(double) * a->nr)) == NULL) {
-                       perror("malloc");
-                       exit(4);
+       if (!avg_in || (a->nr[curr] > nr_alloc)) {
+               SREALLOC(avg_in, double, sizeof(double) * a->nr[curr]);
+               SREALLOC(avg_in_min, double, sizeof(double) * a->nr[curr]);
+               SREALLOC(avg_in_max, double, sizeof(double) * a->nr[curr]);
+
+               if (a->nr[curr] > nr_alloc) {
+                       /* Init additional space allocated */
+                       memset(avg_in + nr_alloc, 0,
+                              sizeof(double) * (a->nr[curr] - nr_alloc));
+                       memset(avg_in_min + nr_alloc, 0,
+                              sizeof(double) * (a->nr[curr] - nr_alloc));
+                       memset(avg_in_max + nr_alloc, 0,
+                              sizeof(double) * (a->nr[curr] - nr_alloc));
                }
-               memset(avg_in, 0, sizeof(double) * a->nr);
-       }
-       if (!avg_in_min) {
-               if ((avg_in_min = (double *) malloc(sizeof(double) * a->nr)) == NULL) {
-                       perror("malloc");
-                       exit(4);
-               }
-               memset(avg_in_min, 0, sizeof(double) * a->nr);
-       }
-       if (!avg_in_max) {
-               if ((avg_in_max = (double *) malloc(sizeof(double) * a->nr)) == NULL) {
-                       perror("malloc");
-                       exit(4);
-               }
-               memset(avg_in_max, 0, sizeof(double) * a->nr);
+               nr_alloc = a->nr[curr];
        }
 
-       if (dis) {
+       if (dish) {
                print_hdr_line(timestamp[!curr], a, FIRST, -2, 9);
        }
 
-       for (i = 0; i < a->nr; i++) {
+       for (i = 0; i < a->nr[curr]; i++) {
                spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
 
                printf("%-11s", timestamp[curr]);
@@ -2307,19 +2369,14 @@ void stub_print_pwr_in_stats(struct activity *a, int curr, int dispavg)
                cprintf_in(IS_STR, " %s\n", spc->device, 0);
        }
 
-       if (dispavg) {
-               if (avg_in) {
-                       free(avg_in);
-                       avg_in = NULL;
-               }
-               if (avg_in_min) {
-                       free(avg_in_min);
-                       avg_in_min = NULL;
-               }
-               if (avg_in_max) {
-                       free(avg_in_max);
-                       avg_in_max = NULL;
-               }
+       if (dispavg && avg_in) {
+               free(avg_in);
+               free(avg_in_min);
+               free(avg_in_max);
+               avg_in = NULL;
+               avg_in_min = NULL;
+               avg_in_max = NULL;
+               nr_alloc = 0;
        }
 }
 
@@ -2374,7 +2431,9 @@ void stub_print_huge_stats(struct activity *a, int curr, int dispavg)
                *smc = (struct stats_huge *) a->buf[curr];
        static unsigned long long
                avg_frhkb = 0,
-               avg_tlhkb = 0;
+               avg_tlhkb = 0,
+               avg_rsvdhkb = 0,
+               avg_surphkb = 0;
        int unit = NO_UNIT;
 
        if (DISPLAY_UNIT(flags)) {
@@ -2382,7 +2441,7 @@ void stub_print_huge_stats(struct activity *a, int curr, int dispavg)
                unit = UNIT_KILOBYTE;
        }
 
-       if (dis) {
+       if (dish) {
                print_hdr_line(timestamp[!curr], a, FIRST, 0, 9);
        }
 
@@ -2395,11 +2454,16 @@ void stub_print_huge_stats(struct activity *a, int curr, int dispavg)
                cprintf_pc(DISPLAY_UNIT(flags), 1, 9, 2,
                           smc->tlhkb ?
                           SP_VALUE(smc->frhkb, smc->tlhkb, smc->tlhkb) : 0.0);
+               cprintf_u64(unit, 2, 9,
+                           (unsigned long long) smc->rsvdhkb,
+                           (unsigned long long) (smc->surphkb));
                printf("\n");
 
                /* Will be used to compute the average */
                avg_frhkb += smc->frhkb;
                avg_tlhkb += smc->tlhkb;
+               avg_rsvdhkb += smc->rsvdhkb;
+               avg_surphkb += smc->surphkb;
        }
        else {
                /* Display average values */
@@ -2413,10 +2477,13 @@ void stub_print_huge_stats(struct activity *a, int curr, int dispavg)
                           SP_VALUE((double) avg_frhkb / avg_count,
                                    (double) avg_tlhkb / avg_count,
                                    (double) avg_tlhkb / avg_count) : 0.0);
+               cprintf_f(unit, 2, 9, 0,
+                         (double) avg_rsvdhkb / avg_count,
+                         (double) avg_surphkb / avg_count);
                printf("\n");
 
                /* Reset average counters */
-               avg_frhkb = avg_tlhkb = 0;
+               avg_frhkb = avg_tlhkb = avg_rsvdhkb = avg_surphkb = 0;
        }
 }
 
@@ -2473,11 +2540,11 @@ void print_pwr_wghfreq_stats(struct activity *a, int prev, int curr,
        struct stats_pwr_wghfreq *spc, *spp, *spc_k, *spp_k;
        unsigned long long tis, tisfreq;
 
-       if (dis) {
+       if (dish) {
                print_hdr_line(timestamp[!curr], a, FIRST, 7, 9);
        }
 
-       for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
+       for (i = 0; (i < a->nr[curr]) && (i < a->bitmap->b_size + 1); i++) {
 
                /*
                 * The size of a->buf[...] CPU structure may be different from the default
@@ -2497,39 +2564,40 @@ void print_pwr_wghfreq_stats(struct activity *a, int prev, int curr,
                 */
 
                /* Should current CPU (including CPU "all") be displayed? */
-               if (a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))) {
-
-                       /* Yes: Display it */
-                       printf("%-11s", timestamp[curr]);
+               if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
+                       /* No */
+                       continue;
 
-                       if (!i) {
-                               /* This is CPU "all" */
-                               cprintf_in(IS_STR, "%s", "     all", 0);
-                       }
-                       else {
-                               cprintf_in(IS_INT, "     %3d", "", i - 1);
-                       }
+               /* Yes: Display it */
+               printf("%-11s", timestamp[curr]);
 
-                       tisfreq = 0;
-                       tis = 0;
+               if (!i) {
+                       /* This is CPU "all" */
+                       cprintf_in(IS_STR, "%s", "     all", 0);
+               }
+               else {
+                       cprintf_in(IS_INT, "     %3d", "", i - 1);
+               }
 
-                       for (k = 0; k < a->nr2; k++) {
+               tisfreq = 0;
+               tis = 0;
 
-                               spc_k = (struct stats_pwr_wghfreq *) ((char *) spc + k * a->msize);
-                               if (!spc_k->freq)
-                                       break;
-                               spp_k = (struct stats_pwr_wghfreq *) ((char *) spp + k * a->msize);
+               for (k = 0; k < a->nr2; k++) {
 
-                               tisfreq += (spc_k->freq / 1000) *
-                                          (spc_k->time_in_state - spp_k->time_in_state);
-                               tis     += (spc_k->time_in_state - spp_k->time_in_state);
-                       }
+                       spc_k = (struct stats_pwr_wghfreq *) ((char *) spc + k * a->msize);
+                       if (!spc_k->freq)
+                               break;
+                       spp_k = (struct stats_pwr_wghfreq *) ((char *) spp + k * a->msize);
 
-                       /* Display weighted frequency for current CPU */
-                       cprintf_f(NO_UNIT, 1, 9, 2,
-                                 tis ? ((double) tisfreq) / tis : 0.0);
-                       printf("\n");
+                       tisfreq += (spc_k->freq / 1000) *
+                                  (spc_k->time_in_state - spp_k->time_in_state);
+                       tis     += (spc_k->time_in_state - spp_k->time_in_state);
                }
+
+               /* Display weighted frequency for current CPU */
+               cprintf_f(NO_UNIT, 1, 9, 2,
+                         tis ? ((double) tisfreq) / tis : 0.0);
+               printf("\n");
        }
 }
 
@@ -2550,19 +2618,15 @@ void stub_print_pwr_usb_stats(struct activity *a, int curr, int dispavg)
        char fmt[16];
        struct stats_pwr_usb *suc, *sum;
 
-       if (dis) {
+       if (dish) {
                printf("\n%-11s     BUS  idvendor    idprod  maxpower",
                       (dispavg ? _("Summary:") : timestamp[!curr]));
                printf(" %-*s product\n", MAX_MANUF_LEN - 1, "manufact");
        }
 
-       for (i = 0; i < a->nr; i++) {
+       for (i = 0; i < a->nr[curr]; i++) {
                suc = (struct stats_pwr_usb *) ((char *) a->buf[curr] + i * a->msize);
 
-               if (!suc->bus_nr)
-                       /* Bus#0 doesn't exist: We are at the end of the list */
-                       break;
-
                printf("%-11s", (dispavg ? _("Summary:") : timestamp[curr]));
                cprintf_in(IS_INT, "  %6d", "", suc->bus_nr);
                cprintf_x(2, 9,
@@ -2578,7 +2642,7 @@ void stub_print_pwr_usb_stats(struct activity *a, int curr, int dispavg)
 
                if (!dispavg) {
                        /* Save current USB device in summary list */
-                       for (j = 0; j < a->nr; j++) {
+                       for (j = 0; j < a->nr_allocated; j++) {
                                sum = (struct stats_pwr_usb *) ((char *) a->buf[2] + j * a->msize);
 
                                if ((sum->bus_nr     == suc->bus_nr) &&
@@ -2592,22 +2656,19 @@ void stub_print_pwr_usb_stats(struct activity *a, int curr, int dispavg)
                                         * Save USB device in summary list.
                                         */
                                        *sum = *suc;
+                                       a->nr[2] = j + 1;
                                        break;
                                }
-                               if (j == a->nr - 1) {
-                                       /*
-                                        * This is the last slot and
-                                        * we still havent't found the device.
-                                        * So create a dummy device here.
-                                        */
-                                       sum->bus_nr = ~0;
-                                       sum->vendor_id = sum->product_id = 0;
-                                       sum->bmaxpower = 0;
-                                       sum->manufacturer[0] = '\0';
-                                       snprintf(sum->product, MAX_PROD_LEN, "%s",
-                                                _("Other devices not listed here"));
-                                       sum->product[MAX_PROD_LEN - 1] = '\0';
-                               }
+                       }
+                       if (j == a->nr_allocated) {
+                               /*
+                                * No free slot has been found for current device.
+                                * So enlarge buffers then save device in list.
+                                */
+                               reallocate_all_buffers(a, j);
+                               sum = (struct stats_pwr_usb *) ((char *) a->buf[2] + j * a->msize);
+                               *sum = *suc;
+                               a->nr[2] = j + 1;
                        }
                }
        }
@@ -2654,14 +2715,15 @@ __print_funct_t print_avg_pwr_usb_stats(struct activity *a, int prev, int curr,
  *
  * IN:
  * @a          Activity structure with statistics.
+ * @prev       Index in array where stats used as reference are.
  * @curr       Index in array for current sample statistics.
  * @dispavg    TRUE if displaying average statistics.
  ***************************************************************************
  */
-__print_funct_t stub_print_filesystem_stats(struct activity *a, int curr, int dispavg)
+__print_funct_t stub_print_filesystem_stats(struct activity *a, int prev, int curr, int dispavg)
 {
-       int i, j;
-       struct stats_filesystem *sfc, *sfm;
+       int i, j, j0, found;
+       struct stats_filesystem *sfc, *sfp, *sfm;
        int unit = NO_UNIT;
 
        if (DISPLAY_UNIT(flags)) {
@@ -2669,41 +2731,76 @@ __print_funct_t stub_print_filesystem_stats(struct activity *a, int curr, int di
                unit = UNIT_BYTE;
        }
 
-       if (dis) {
+       if (dish || DISPLAY_ZERO_OMIT(flags)) {
                print_hdr_line((dispavg ? _("Summary:") : timestamp[!curr]),
                               a, FIRST + DISPLAY_MOUNT(a->opt_flags), -1, 9);
        }
 
-       for (i = 0; i < a->nr; i++) {
+       for (i = 0; i < a->nr[curr]; i++) {
                sfc = (struct stats_filesystem *) ((char *) a->buf[curr] + i * a->msize);
 
-               if (!sfc->f_blocks)
-                       /* Size of filesystem is zero: We are at the end of the list */
-                       break;
+               if (a->item_list != NULL) {
+                       /* A list of devices has been entered on the command line */
+                       if (!search_list_item(a->item_list,
+                                             DISPLAY_MOUNT(a->opt_flags) ? sfc->mountp : sfc->fs_name))
+                               /* Device not found */
+                               continue;
+               }
+
+               found = FALSE;
+               if (DISPLAY_ZERO_OMIT(flags) && !dispavg) {
 
-               printf("%-11s", (dispavg ? _("Summary:") : timestamp[curr]));
-               cprintf_f(unit, 2, 9, 0,
-                         unit < 0 ? (double) sfc->f_bfree / 1024 / 1024 : (double) sfc->f_bfree,
-                         unit < 0 ? (double) (sfc->f_blocks - sfc->f_bfree) / 1024 / 1024 :
-                                    (double) (sfc->f_blocks - sfc->f_bfree));
-               cprintf_pc(DISPLAY_UNIT(flags), 2, 9, 2,
-                          /* f_blocks is not zero. But test it anyway ;-) */
-                          sfc->f_blocks ? SP_VALUE(sfc->f_bfree, sfc->f_blocks, sfc->f_blocks)
-                          : 0.0,
-                          sfc->f_blocks ? SP_VALUE(sfc->f_bavail, sfc->f_blocks, sfc->f_blocks)
-                          : 0.0);
-               cprintf_u64(NO_UNIT, 2, 9,
-                           (unsigned long long) sfc->f_ffree,
-                           (unsigned long long) (sfc->f_files - sfc->f_ffree));
-               cprintf_pc(DISPLAY_UNIT(flags), 1, 9, 2,
-                          sfc->f_files ? SP_VALUE(sfc->f_ffree, sfc->f_files, sfc->f_files)
-                          : 0.0);
-               cprintf_in(IS_STR, " %s\n",
-                          DISPLAY_MOUNT(a->opt_flags) ? sfc->mountp : sfc->fs_name, 0);
+                       if (a->nr[prev] > 0) {
+                               /* Look for corresponding fs in previous iteration */
+                               j = i;
+
+                               if (j >= a->nr[prev]) {
+                                       j = a->nr[prev] - 1;
+                               }
+
+                               j0 = j;
+
+                               do {
+                                       sfp = (struct stats_filesystem *) ((char *) a->buf[prev] + j * a->msize);
+                                       if (!strcmp(sfp->fs_name, sfc->fs_name)) {
+                                               found = TRUE;
+                                               break;
+                                       }
+                                       if (++j >= a->nr[prev]) {
+                                               j = 0;
+                                       }
+                               }
+                               while (j != j0);
+                       }
+               }
+
+               if (!DISPLAY_ZERO_OMIT(flags) || dispavg || WANT_SINCE_BOOT(flags) || !found ||
+                   (found && memcmp(sfp, sfc, STATS_FILESYSTEM_SIZE2CMP))) {
+
+                       printf("%-11s", (dispavg ? _("Summary:") : timestamp[curr]));
+                       cprintf_f(unit, 2, 9, 0,
+                                 unit < 0 ? (double) sfc->f_bfree / 1024 / 1024 : (double) sfc->f_bfree,
+                                 unit < 0 ? (double) (sfc->f_blocks - sfc->f_bfree) / 1024 / 1024 :
+                                            (double) (sfc->f_blocks - sfc->f_bfree));
+                       cprintf_pc(DISPLAY_UNIT(flags), 2, 9, 2,
+                                  /* f_blocks is not zero. But test it anyway ;-) */
+                                  sfc->f_blocks ? SP_VALUE(sfc->f_bfree, sfc->f_blocks, sfc->f_blocks)
+                                  : 0.0,
+                                  sfc->f_blocks ? SP_VALUE(sfc->f_bavail, sfc->f_blocks, sfc->f_blocks)
+                                  : 0.0);
+                       cprintf_u64(NO_UNIT, 2, 9,
+                                   (unsigned long long) sfc->f_ffree,
+                                   (unsigned long long) (sfc->f_files - sfc->f_ffree));
+                       cprintf_pc(DISPLAY_UNIT(flags), 1, 9, 2,
+                                  sfc->f_files ? SP_VALUE(sfc->f_ffree, sfc->f_files, sfc->f_files)
+                                  : 0.0);
+                       cprintf_in(IS_STR, " %s\n",
+                                  DISPLAY_MOUNT(a->opt_flags) ? sfc->mountp : sfc->fs_name, 0);
+               }
 
                if (!dispavg) {
                        /* Save current filesystem in summary list */
-                       for (j = 0; j < a->nr; j++) {
+                       for (j = 0; j < a->nr_allocated; j++) {
                                sfm = (struct stats_filesystem *) ((char *) a->buf[2] + j * a->msize);
 
                                if (!strcmp(sfm->fs_name, sfc->fs_name) ||
@@ -2713,9 +2810,22 @@ __print_funct_t stub_print_filesystem_stats(struct activity *a, int curr, int di
                                         * or free slot (end of list).
                                         */
                                        *sfm = *sfc;
+                                       if (j >= a->nr[2]) {
+                                               a->nr[2] = j + 1;
+                                       }
                                        break;
                                }
                        }
+                       if (j == a->nr_allocated) {
+                               /*
+                                * No free slot has been found for current filesystem.
+                                * So enlarge buffers then save filesystem in list.
+                                */
+                               reallocate_all_buffers(a, j);
+                               sfm = (struct stats_filesystem *) ((char *) a->buf[2] + j * a->msize);
+                               *sfm = *sfc;
+                               a->nr[2] = j + 1;
+                       }
                }
        }
 }
@@ -2734,7 +2844,7 @@ __print_funct_t stub_print_filesystem_stats(struct activity *a, int curr, int di
 __print_funct_t print_filesystem_stats(struct activity *a, int prev, int curr,
                                       unsigned long long itv)
 {
-       stub_print_filesystem_stats(a, curr, FALSE);
+       stub_print_filesystem_stats(a, prev, curr, FALSE);
 }
 
 /*
@@ -2751,7 +2861,7 @@ __print_funct_t print_filesystem_stats(struct activity *a, int prev, int curr,
 __print_funct_t print_avg_filesystem_stats(struct activity *a, int prev, int curr,
                                           unsigned long long itv)
 {
-       stub_print_filesystem_stats(a, 2, TRUE);
+       stub_print_filesystem_stats(a, prev, 2, TRUE);
 }
 
 /*
@@ -2768,21 +2878,54 @@ __print_funct_t print_avg_filesystem_stats(struct activity *a, int prev, int cur
 __print_funct_t print_fchost_stats(struct activity *a, int prev, int curr,
                                   unsigned long long itv)
 {
-       int i;
-       struct stats_fchost *sfcc,*sfcp;
+       int i, j, j0, found;
+       struct stats_fchost *sfcc, *sfcp, sfczero;
 
-       if (dis) {
+       memset(&sfczero, 0, sizeof(struct stats_fchost));
+
+       if (dish) {
                print_hdr_line(timestamp[!curr], a, FIRST, -1, 9);
        }
 
-       for (i = 0; i < a->nr; i++) {
-
+       for (i = 0; i < a->nr[curr]; i++) {
                sfcc = (struct stats_fchost *) ((char *) a->buf[curr] + i * a->msize);
-               sfcp = (struct stats_fchost *) ((char *) a->buf[prev] + i * a->msize);
 
-               if (!sfcc->fchost_name[0])
-                       /* We are at the end of the list */
-                       break;
+               if (WANT_SINCE_BOOT(flags)) {
+                       sfcp = (struct stats_fchost *) ((char *) a->buf[prev]);
+                       found = TRUE;
+               }
+               else {
+                       found = FALSE;
+
+                       if (a->nr[prev] > 0) {
+                               /* Look for corresponding structure in previous iteration */
+                               j = i;
+
+                               if (j >= a->nr[prev]) {
+                                       j = a->nr[prev] - 1;
+                               }
+
+                               j0 = j;
+
+                               do {
+                                       sfcp = (struct stats_fchost *) ((char *) a->buf[prev] + j * a->msize);
+                                       if (!strcmp(sfcc->fchost_name, sfcp->fchost_name)) {
+                                               found = TRUE;
+                                               break;
+                                       }
+
+                                       if (++j >= a->nr[prev]) {
+                                               j = 0;
+                                       }
+                               }
+                               while (j != j0);
+                       }
+               }
+
+               if (!found) {
+                       /* This is a newly registered host */
+                       sfcp = &sfczero;
+               }
 
                printf("%-11s", timestamp[curr]);
                cprintf_f(NO_UNIT, 4, 9, 2,
@@ -2808,55 +2951,72 @@ __print_funct_t print_fchost_stats(struct activity *a, int prev, int curr,
 __print_funct_t print_softnet_stats(struct activity *a, int prev, int curr,
                                    unsigned long long itv)
 {
+       int i;
        struct stats_softnet
                *ssnc = (struct stats_softnet *) a->buf[curr],
                *ssnp = (struct stats_softnet *) a->buf[prev];
-       int i;
+       unsigned char offline_cpu_bitmap[BITMAP_SIZE(NR_CPUS)] = {0};
 
-       if (dis) {
+       if (dish || DISPLAY_ZERO_OMIT(flags)) {
                print_hdr_line(timestamp[!curr], a, FIRST, 7, 9);
        }
 
-       for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
+       /*
+        * @nr[curr] cannot normally be greater than @nr_ini
+        * (since @nr_ini counts up all CPU, even those offline).
+        * If this happens, it may be because the machine has been
+        * restarted with more CPU and no LINUX_RESTART has been
+        * inserted in file.
+        */
+       if (a->nr[curr] > a->nr_ini) {
+               a->nr_ini = a->nr[curr];
+       }
 
-               /*
-                * The size of a->buf[...] CPU structure may be different from the default
-                * sizeof(struct stats_pwr_cpufreq) value if data have been read from a file!
-                * That's why we don't use a syntax like:
-                * ssnc = (struct stats_softnet *) a->buf[...] + i;
-                 */
-                ssnc = (struct stats_softnet *) ((char *) a->buf[curr] + i * a->msize);
-                ssnp = (struct stats_softnet *) ((char *) a->buf[prev] + i * a->msize);
+       /* Compute statistics for CPU "all" */
+       get_global_soft_statistics(a, prev, curr, flags, offline_cpu_bitmap);
+
+       for (i = 0; (i < a->nr_ini) && (i < a->bitmap->b_size + 1); i++) {
 
                /*
+                * Should current CPU (including CPU "all") be displayed?
                 * Note: a->nr is in [1, NR_CPUS + 1].
                 * Bitmap size is provided for (NR_CPUS + 1) CPUs.
                 * Anyway, NR_CPUS may vary between the version of sysstat
                 * used by sadc to create a file, and the version of sysstat
                 * used by sar to read it...
                 */
+               if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))) ||
+                   offline_cpu_bitmap[i >> 3] & (1 << (i & 0x07)))
+                       /* No */
+                       continue;
+               /*
+                * The size of a->buf[...] CPU structure may be different from the default
+                * sizeof(struct stats_pwr_cpufreq) value if data have been read from a file!
+                * That's why we don't use a syntax like:
+                * ssnc = (struct stats_softnet *) a->buf[...] + i;
+                 */
+                ssnc = (struct stats_softnet *) ((char *) a->buf[curr] + i * a->msize);
+                ssnp = (struct stats_softnet *) ((char *) a->buf[prev] + i * a->msize);
 
-               /* Should current CPU (including CPU "all") be displayed? */
-               if (a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))) {
-
-                       /* Yes: Display it */
-                       printf("%-11s", timestamp[curr]);
+               if (DISPLAY_ZERO_OMIT(flags) && !memcmp(ssnp, ssnc, STATS_SOFTNET_SIZE))
+                       continue;
 
-                       if (!i) {
-                               /* This is CPU "all" */
-                               cprintf_in(IS_STR, " %s", "    all", 0);
-                       }
-                       else {
-                               cprintf_in(IS_INT, " %7d", "", i - 1);
-                       }
+               printf("%-11s", timestamp[curr]);
 
-                       cprintf_f(NO_UNIT, 5, 9, 2,
-                                 S_VALUE(ssnp->processed,    ssnc->processed,    itv),
-                                 S_VALUE(ssnp->dropped,      ssnc->dropped,      itv),
-                                 S_VALUE(ssnp->time_squeeze, ssnc->time_squeeze, itv),
-                                 S_VALUE(ssnp->received_rps, ssnc->received_rps, itv),
-                                 S_VALUE(ssnp->flow_limit,   ssnc->flow_limit,   itv));
-                       printf("\n");
+               if (!i) {
+                       /* This is CPU "all" */
+                       cprintf_in(IS_STR, " %s", "    all", 0);
                }
+               else {
+                       cprintf_in(IS_INT, " %7d", "", i - 1);
+               }
+
+               cprintf_f(NO_UNIT, 5, 9, 2,
+                         S_VALUE(ssnp->processed,    ssnc->processed,    itv),
+                         S_VALUE(ssnp->dropped,      ssnc->dropped,      itv),
+                         S_VALUE(ssnp->time_squeeze, ssnc->time_squeeze, itv),
+                         S_VALUE(ssnp->received_rps, ssnc->received_rps, itv),
+                         S_VALUE(ssnp->flow_limit,   ssnc->flow_limit,   itv));
+               printf("\n");
        }
 }