xfs: create global stats and stats_clear in sysfs
[firefly-linux-kernel-4.4.55.git] / fs / xfs / xfs_stats.c
index f2240383d4bba79b75f78f7d45803c76728457c5..e19b84a327d117ad9cc45d514955af49b7807da0 100644 (file)
@@ -29,6 +29,88 @@ static int counter_val(int idx)
        return val;
 }
 
+int xfs_stats_format(char *buf)
+{
+       int             i, j;
+       int             len = 0;
+       __uint64_t      xs_xstrat_bytes = 0;
+       __uint64_t      xs_write_bytes = 0;
+       __uint64_t      xs_read_bytes = 0;
+
+       static const struct xstats_entry {
+               char    *desc;
+               int     endpoint;
+       } xstats[] = {
+               { "extent_alloc",       XFSSTAT_END_EXTENT_ALLOC        },
+               { "abt",                XFSSTAT_END_ALLOC_BTREE         },
+               { "blk_map",            XFSSTAT_END_BLOCK_MAPPING       },
+               { "bmbt",               XFSSTAT_END_BLOCK_MAP_BTREE     },
+               { "dir",                XFSSTAT_END_DIRECTORY_OPS       },
+               { "trans",              XFSSTAT_END_TRANSACTIONS        },
+               { "ig",                 XFSSTAT_END_INODE_OPS           },
+               { "log",                XFSSTAT_END_LOG_OPS             },
+               { "push_ail",           XFSSTAT_END_TAIL_PUSHING        },
+               { "xstrat",             XFSSTAT_END_WRITE_CONVERT       },
+               { "rw",                 XFSSTAT_END_READ_WRITE_OPS      },
+               { "attr",               XFSSTAT_END_ATTRIBUTE_OPS       },
+               { "icluster",           XFSSTAT_END_INODE_CLUSTER       },
+               { "vnodes",             XFSSTAT_END_VNODE_OPS           },
+               { "buf",                XFSSTAT_END_BUF                 },
+               { "abtb2",              XFSSTAT_END_ABTB_V2             },
+               { "abtc2",              XFSSTAT_END_ABTC_V2             },
+               { "bmbt2",              XFSSTAT_END_BMBT_V2             },
+               { "ibt2",               XFSSTAT_END_IBT_V2              },
+               { "fibt2",              XFSSTAT_END_FIBT_V2             },
+               /* we print both series of quota information together */
+               { "qm",                 XFSSTAT_END_QM                  },
+       };
+
+       /* Loop over all stats groups */
+
+       for (i = j = 0; i < ARRAY_SIZE(xstats); i++) {
+               len += snprintf(buf + len, PATH_MAX - len, "%s",
+                               xstats[i].desc);
+               /* inner loop does each group */
+               for (; j < xstats[i].endpoint; j++)
+                       len += snprintf(buf + len, PATH_MAX - len, " %u",
+                                       counter_val(j));
+               len += snprintf(buf + len, PATH_MAX - len, "\n");
+       }
+       /* extra precision counters */
+       for_each_possible_cpu(i) {
+               xs_xstrat_bytes += per_cpu(xfsstats, i).xs_xstrat_bytes;
+               xs_write_bytes += per_cpu(xfsstats, i).xs_write_bytes;
+               xs_read_bytes += per_cpu(xfsstats, i).xs_read_bytes;
+       }
+
+       len += snprintf(buf + len, PATH_MAX-len, "xpc %Lu %Lu %Lu\n",
+                       xs_xstrat_bytes, xs_write_bytes, xs_read_bytes);
+       len += snprintf(buf + len, PATH_MAX-len, "debug %u\n",
+#if defined(DEBUG)
+               1);
+#else
+               0);
+#endif
+
+       return len;
+}
+
+void xfs_stats_clearall(void)
+{
+       int             c;
+       __uint32_t      vn_active;
+
+       xfs_notice(NULL, "Clearing xfsstats");
+       for_each_possible_cpu(c) {
+               preempt_disable();
+               /* save vn_active, it's a universal truth! */
+               vn_active = per_cpu(xfsstats, c).vn_active;
+               memset(&per_cpu(xfsstats, c), 0, sizeof(struct xfsstats));
+               per_cpu(xfsstats, c).vn_active = vn_active;
+               preempt_enable();
+       }
+}
+
 static int xfs_stat_proc_show(struct seq_file *m, void *v)
 {
        int             i, j;