]> granicus.if.org Git - sysstat/blobdiff - json_stats.c
Update README.md file
[sysstat] / json_stats.c
index b0ba12e17f730b8bb7a97b669daacf371dcdfeae..b056b486e5e76910d0cfe8c94d3d9f20531c18ca 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * json_stats.c: Funtions used by sadf to display statistics in JSON format.
- * (C) 1999-2016 by Sebastien GODARD (sysstat <at> orange.fr)
+ * (C) 1999-2018 by Sebastien GODARD (sysstat <at> orange.fr)
  *
  ***************************************************************************
  * This program is free software; you can redistribute it and/or modify it *
@@ -24,7 +24,6 @@
 #include <stdarg.h>
 
 #include "sa.h"
-#include "sadf.h"
 #include "ioconf.h"
 #include "json_stats.h"
 
@@ -37,7 +36,6 @@
 #endif
 
 extern unsigned int flags;
-extern unsigned int dm_major;
 
 /*
  ***************************************************************************
@@ -103,31 +101,46 @@ void json_markup_power_management(int tab, int action)
  * @a          Activity structure with statistics.
  * @curr       Index in array for current sample statistics.
  * @tab                Indentation in output.
- * @g_itv      Interval of time in jiffies mutliplied by the number of
- *             processors.
+ * @itv                Interval of time in 1/100th of a second (independent of the
+ *             number of processors). Unused here.
  ***************************************************************************
  */
 __print_funct_t json_print_cpu_stats(struct activity *a, int curr, int tab,
-                                    unsigned long long g_itv)
+                                    unsigned long long itv)
 {
-       int i, cpu_offline;
+       int i;
        int sep = FALSE;
+       unsigned long long deltot_jiffies = 1;
        struct stats_cpu *scc, *scp;
-       char cpuno[8];
+       unsigned char offline_cpu_bitmap[BITMAP_SIZE(NR_CPUS)] = {0};
+       char cpuno[16];
 
        xprintf(tab++, "\"cpu-load\": [");
 
-       for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
+       /* @nr[curr] cannot normally be greater than @nr_ini */
+       if (a->nr[curr] > a->nr_ini) {
+               a->nr_ini = a->nr[curr];
+       }
 
-               scc = (struct stats_cpu *) ((char *) a->buf[curr]  + i * a->msize);
-               scp = (struct stats_cpu *) ((char *) a->buf[!curr] + 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, !curr, 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? */
-               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: Display current CPU stats */
+               scc = (struct stats_cpu *) ((char *) a->buf[curr]  + i * a->msize);
+               scp = (struct stats_cpu *) ((char *) a->buf[!curr] + i * a->msize);
 
                if (sep) {
                        printf(",\n");
@@ -137,40 +150,30 @@ __print_funct_t json_print_cpu_stats(struct activity *a, int curr, int tab,
                if (!i) {
                        /* This is CPU "all" */
                        strcpy(cpuno, "all");
+
+                       if (a->nr_ini == 1) {
+                               /*
+                                * This is a UP machine. In this case
+                                * interval has still not been calculated.
+                                */
+                               deltot_jiffies = get_per_cpu_interval(scc, scp);
+                       }
+                       if (!deltot_jiffies) {
+                               /* CPU "all" cannot be tickless */
+                               deltot_jiffies = 1;
+                       }
                }
                else {
                        sprintf(cpuno, "%d", 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.)
+                        * Recalculate interval for current proc.
+                        * If result is 0 then current CPU is a tickless one.
                         */
-                       if ((scc->cpu_user    + scc->cpu_nice + scc->cpu_sys   +
-                            scc->cpu_iowait  + scc->cpu_idle + scc->cpu_steal +
-                            scc->cpu_hardirq + scc->cpu_softirq) == 0) {
-                               /*
-                                * 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.
-                                */
-                               *scc = *scp;
-
-                               g_itv = 0;
-                               cpu_offline = TRUE;
-                       }
-                       else {
-                               /*
-                                * Recalculate interval for current proc.
-                                * If result is 0 then current CPU is a tickless one.
-                                */
-                               g_itv = get_per_cpu_interval(scc, scp);
-                               cpu_offline = FALSE;
-                       }
+                       deltot_jiffies = get_per_cpu_interval(scc, scp);
 
-                       if (!g_itv) {
-                               /* Current CPU is offline or tickless */
+                       if (!deltot_jiffies) {
+                               /* Current CPU is tickless */
                                if (DISPLAY_CPU_DEF(a->opt_flags)) {
                                        xprintf0(tab, "{\"cpu\": \"%d\", "
                                                 "\"user\": %.2f, "
@@ -179,8 +182,7 @@ __print_funct_t json_print_cpu_stats(struct activity *a, int curr, int tab,
                                                 "\"iowait\": %.2f, "
                                                 "\"steal\": %.2f, "
                                                 "\"idle\": %.2f}",
-                                                i - 1, 0.0, 0.0, 0.0, 0.0, 0.0,
-                                                cpu_offline ? 0.0 : 100.0);
+                                                i - 1, 0.0, 0.0, 0.0, 0.0, 0.0, 100.0);
                                }
                                else if (DISPLAY_CPU_ALL(a->opt_flags)) {
                                        xprintf0(tab, "{\"cpu\": \"%d\", "
@@ -195,8 +197,7 @@ __print_funct_t json_print_cpu_stats(struct activity *a, int curr, int tab,
                                                 "\"gnice\": %.2f, "
                                                 "\"idle\": %.2f}",
                                                 i - 1, 0.0, 0.0, 0.0, 0.0,
-                                                0.0, 0.0, 0.0, 0.0, 0.0,
-                                                cpu_offline ? 0.0 : 100.0);
+                                                0.0, 0.0, 0.0, 0.0, 0.0, 100.0);
                                }
                                continue;
                        }
@@ -211,16 +212,16 @@ __print_funct_t json_print_cpu_stats(struct activity *a, int curr, int tab,
                                 "\"steal\": %.2f, "
                                 "\"idle\": %.2f}",
                                 cpuno,
-                                ll_sp_value(scp->cpu_user, scc->cpu_user, g_itv),
-                                ll_sp_value(scp->cpu_nice, scc->cpu_nice, g_itv),
+                                ll_sp_value(scp->cpu_user, scc->cpu_user, deltot_jiffies),
+                                ll_sp_value(scp->cpu_nice, scc->cpu_nice, deltot_jiffies),
                                 ll_sp_value(scp->cpu_sys + scp->cpu_hardirq + scp->cpu_softirq,
                                             scc->cpu_sys + scc->cpu_hardirq + scc->cpu_softirq,
-                                            g_itv),
-                                ll_sp_value(scp->cpu_iowait, scc->cpu_iowait, g_itv),
-                                ll_sp_value(scp->cpu_steal, scc->cpu_steal, g_itv),
+                                            deltot_jiffies),
+                                ll_sp_value(scp->cpu_iowait, scc->cpu_iowait, deltot_jiffies),
+                                ll_sp_value(scp->cpu_steal, scc->cpu_steal, deltot_jiffies),
                                 scc->cpu_idle < scp->cpu_idle ?
                                 0.0 :
-                                ll_sp_value(scp->cpu_idle, scc->cpu_idle, g_itv));
+                                ll_sp_value(scp->cpu_idle, scc->cpu_idle, deltot_jiffies));
                }
                else if (DISPLAY_CPU_ALL(a->opt_flags)) {
                        xprintf0(tab, "{\"cpu\": \"%s\", "
@@ -238,21 +239,21 @@ __print_funct_t json_print_cpu_stats(struct activity *a, int curr, int tab,
                                 (scc->cpu_user - scc->cpu_guest) < (scp->cpu_user - scp->cpu_guest) ?
                                 0.0 :
                                 ll_sp_value(scp->cpu_user - scp->cpu_guest,
-                                            scc->cpu_user - scc->cpu_guest, g_itv),
+                                            scc->cpu_user - scc->cpu_guest, deltot_jiffies),
                                 (scc->cpu_nice - scc->cpu_guest_nice) < (scp->cpu_nice - scp->cpu_guest_nice) ?
                                 0.0 :
                                 ll_sp_value(scp->cpu_nice - scp->cpu_guest_nice,
-                                            scc->cpu_nice - scc->cpu_guest_nice, g_itv),
-                                ll_sp_value(scp->cpu_sys, scc->cpu_sys, g_itv),
-                                ll_sp_value(scp->cpu_iowait, scc->cpu_iowait, g_itv),
-                                ll_sp_value(scp->cpu_steal, scc->cpu_steal, g_itv),
-                                ll_sp_value(scp->cpu_hardirq, scc->cpu_hardirq, g_itv),
-                                ll_sp_value(scp->cpu_softirq, scc->cpu_softirq, g_itv),
-                                ll_sp_value(scp->cpu_guest, scc->cpu_guest, g_itv),
-                                ll_sp_value(scp->cpu_guest_nice, scc->cpu_guest_nice, g_itv),
+                                            scc->cpu_nice - scc->cpu_guest_nice, deltot_jiffies),
+                                ll_sp_value(scp->cpu_sys, scc->cpu_sys, deltot_jiffies),
+                                ll_sp_value(scp->cpu_iowait, scc->cpu_iowait, deltot_jiffies),
+                                ll_sp_value(scp->cpu_steal, scc->cpu_steal, deltot_jiffies),
+                                ll_sp_value(scp->cpu_hardirq, scc->cpu_hardirq, deltot_jiffies),
+                                ll_sp_value(scp->cpu_softirq, scc->cpu_softirq, deltot_jiffies),
+                                ll_sp_value(scp->cpu_guest, scc->cpu_guest, deltot_jiffies),
+                                ll_sp_value(scp->cpu_guest_nice, scc->cpu_guest_nice, deltot_jiffies),
                                 scc->cpu_idle < scp->cpu_idle ?
                                 0.0 :
-                                ll_sp_value(scp->cpu_idle, scc->cpu_idle, g_itv));
+                                ll_sp_value(scp->cpu_idle, scc->cpu_idle, deltot_jiffies));
                }
        }
 
@@ -268,7 +269,7 @@ __print_funct_t json_print_cpu_stats(struct activity *a, int curr, int tab,
  * @a          Activity structure with statistics.
  * @curr       Index in array for current sample statistics.
  * @tab                Indentation in output.
- * @itv                Interval of time in jiffies.
+ * @itv                Interval of time in 1/100th of a second.
  ***************************************************************************
  */
 __print_funct_t json_print_pcsw_stats(struct activity *a, int curr, int tab,
@@ -294,7 +295,7 @@ __print_funct_t json_print_pcsw_stats(struct activity *a, int curr, int tab,
  * @a          Activity structure with statistics.
  * @curr       Index in array for current sample statistics.
  * @tab                Indentation in output.
- * @itv                Interval of time in jiffies.
+ * @itv                Interval of time in 1/100th of a second.
  ***************************************************************************
  */
 __print_funct_t json_print_irq_stats(struct activity *a, int curr, int tab,
@@ -303,11 +304,11 @@ __print_funct_t json_print_irq_stats(struct activity *a, int curr, int tab,
        int i;
        struct stats_irq *sic, *sip;
        int sep = FALSE;
-       char irqno[8];
+       char irqno[16];
 
        xprintf(tab++, "\"interrupts\": [");
 
-       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++) {
 
                sic = (struct stats_irq *) ((char *) a->buf[curr]  + i * a->msize);
                sip = (struct stats_irq *) ((char *) a->buf[!curr] + i * a->msize);
@@ -349,7 +350,7 @@ __print_funct_t json_print_irq_stats(struct activity *a, int curr, int tab,
  * @a          Activity structure with statistics.
  * @curr       Index in array for current sample statistics.
  * @tab                Indentation in output.
- * @itv                Interval of time in jiffies.
+ * @itv                Interval of time in 1/100th of a second.
  ***************************************************************************
  */
 __print_funct_t json_print_swap_stats(struct activity *a, int curr, int tab,
@@ -374,7 +375,7 @@ __print_funct_t json_print_swap_stats(struct activity *a, int curr, int tab,
  * @a          Activity structure with statistics.
  * @curr       Index in array for current sample statistics.
  * @tab                Indentation in output.
- * @itv                Interval of time in jiffies.
+ * @itv                Interval of time in 1/100th of a second.
  ***************************************************************************
  */
 __print_funct_t json_print_paging_stats(struct activity *a, int curr, int tab,
@@ -417,7 +418,7 @@ __print_funct_t json_print_paging_stats(struct activity *a, int curr, int tab,
  * @a          Activity structure with statistics.
  * @curr       Index in array for current sample statistics.
  * @tab                Indentation in output.
- * @itv                Interval of time in jiffies.
+ * @itv                Interval of time in 1/100th of a second.
  ***************************************************************************
  */
 __print_funct_t json_print_io_stats(struct activity *a, int curr, int tab,
@@ -461,37 +462,44 @@ __print_funct_t json_print_io_stats(struct activity *a, int curr, int tab,
  * @a          Activity structure with statistics.
  * @curr       Index in array for current sample statistics.
  * @tab                Indentation in output.
- * @itv                Interval of time in jiffies.
+ * @itv                Interval of time in 1/100th of a second.
  ***************************************************************************
  */
 __print_funct_t json_print_memory_stats(struct activity *a, int curr, int tab,
                                        unsigned long long itv)
 {
        struct stats_memory
-               *smc = (struct stats_memory *) a->buf[curr],
-               *smp = (struct stats_memory *) a->buf[!curr];
+               *smc = (struct stats_memory *) a->buf[curr];
        int sep = FALSE;
+       unsigned long long nousedmem;
 
        xprintf0(tab, "\"memory\": {");
 
-       if (DISPLAY_MEM_AMT(a->opt_flags)) {
+       if (DISPLAY_MEMORY(a->opt_flags)) {
 
                sep = TRUE;
 
-               printf("\"memfree\": %lu, "
-                      "\"memused\": %lu, "
+               nousedmem = smc->frmkb + smc->bufkb + smc->camkb + smc->slabkb;
+               if (nousedmem > smc->tlmkb) {
+                       nousedmem = smc->tlmkb;
+               }
+
+               printf("\"memfree\": %llu, "
+                      "\"avail\": %llu, "
+                      "\"memused\": %llu, "
                       "\"memused-percent\": %.2f, "
-                      "\"buffers\": %lu, "
-                      "\"cached\": %lu, "
-                      "\"commit\": %lu, "
+                      "\"buffers\": %llu, "
+                      "\"cached\": %llu, "
+                      "\"commit\": %llu, "
                       "\"commit-percent\": %.2f, "
-                      "\"active\": %lu, "
-                      "\"inactive\": %lu, "
-                      "\"dirty\": %lu",
+                      "\"active\": %llu, "
+                      "\"inactive\": %llu, "
+                      "\"dirty\": %llu",
                       smc->frmkb,
-                      smc->tlmkb - smc->frmkb,
+                      smc->availablekb,
+                      smc->tlmkb - nousedmem,
                       smc->tlmkb ?
-                      SP_VALUE(smc->frmkb, smc->tlmkb, smc->tlmkb) :
+                      SP_VALUE(nousedmem, smc->tlmkb, smc->tlmkb) :
                       0.0,
                       smc->bufkb,
                       smc->camkb,
@@ -505,11 +513,11 @@ __print_funct_t json_print_memory_stats(struct activity *a, int curr, int tab,
 
                if (DISPLAY_MEM_ALL(a->opt_flags)) {
                        /* Display extended memory stats */
-                       printf(", \"anonpg\": %lu, "
-                              "\"slab\": %lu, "
-                              "\"kstack\": %lu, "
-                              "\"pgtbl\": %lu, "
-                              "\"vmused\": %lu",
+                       printf(", \"anonpg\": %llu, "
+                              "\"slab\": %llu, "
+                              "\"kstack\": %llu, "
+                              "\"pgtbl\": %llu, "
+                              "\"vmused\": %llu",
                               smc->anonpgkb,
                               smc->slabkb,
                               smc->kstackkb,
@@ -525,10 +533,10 @@ __print_funct_t json_print_memory_stats(struct activity *a, int curr, int tab,
                }
                sep = TRUE;
 
-               printf("\"swpfree\": %lu, "
-                      "\"swpused\": %lu, "
+               printf("\"swpfree\": %llu, "
+                      "\"swpused\": %llu, "
                       "\"swpused-percent\": %.2f, "
-                      "\"swpcad\": %lu, "
+                      "\"swpcad\": %llu, "
                       "\"swpcad-percent\": %.2f",
                       smc->frskb,
                       smc->tlskb - smc->frskb,
@@ -541,23 +549,6 @@ __print_funct_t json_print_memory_stats(struct activity *a, int curr, int tab,
                       0.0);
        }
 
-       if (DISPLAY_MEMORY(a->opt_flags)) {
-
-               if (sep) {
-                       printf(", ");
-               }
-
-               printf("\"frmpg\": %.2f, "
-                      "\"bufpg\": %.2f, "
-                      "\"campg\": %.2f",
-                      S_VALUE((double) KB_TO_PG(smp->frmkb),
-                              (double) KB_TO_PG(smc->frmkb), itv),
-                      S_VALUE((double) KB_TO_PG(smp->bufkb),
-                              (double) KB_TO_PG(smc->bufkb), itv),
-                      S_VALUE((double) KB_TO_PG(smp->camkb),
-                              (double) KB_TO_PG(smc->camkb), itv));
-       }
-
        printf("}");
 }
 
@@ -569,7 +560,7 @@ __print_funct_t json_print_memory_stats(struct activity *a, int curr, int tab,
  * @a          Activity structure with statistics.
  * @curr       Index in array for current sample statistics.
  * @tab                Indentation in output.
- * @itv                Interval of time in jiffies.
+ * @itv                Interval of time in 1/100th of a second.
  ***************************************************************************
  */
 __print_funct_t json_print_ktables_stats(struct activity *a, int curr, int tab,
@@ -579,10 +570,10 @@ __print_funct_t json_print_ktables_stats(struct activity *a, int curr, int tab,
                *skc = (struct stats_ktables *) a->buf[curr];
 
        xprintf0(tab, "\"kernel\": {"
-                "\"dentunusd\": %u, "
-                "\"file-nr\": %u, "
-                "\"inode-nr\": %u, "
-                "\"pty-nr\": %u}",
+                "\"dentunusd\": %llu, "
+                "\"file-nr\": %llu, "
+                "\"inode-nr\": %llu, "
+                "\"pty-nr\": %llu}",
                 skc->dentry_stat,
                 skc->file_used,
                 skc->inode_used,
@@ -597,7 +588,7 @@ __print_funct_t json_print_ktables_stats(struct activity *a, int curr, int tab,
  * @a          Activity structure with statistics.
  * @curr       Index in array for current sample statistics.
  * @tab                Indentation in output.
- * @itv                Interval of time in jiffies.
+ * @itv                Interval of time in 1/100th of a second.
  ***************************************************************************
  */
 __print_funct_t json_print_queue_stats(struct activity *a, int curr, int tab,
@@ -607,12 +598,12 @@ __print_funct_t json_print_queue_stats(struct activity *a, int curr, int tab,
                *sqc = (struct stats_queue *) a->buf[curr];
 
        xprintf0(tab, "\"queue\": {"
-                "\"runq-sz\": %lu, "
-                "\"plist-sz\": %u, "
+                "\"runq-sz\": %llu, "
+                "\"plist-sz\": %llu, "
                 "\"ldavg-1\": %.2f, "
                 "\"ldavg-5\": %.2f, "
                 "\"ldavg-15\": %.2f, "
-                "\"blocked\": %lu}",
+                "\"blocked\": %llu}",
                 sqc->nr_running,
                 sqc->nr_threads,
                 (double) sqc->load_avg_1 / 100,
@@ -629,48 +620,69 @@ __print_funct_t json_print_queue_stats(struct activity *a, int curr, int tab,
  * @a          Activity structure with statistics.
  * @curr       Index in array for current sample statistics.
  * @tab                Indentation in output.
- * @itv                Interval of time in jiffies.
+ * @itv                Interval of time in 1/100th of a second.
  ***************************************************************************
  */
 __print_funct_t json_print_serial_stats(struct activity *a, int curr, int tab,
                                        unsigned long long itv)
 {
-       int i;
+       int i, j, j0, found;
        struct stats_serial *ssc, *ssp;
        int sep = FALSE;
 
        xprintf(tab++, "\"serial\": [");
 
-       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[!curr] + i * a->msize);
+               found = FALSE;
 
-               if (ssc->line == 0)
-                       continue;
+               if (a->nr[!curr] > 0) {
+                       ssc = (struct stats_serial *) ((char *) a->buf[curr] + i * a->msize);
 
-               if (ssc->line == ssp->line) {
+                       /* Look for corresponding serial line in previous iteration */
+                       j = i;
 
-                       if (sep) {
-                               printf(",\n");
+                       if (j >= a->nr[!curr]) {
+                               j = a->nr[!curr] - 1;
                        }
-                       sep = TRUE;
 
-                       xprintf0(tab, "{\"line\": %d, "
-                                "\"rcvin\": %.2f, "
-                                "\"xmtin\": %.2f, "
-                                "\"framerr\": %.2f, "
-                                "\"prtyerr\": %.2f, "
-                                "\"brk\": %.2f, "
-                                "\"ovrun\": %.2f}",
-                                ssc->line - 1,
-                                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));
+                       j0 = j;
+
+                       do {
+                               ssp = (struct stats_serial *) ((char *) a->buf[!curr] + j * a->msize);
+                               if (ssc->line == ssp->line) {
+                                       found = TRUE;
+                                       break;
+                               }
+                               if (++j >= a->nr[!curr]) {
+                                       j = 0;
+                               }
+                       }
+                       while (j != j0);
                }
+
+               if (!found)
+                       continue;
+
+               if (sep) {
+                       printf(",\n");
+               }
+               sep = TRUE;
+
+               xprintf0(tab, "{\"line\": %d, "
+                        "\"rcvin\": %.2f, "
+                        "\"xmtin\": %.2f, "
+                        "\"framerr\": %.2f, "
+                        "\"prtyerr\": %.2f, "
+                        "\"brk\": %.2f, "
+                        "\"ovrun\": %.2f}",
+                        ssc->line,
+                        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");
@@ -685,54 +697,48 @@ __print_funct_t json_print_serial_stats(struct activity *a, int curr, int tab,
  * @a          Activity structure with statistics.
  * @curr       Index in array for current sample statistics.
  * @tab                Indentation in output.
- * @itv                Interval of time in jiffies.
+ * @itv                Interval of time in 1/100th of a second.
  ***************************************************************************
  */
 __print_funct_t json_print_disk_stats(struct activity *a, int curr, int tab,
                                      unsigned long long itv)
 {
        int i, j;
-       struct stats_disk *sdc, *sdp;
+       struct stats_disk *sdc, *sdp, sdpzero;
        struct ext_disk_stats xds;
        int sep = FALSE;
-       char *dev_name, *persist_dev_name;
+       char *dev_name;
+
+       memset(&sdpzero, 0, STATS_DISK_SIZE);
 
        xprintf(tab++, "\"disk\": [");
 
-       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, !curr, i);
-               sdp = (struct stats_disk *) ((char *) a->buf[!curr] + j * a->msize);
-
-               /* Compute extended statistics values */
-               compute_ext_disk_stats(sdc, sdp, itv, &xds);
-
-               dev_name = NULL;
-               persist_dev_name = NULL;
-
-               if (DISPLAY_PERSIST_NAME_S(flags)) {
-                       persist_dev_name = get_persistent_name_from_pretty(get_devname(sdc->major, sdc->minor, TRUE));
-               }
-
-               if (persist_dev_name) {
-                       dev_name = persist_dev_name;
+               if (j < 0) {
+                       /* This is a newly registered interface. Previous stats are zero */
+                       sdp = &sdpzero;
                }
                else {
-                       if ((USE_PRETTY_OPTION(flags)) && (sdc->major == dm_major)) {
-                               dev_name = transform_devmapname(sdc->major, sdc->minor);
-                       }
+                       sdp = (struct stats_disk *) ((char *) a->buf[!curr] + j * a->msize);
+               }
 
-                       if (!dev_name) {
-                               dev_name = get_devname(sdc->major, sdc->minor,
-                                                      USE_PRETTY_OPTION(flags));
-                       }
+               /* Get device name */
+               dev_name = get_sa_devname(sdc->major, sdc->minor, flags);
+
+               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;
                }
 
+               /* Compute extended statistics values */
+               compute_ext_disk_stats(sdc, sdp, itv, &xds);
+
                if (sep) {
                        printf(",\n");
                }
@@ -742,18 +748,26 @@ __print_funct_t json_print_disk_stats(struct activity *a, int curr, int tab,
                         "\"tps\": %.2f, "
                         "\"rd_sec\": %.2f, "
                         "\"wr_sec\": %.2f, "
+                        "\"rkB\": %.2f, "
+                        "\"wkB\": %.2f, "
                         "\"avgrq-sz\": %.2f, "
+                        "\"areq-sz\": %.2f, "
                         "\"avgqu-sz\": %.2f, "
+                        "\"aqu-sz\": %.2f, "
                         "\"await\": %.2f, "
                         "\"svctm\": %.2f, "
                         "\"util-percent\": %.2f}",
                         /* Confusion possible here between index and minor numbers */
                         dev_name,
                         S_VALUE(sdp->nr_ios, sdc->nr_ios, itv),
-                        S_VALUE(sdp->rd_sect, sdc->rd_sect, itv),
+                        S_VALUE(sdp->rd_sect, sdc->rd_sect, itv), /* Unit = sectors (for backward compatibility) */
                         S_VALUE(sdp->wr_sect, sdc->wr_sect, itv),
+                        S_VALUE(sdp->rd_sect, sdc->rd_sect, itv) / 2,
+                        S_VALUE(sdp->wr_sect, sdc->wr_sect, itv) / 2,
                         /* See iostat for explanations */
-                        xds.arqsz,
+                        xds.arqsz,     /* Unit = sectors (for backward compatibility) */
+                        xds.arqsz / 2,
+                        S_VALUE(sdp->rq_ticks, sdc->rq_ticks, itv) / 1000.0,   /* For backward compatibility */
                         S_VALUE(sdp->rq_ticks, sdc->rq_ticks, itv) / 1000.0,
                         xds.await,
                         xds.svctm,
@@ -772,17 +786,19 @@ __print_funct_t json_print_disk_stats(struct activity *a, int curr, int tab,
  * @a          Activity structure with statistics.
  * @curr       Index in array for current sample statistics.
  * @tab                Indentation in output.
- * @itv                Interval of time in jiffies.
+ * @itv                Interval of time in 1/100th of a second.
  ***************************************************************************
  */
 __print_funct_t json_print_net_dev_stats(struct activity *a, int curr, int tab,
                                         unsigned long long itv)
 {
        int i, j;
-       struct stats_net_dev *sndc, *sndp;
+       struct stats_net_dev *sndc, *sndp, sndzero;
        int sep = FALSE;
        double rxkb, txkb, ifutil;
 
+       memset(&sndzero, 0, STATS_NET_DEV_SIZE);
+
        if (!IS_SELECTED(a->options) || (a->nr <= 0))
                goto close_json_markup;
 
@@ -791,15 +807,25 @@ __print_funct_t json_print_net_dev_stats(struct activity *a, int curr, int tab,
 
        xprintf(tab++, "\"net-dev\": [");
 
-       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, ""))
-                       continue;
+               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, !curr, i);
-               sndp = (struct stats_net_dev *) ((char *) a->buf[!curr] + j * a->msize);
+               if (j < 0) {
+                       /* This is a newly registered interface. Previous stats are zero */
+                       sndp = &sndzero;
+               }
+               else {
+                       sndp = (struct stats_net_dev *) ((char *) a->buf[!curr] + j * a->msize);
+               }
 
                if (sep) {
                        printf(",\n");
@@ -849,33 +875,45 @@ close_json_markup:
  * @a          Activity structure with statistics.
  * @curr       Index in array for current sample statistics.
  * @tab                Indentation in output.
- * @itv                Interval of time in jiffies.
+ * @itv                Interval of time in 1/100th of a second.
  ***************************************************************************
  */
 __print_funct_t json_print_net_edev_stats(struct activity *a, int curr, int tab,
                                          unsigned long long itv)
 {
        int i, j;
-       struct stats_net_edev *snedc, *snedp;
+       struct stats_net_edev *snedc, *snedp, snedzero;
        int sep = FALSE;
 
        if (!IS_SELECTED(a->options) || (a->nr <= 0))
                goto close_json_markup;
 
+       memset(&snedzero, 0, STATS_NET_EDEV_SIZE);
+
        json_markup_network(tab, OPEN_JSON_MARKUP);
        tab++;
 
        xprintf(tab++, "\"net-edev\": [");
 
-       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, ""))
-                       continue;
+               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, !curr, i);
-               snedp = (struct stats_net_edev *) ((char *) a->buf[!curr] + j * a->msize);
+               if (j < 0) {
+                       /* This is a newly registered interface. Previous stats are zero */
+                       snedp = &snedzero;
+               }
+               else {
+                       snedp = (struct stats_net_edev *) ((char *) a->buf[!curr] + j * a->msize);
+               }
 
                if (sep) {
                        printf(",\n");
@@ -923,7 +961,7 @@ close_json_markup:
  * @a          Activity structure with statistics.
  * @curr       Index in array for current sample statistics.
  * @tab                Indentation in output.
- * @itv                Interval of time in jiffies.
+ * @itv                Interval of time in 1/100th of a second.
  ***************************************************************************
  */
 __print_funct_t json_print_net_nfs_stats(struct activity *a, int curr, int tab,
@@ -968,7 +1006,7 @@ close_json_markup:
  * @a          Activity structure with statistics.
  * @curr       Index in array for current sample statistics.
  * @tab                Indentation in output.
- * @itv                Interval of time in jiffies.
+ * @itv                Interval of time in 1/100th of a second.
  ***************************************************************************
  */
 __print_funct_t json_print_net_nfsd_stats(struct activity *a, int curr, int tab,
@@ -1023,7 +1061,7 @@ close_json_markup:
  * @a          Activity structure with statistics.
  * @curr       Index in array for current sample statistics.
  * @tab                Indentation in output.
- * @itv                Interval of time in jiffies.
+ * @itv                Interval of time in 1/100th of a second.
  ***************************************************************************
  */
 __print_funct_t json_print_net_sock_stats(struct activity *a, int curr, int tab,
@@ -1067,7 +1105,7 @@ close_json_markup:
  * @a          Activity structure with statistics.
  * @curr       Index in array for current sample statistics.
  * @tab                Indentation in output.
- * @itv                Interval of time in jiffies.
+ * @itv                Interval of time in 1/100th of a second.
  ***************************************************************************
  */
 __print_funct_t json_print_net_ip_stats(struct activity *a, int curr, int tab,
@@ -1116,7 +1154,7 @@ close_json_markup:
  * @a          Activity structure with statistics.
  * @curr       Index in array for current sample statistics.
  * @tab                Indentation in output.
- * @itv                Interval of time in jiffies.
+ * @itv                Interval of time in 1/100th of a second.
  ***************************************************************************
  */
 __print_funct_t json_print_net_eip_stats(struct activity *a, int curr, int tab,
@@ -1165,7 +1203,7 @@ close_json_markup:
  * @a          Activity structure with statistics.
  * @curr       Index in array for current sample statistics.
  * @tab                Indentation in output.
- * @itv                Interval of time in jiffies.
+ * @itv                Interval of time in 1/100th of a second.
  ***************************************************************************
  */
 __print_funct_t json_print_net_icmp_stats(struct activity *a, int curr, int tab,
@@ -1226,7 +1264,7 @@ close_json_markup:
  * @a          Activity structure with statistics.
  * @curr       Index in array for current sample statistics.
  * @tab                Indentation in output.
- * @itv                Interval of time in jiffies.
+ * @itv                Interval of time in 1/100th of a second.
  ***************************************************************************
  */
 __print_funct_t json_print_net_eicmp_stats(struct activity *a, int curr, int tab,
@@ -1283,7 +1321,7 @@ close_json_markup:
  * @a          Activity structure with statistics.
  * @curr       Index in array for current sample statistics.
  * @tab                Indentation in output.
- * @itv                Interval of time in jiffies.
+ * @itv                Interval of time in 1/100th of a second.
  ***************************************************************************
  */
 __print_funct_t json_print_net_tcp_stats(struct activity *a, int curr, int tab,
@@ -1324,7 +1362,7 @@ close_json_markup:
  * @a          Activity structure with statistics.
  * @curr       Index in array for current sample statistics.
  * @tab                Indentation in XML output.
- * @itv                Interval of time in jiffies.
+ * @itv                Interval of time in 1/100th of a second.
  ***************************************************************************
  */
 __print_funct_t json_print_net_etcp_stats(struct activity *a, int curr, int tab,
@@ -1367,7 +1405,7 @@ close_json_markup:
  * @a          Activity structure with statistics.
  * @curr       Index in array for current sample statistics.
  * @tab                Indentation in output.
- * @itv                Interval of time in jiffies.
+ * @itv                Interval of time in 1/100th of a second.
  ***************************************************************************
  */
 __print_funct_t json_print_net_udp_stats(struct activity *a, int curr, int tab,
@@ -1408,7 +1446,7 @@ close_json_markup:
  * @a          Activity structure with statistics.
  * @curr       Index in array for current sample statistics.
  * @tab                Indentation in output.
- * @itv                Interval of time in jiffies.
+ * @itv                Interval of time in 1/100th of a second.
  ***************************************************************************
  */
 __print_funct_t json_print_net_sock6_stats(struct activity *a, int curr, int tab,
@@ -1448,7 +1486,7 @@ close_json_markup:
  * @a          Activity structure with statistics.
  * @curr       Index in array for current sample statistics.
  * @tab                Indentation in output.
- * @itv                Interval of time in jiffies.
+ * @itv                Interval of time in 1/100th of a second.
  ***************************************************************************
  */
 __print_funct_t json_print_net_ip6_stats(struct activity *a, int curr, int tab,
@@ -1501,7 +1539,7 @@ close_json_markup:
  * @a          Activity structure with statistics.
  * @curr       Index in array for current sample statistics.
  * @tab                Indentation in output.
- * @itv                Interval of time in jiffies.
+ * @itv                Interval of time in 1/100th of a second.
  ***************************************************************************
  */
 __print_funct_t json_print_net_eip6_stats(struct activity *a, int curr, int tab,
@@ -1556,7 +1594,7 @@ close_json_markup:
  * @a          Activity structure with statistics.
  * @curr       Index in array for current sample statistics.
  * @tab                Indentation in output.
- * @itv                Interval of time in jiffies.
+ * @itv                Interval of time in 1/100th of a second.
  ***************************************************************************
  */
 __print_funct_t json_print_net_icmp6_stats(struct activity *a, int curr, int tab,
@@ -1623,7 +1661,7 @@ close_json_markup:
  * @a          Activity structure with statistics.
  * @curr       Index in array for current sample statistics.
  * @tab                Indentation in output.
- * @itv                Interval of time in jiffies.
+ * @itv                Interval of time in 1/100th of a second.
  ***************************************************************************
  */
 __print_funct_t json_print_net_eicmp6_stats(struct activity *a, int curr, int tab,
@@ -1678,7 +1716,7 @@ close_json_markup:
  * @a          Activity structure with statistics.
  * @curr       Index in array for current sample statistics.
  * @tab                Indentation in output.
- * @itv                Interval of time in jiffies.
+ * @itv                Interval of time in 1/100th of a second.
  ***************************************************************************
  */
 __print_funct_t json_print_net_udp6_stats(struct activity *a, int curr, int tab,
@@ -1719,7 +1757,7 @@ close_json_markup:
  * @a          Activity structure with statistics.
  * @curr       Index in array for current sample statistics.
  * @tab                Indentation in output.
- * @itv                Interval of time in jiffies.
+ * @itv                Interval of time in 1/100th of a second.
  ***************************************************************************
  */
 __print_funct_t json_print_pwr_cpufreq_stats(struct activity *a, int curr, int tab,
@@ -1728,9 +1766,9 @@ __print_funct_t json_print_pwr_cpufreq_stats(struct activity *a, int curr, int t
        int i;
        struct stats_pwr_cpufreq *spc;
        int sep = FALSE;
-       char cpuno[8];
+       char cpuno[16];
 
-       if (!IS_SELECTED(a->options) || (a->nr <= 0))
+       if (!IS_SELECTED(a->options) || (a->nr[curr] <= 0))
                goto close_json_markup;
 
        json_markup_power_management(tab, OPEN_JSON_MARKUP);
@@ -1738,32 +1776,32 @@ __print_funct_t json_print_pwr_cpufreq_stats(struct activity *a, int curr, int t
 
        xprintf(tab++, "\"cpu-frequency\": [");
 
-       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++) {
 
-               spc = (struct stats_pwr_cpufreq *) ((char *) a->buf[curr]  + i * a->msize);
+               spc = (struct stats_pwr_cpufreq *) ((char *) a->buf[curr] + i * a->msize);
 
                /* Should current CPU (including CPU "all") be displayed? */
-               if (a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))) {
-
-                       /* Yes: Display it */
-                       if (!i) {
-                               /* This is CPU "all" */
-                               strcpy(cpuno, "all");
-                       }
-                       else {
-                               sprintf(cpuno, "%d", i - 1);
-                       }
+               if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
+                       /* No */
+                       continue;
 
-                       if (sep) {
-                               printf(",\n");
-                       }
-                       sep = TRUE;
+               if (!i) {
+                       /* This is CPU "all" */
+                       strcpy(cpuno, "all");
+               }
+               else {
+                       sprintf(cpuno, "%d", i - 1);
+               }
 
-                       xprintf0(tab, "{\"number\": \"%s\", "
-                                "\"frequency\": %.2f}",
-                                cpuno,
-                                ((double) spc->cpufreq) / 100);
+               if (sep) {
+                       printf(",\n");
                }
+               sep = TRUE;
+
+               xprintf0(tab, "{\"number\": \"%s\", "
+                        "\"frequency\": %.2f}",
+                        cpuno,
+                        ((double) spc->cpufreq) / 100);
        }
 
        printf("\n");
@@ -1784,7 +1822,7 @@ close_json_markup:
  * @a          Activity structure with statistics.
  * @curr       Index in array for current sample statistics.
  * @tab                Indentation in output.
- * @itv                Interval of time in jiffies.
+ * @itv                Interval of time in 1/100th of a second.
  ***************************************************************************
  */
 __print_funct_t json_print_pwr_fan_stats(struct activity *a, int curr, int tab,
@@ -1794,7 +1832,7 @@ __print_funct_t json_print_pwr_fan_stats(struct activity *a, int curr, int tab,
        struct stats_pwr_fan *spc;
        int sep = FALSE;
 
-       if (!IS_SELECTED(a->options) || (a->nr <= 0))
+       if (!IS_SELECTED(a->options) || (a->nr[curr] <= 0))
                goto close_json_markup;
 
        json_markup_power_management(tab, OPEN_JSON_MARKUP);
@@ -1802,8 +1840,8 @@ __print_funct_t json_print_pwr_fan_stats(struct activity *a, int curr, int tab,
 
        xprintf(tab++, "\"fan-speed\": [");
 
-       for (i = 0; i < a->nr; i++) {
-               spc = (struct stats_pwr_fan *) ((char *) a->buf[curr]  + i * a->msize);
+       for (i = 0; i < a->nr[curr]; i++) {
+               spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
 
                if (sep) {
                        printf(",\n");
@@ -1838,7 +1876,7 @@ close_json_markup:
  * @a          Activity structure with statistics.
  * @curr       Index in array for current sample statistics.
  * @tab                Indentation in output.
- * @itv                Interval of time in jiffies.
+ * @itv                Interval of time in 1/100th of a second.
  ***************************************************************************
  */
 __print_funct_t json_print_pwr_temp_stats(struct activity *a, int curr, int tab,
@@ -1848,7 +1886,7 @@ __print_funct_t json_print_pwr_temp_stats(struct activity *a, int curr, int tab,
        struct stats_pwr_temp *spc;
        int sep = FALSE;
 
-       if (!IS_SELECTED(a->options) || (a->nr <= 0))
+       if (!IS_SELECTED(a->options) || (a->nr[curr] <= 0))
                goto close_json_markup;
 
        json_markup_power_management(tab, OPEN_JSON_MARKUP);
@@ -1856,8 +1894,8 @@ __print_funct_t json_print_pwr_temp_stats(struct activity *a, int curr, int tab,
 
        xprintf(tab++, "\"temperature\": [");
 
-       for (i = 0; i < a->nr; i++) {
-               spc = (struct stats_pwr_temp *) ((char *) a->buf[curr]  + i * a->msize);
+       for (i = 0; i < a->nr[curr]; i++) {
+               spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
 
                if (sep) {
                        printf(",\n");
@@ -1894,7 +1932,7 @@ close_json_markup:
  * @a          Activity structure with statistics.
  * @curr       Index in array for current sample statistics.
  * @tab                Indentation in output.
- * @itv                Interval of time in jiffies.
+ * @itv                Interval of time in 1/100th of a second.
  ***************************************************************************
  */
 __print_funct_t json_print_pwr_in_stats(struct activity *a, int curr, int tab,
@@ -1904,7 +1942,7 @@ __print_funct_t json_print_pwr_in_stats(struct activity *a, int curr, int tab,
        struct stats_pwr_in *spc;
        int sep = FALSE;
 
-       if (!IS_SELECTED(a->options) || (a->nr <= 0))
+       if (!IS_SELECTED(a->options) || (a->nr[curr] <= 0))
                goto close_json_markup;
 
        json_markup_power_management(tab, OPEN_JSON_MARKUP);
@@ -1912,8 +1950,8 @@ __print_funct_t json_print_pwr_in_stats(struct activity *a, int curr, int tab,
 
        xprintf(tab++, "\"voltage-input\": [");
 
-       for (i = 0; i < a->nr; i++) {
-               spc = (struct stats_pwr_in *) ((char *) a->buf[curr]  + i * a->msize);
+       for (i = 0; i < a->nr[curr]; i++) {
+               spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
 
                if (sep) {
                        printf(",\n");
@@ -1950,7 +1988,7 @@ close_json_markup:
  * @a          Activity structure with statistics.
  * @curr       Index in array for current sample statistics.
  * @tab                Indentation in output.
- * @itv                Interval of time in jiffies.
+ * @itv                Interval of time in 1/100th of a second.
  ***************************************************************************
  */
 __print_funct_t json_print_huge_stats(struct activity *a, int curr, int tab,
@@ -1960,8 +1998,8 @@ __print_funct_t json_print_huge_stats(struct activity *a, int curr, int tab,
                *smc = (struct stats_huge *) a->buf[curr];
 
        xprintf0(tab, "\"hugepages\": {"
-                "\"hugfree\": %lu, "
-                "\"hugused\": %lu, "
+                "\"hugfree\": %llu, "
+                "\"hugused\": %llu, "
                 "\"hugused-percent\": %.2f}",
                 smc->frhkb,
                 smc->tlhkb - smc->frhkb,
@@ -1978,7 +2016,7 @@ __print_funct_t json_print_huge_stats(struct activity *a, int curr, int tab,
  * @a          Activity structure with statistics.
  * @curr       Index in array for current sample statistics.
  * @tab                Indentation in output.
- * @itv                Interval of time in jiffies.
+ * @itv                Interval of time in 1/100th of a second.
  ***************************************************************************
  */
 __print_funct_t json_print_pwr_wghfreq_stats(struct activity *a, int curr, int tab,
@@ -1988,9 +2026,9 @@ __print_funct_t json_print_pwr_wghfreq_stats(struct activity *a, int curr, int t
        struct stats_pwr_wghfreq *spc, *spp, *spc_k, *spp_k;
        unsigned long long tis, tisfreq;
        int sep = FALSE;
-       char cpuno[8];
+       char cpuno[16];
 
-       if (!IS_SELECTED(a->options) || (a->nr <= 0))
+       if (!IS_SELECTED(a->options) || (a->nr[curr] <= 0))
                goto close_json_markup;
 
        json_markup_power_management(tab, OPEN_JSON_MARKUP);
@@ -1998,48 +2036,48 @@ __print_funct_t json_print_pwr_wghfreq_stats(struct activity *a, int curr, int t
 
        xprintf(tab++, "\"cpu-weighted-frequency\": [");
 
-       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++) {
 
                spc = (struct stats_pwr_wghfreq *) ((char *) a->buf[curr]  + i * a->msize * a->nr2);
                spp = (struct stats_pwr_wghfreq *) ((char *) a->buf[!curr] + i * a->msize * a->nr2);
 
                /* 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... */
-                       tisfreq = 0;
-                       tis = 0;
+               tisfreq = 0;
+               tis = 0;
 
-                       for (k = 0; k < a->nr2; k++) {
+               for (k = 0; k < a->nr2; k++) {
 
-                               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);
+                       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);
 
-                               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);
-                       }
-
-                       if (!i) {
-                               /* This is CPU "all" */
-                               strcpy(cpuno, "all");
-                       }
-                       else {
-                               sprintf(cpuno, "%d", i - 1);
-                       }
+                       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);
+               }
 
-                       if (sep) {
-                               printf(",\n");
-                       }
-                       sep = TRUE;
+               if (!i) {
+                       /* This is CPU "all" */
+                       strcpy(cpuno, "all");
+               }
+               else {
+                       sprintf(cpuno, "%d", i - 1);
+               }
 
-                       xprintf0(tab, "{\"number\": \"%s\", "
-                                "\"weighted-frequency\": %.2f}",
-                                cpuno,
-                                tis ? ((double) tisfreq) / tis : 0.0);
+               if (sep) {
+                       printf(",\n");
                }
+               sep = TRUE;
+
+               xprintf0(tab, "{\"number\": \"%s\", "
+                        "\"weighted-frequency\": %.2f}",
+                        cpuno,
+                        tis ? ((double) tisfreq) / tis : 0.0);
        }
 
        printf("\n");
@@ -2060,7 +2098,7 @@ close_json_markup:
  * @a          Activity structure with statistics.
  * @curr       Index in array for current sample statistics.
  * @tab                Indentation in output.
- * @itv                Interval of time in jiffies.
+ * @itv                Interval of time in 1/100th of a second.
  ***************************************************************************
  */
 __print_funct_t json_print_pwr_usb_stats(struct activity *a, int curr, int tab,
@@ -2070,7 +2108,7 @@ __print_funct_t json_print_pwr_usb_stats(struct activity *a, int curr, int tab,
        struct stats_pwr_usb *suc;
        int sep = FALSE;
 
-       if (!IS_SELECTED(a->options) || (a->nr <= 0))
+       if (!IS_SELECTED(a->options) || (a->nr[curr] <= 0))
                goto close_json_markup;
 
        json_markup_power_management(tab, OPEN_JSON_MARKUP);
@@ -2078,12 +2116,8 @@ __print_funct_t json_print_pwr_usb_stats(struct activity *a, int curr, int tab,
 
        xprintf(tab++, "\"usb-devices\": [");
 
-       for (i = 0; i < a->nr; 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;
+       for (i = 0; i < a->nr[curr]; i++) {
+               suc = (struct stats_pwr_usb *) ((char *) a->buf[curr] + i * a->msize);
 
                if (sep) {
                        printf(",\n");
@@ -2122,7 +2156,7 @@ close_json_markup:
  * @a          Activity structure with statistics.
  * @curr       Index in array for current sample statistics.
  * @tab                Indentation in output.
- * @itv                Interval of time in jiffies.
+ * @itv                Interval of time in 1/100th of a second.
  ***************************************************************************
  */
 __print_funct_t json_print_filesystem_stats(struct activity *a, int curr, int tab,
@@ -2134,12 +2168,16 @@ __print_funct_t json_print_filesystem_stats(struct activity *a, int curr, int ta
 
        xprintf(tab++, "\"filesystems\": [");
 
-       for (i = 0; i < a->nr; i++) {
-               sfc = (struct stats_filesystem *) ((char *) a->buf[curr]  + i * a->msize);
+       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;
+               }
 
                if (sep) {
                        printf(",\n");
@@ -2180,17 +2218,17 @@ __print_funct_t json_print_filesystem_stats(struct activity *a, int curr, int ta
  * @a          Activity structure with statistics.
  * @curr       Index in array for current sample statistics.
  * @tab                Indentation in output.
- * @itv                Interval of time in jiffies.
+ * @itv                Interval of time in 1/100th of a second.
  ***************************************************************************
  */
 __print_funct_t json_print_fchost_stats(struct activity *a, int curr, int tab,
                                        unsigned long long itv)
 {
-       int i;
+       int i, j, j0, found;
        struct stats_fchost *sfcc, *sfcp;
        int sep = FALSE;
 
-       if (!IS_SELECTED(a->options) || (a->nr <= 0))
+       if (!IS_SELECTED(a->options) || (a->nr[curr] <= 0))
                goto close_json_markup;
 
        json_markup_network(tab, OPEN_JSON_MARKUP);
@@ -2198,13 +2236,37 @@ __print_funct_t json_print_fchost_stats(struct activity *a, int curr, int tab,
 
        xprintf(tab++, "\"fchosts\": [");
 
-       for (i = 0; i < a->nr; i++) {
-               sfcc = (struct stats_fchost *) ((char *) a->buf[curr]  + i * a->msize);
-               sfcp = (struct stats_fchost *) ((char *) a->buf[!curr]  + i * a->msize);
+       for (i = 0; i < a->nr[curr]; i++) {
+
+               found = FALSE;
+
+               if (a->nr[!curr] > 0) {
+                       sfcc = (struct stats_fchost *) ((char *) a->buf[curr] + i * a->msize);
+
+                       /* Look for corresponding structure in previous iteration */
+                       j = i;
+
+                       if (j >= a->nr[!curr]) {
+                               j = a->nr[!curr] - 1;
+                       }
+
+                       j0 = j;
+
+                       do {
+                               sfcp = (struct stats_fchost *) ((char *) a->buf[!curr] + j * a->msize);
+                               if (!strcmp(sfcc->fchost_name, sfcp->fchost_name)) {
+                                       found = TRUE;
+                                       break;
+                               }
+                               if (++j >= a->nr[!curr]) {
+                                       j = 0;
+                               }
+                       }
+                       while (j != j0);
+               }
 
-               if (!sfcc->fchost_name[0])
-                       /* We are at the end of the list */
-                       break;
+               if (!found)
+                       continue;
 
                if (sep)
                        printf(",\n");
@@ -2242,18 +2304,89 @@ close_json_markup:
  * @a          Activity structure with statistics.
  * @curr       Index in array for current sample statistics.
  * @tab                Indentation in output.
- * @itv                Interval of time in jiffies.
+ * @itv                Interval of time in 1/100th of a second.
  ***************************************************************************
  */
 __print_funct_t json_print_softnet_stats(struct activity *a, int curr, int tab,
                                         unsigned long long itv)
 {
-       if (!IS_SELECTED(a->options) || (a->nr <= 0))
+       int i;
+       struct stats_softnet *ssnc, *ssnp;
+       int sep = FALSE;
+       char cpuno[16];
+       unsigned char offline_cpu_bitmap[BITMAP_SIZE(NR_CPUS)] = {0};
+
+       if (!IS_SELECTED(a->options) || (a->nr[curr] <= 0))
                goto close_json_markup;
 
        json_markup_network(tab, OPEN_JSON_MARKUP);
+       tab++;
+
+       xprintf(tab++, "\"softnet\": [");
+
+       /* @nr[curr] cannot normally be greater than @nr_ini */
+       if (a->nr[curr] > a->nr_ini) {
+               a->nr_ini = a->nr[curr];
+       }
+
+       /* Compute statistics for CPU "all" */
+       get_global_soft_statistics(a, !curr, 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[!curr] + i * a->msize);
+
+               if (sep) {
+                       printf(",\n");
+               }
+               sep = TRUE;
+
+               if (!i) {
+                       /* This is CPU "all" */
+                       strcpy(cpuno, "all");
+               }
+               else {
+                       sprintf(cpuno, "%d", i - 1);
+               }
 
-       /* FIXME */
+               xprintf0(tab, "{\"cpu\": \"%s\", "
+                        "\"total\": %.2f, "
+                        "\"dropd\": %.2f, "
+                        "\"squeezd\": %.2f, "
+                        "\"rx_rps\": %.2f, "
+                        "\"flw_lim\": %.2f}",
+                        cpuno,
+                        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");
+       xprintf0(--tab, "]");
+
+       tab --;
 
 close_json_markup:
        if (CLOSE_MARKUP(a->options)) {