xfs: pass xfsstats structures to handlers and macros
authorBill O'Donnell <billodo@redhat.com>
Sun, 11 Oct 2015 18:19:45 +0000 (05:19 +1100)
committerDave Chinner <david@fromorbit.com>
Sun, 11 Oct 2015 18:19:45 +0000 (05:19 +1100)
This patch is the next step toward per-fs xfs stats. The patch makes
the show and clear routines able to handle any stats structure
associated with a kobject.

Instead of a single global xfsstats structure, add kobject and a pointer
to a per-cpu struct xfsstats. Modify the macros that manipulate the stats
accordingly: XFS_STATS_INC, XFS_STATS_DEC, and XFS_STATS_ADD now access
xfsstats->xs_stats.

The sysfs functions need to get from the kobject back to the xfsstats
structure which contains it, and pass the pointer to the ->xs_stats
percpu structure into the show & clear routines.

Signed-off-by: Bill O'Donnell <billodo@redhat.com>
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
fs/xfs/xfs_linux.h
fs/xfs/xfs_stats.c
fs/xfs/xfs_stats.h
fs/xfs/xfs_super.c
fs/xfs/xfs_sysctl.c
fs/xfs/xfs_sysfs.c

index 85f883dd6207bd41b6b2951111009cb5097ae339..ec0e239a0fa9070f30541b14f305b8d28c153339 100644 (file)
@@ -171,6 +171,13 @@ struct xfs_kobj {
        struct completion       complete;
 };
 
+struct xstats {
+       struct xfsstats __percpu        *xs_stats;
+       struct xfs_kobj                 xs_kobj;
+};
+
+extern struct xstats xfsstats;
+
 /* Kernel uid/gid conversion. These are used to convert to/from the on disk
  * uid_t/gid_t types to the kuid_t/kgid_t types that the kernel uses internally.
  * The conversion here is type only, the value will remain the same since we
index f481da09c3888c1a507a992bab56aa77cb218554..3348b0b6177d07fc1bdd67ea4bd7f3008922582e 100644 (file)
 #include "xfs.h"
 #include <linux/proc_fs.h>
 
-DEFINE_PER_CPU(struct xfsstats, xfsstats);
+struct xstats xfsstats;
 
-static int counter_val(int idx)
+static int counter_val(struct xfsstats __percpu *stats, int idx)
 {
        int val = 0, cpu;
 
        for_each_possible_cpu(cpu)
-               val += *(((__u32 *)&per_cpu(xfsstats, cpu) + idx));
+               val += *(((__u32 *)per_cpu_ptr(stats, cpu) + idx));
        return val;
 }
 
-int xfs_stats_format(char *buf)
+int xfs_stats_format(struct xfsstats __percpu *stats, char *buf)
 {
        int             i, j;
        int             len = 0;
@@ -73,14 +73,14 @@ int xfs_stats_format(char *buf)
                /* inner loop does each group */
                for (; j < xstats[i].endpoint; j++)
                        len += snprintf(buf + len, PATH_MAX - len, " %u",
-                                       counter_val(j));
+                                       counter_val(stats, 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;
+               xs_xstrat_bytes += per_cpu_ptr(stats, i)->xs_xstrat_bytes;
+               xs_write_bytes += per_cpu_ptr(stats, i)->xs_write_bytes;
+               xs_read_bytes += per_cpu_ptr(stats, i)->xs_read_bytes;
        }
 
        len += snprintf(buf + len, PATH_MAX-len, "xpc %Lu %Lu %Lu\n",
@@ -95,7 +95,7 @@ int xfs_stats_format(char *buf)
        return len;
 }
 
-void xfs_stats_clearall(void)
+void xfs_stats_clearall(struct xfsstats __percpu *stats)
 {
        int             c;
        __uint32_t      vn_active;
@@ -104,9 +104,9 @@ void xfs_stats_clearall(void)
        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;
+               vn_active = per_cpu_ptr(stats, c)->vn_active;
+               memset(per_cpu_ptr(stats, c), 0, sizeof(*stats));
+               per_cpu_ptr(stats, c)->vn_active = vn_active;
                preempt_enable();
        }
 }
@@ -117,10 +117,8 @@ static int xqm_proc_show(struct seq_file *m, void *v)
 {
        /* maximum; incore; ratio free to inuse; freelist */
        seq_printf(m, "%d\t%d\t%d\t%u\n",
-                       0,
-                       counter_val(XFSSTAT_END_XQMSTAT),
-                       0,
-                       counter_val(XFSSTAT_END_XQMSTAT + 1));
+                  0, counter_val(xfsstats.xs_stats, XFSSTAT_END_XQMSTAT),
+                  0, counter_val(xfsstats.xs_stats, XFSSTAT_END_XQMSTAT + 1));
        return 0;
 }
 
@@ -144,7 +142,7 @@ static int xqmstat_proc_show(struct seq_file *m, void *v)
 
        seq_printf(m, "qm");
        for (j = XFSSTAT_END_IBT_V2; j < XFSSTAT_END_XQMSTAT; j++)
-               seq_printf(m, " %u", counter_val(j));
+               seq_printf(m, " %u", counter_val(xfsstats.xs_stats, j));
        seq_putc(m, '\n');
        return 0;
 }
index 18807b576394c432822b569df8bac8597cbbb8f0..54f2260299d1a9adb5220da36420e52474de64ce 100644 (file)
@@ -18,9 +18,6 @@
 #ifndef __XFS_STATS_H__
 #define __XFS_STATS_H__
 
-int xfs_stats_format(char *buf);
-void xfs_stats_clearall(void);
-
 #if defined(CONFIG_PROC_FS) && !defined(XFS_STATS_OFF)
 
 #include <linux/percpu.h>
@@ -217,15 +214,18 @@ struct xfsstats {
        __uint64_t              xs_read_bytes;
 };
 
-DECLARE_PER_CPU(struct xfsstats, xfsstats);
+int xfs_stats_format(struct xfsstats __percpu *stats, char *buf);
+void xfs_stats_clearall(struct xfsstats __percpu *stats);
+extern struct xstats xfsstats;
 
-/*
- * We don't disable preempt, not too worried about poking the
- * wrong CPU's stat for now (also aggregated before reporting).
- */
-#define XFS_STATS_INC(v)       (per_cpu(xfsstats, current_cpu()).v++)
-#define XFS_STATS_DEC(v)       (per_cpu(xfsstats, current_cpu()).v--)
-#define XFS_STATS_ADD(v, inc)  (per_cpu(xfsstats, current_cpu()).v += (inc))
+#define XFS_STATS_INC(v)       \
+       (per_cpu_ptr(xfsstats.xs_stats, current_cpu())->v++)
+
+#define XFS_STATS_DEC(v)       \
+       (per_cpu_ptr(xfsstats.xs_stats, current_cpu())->v--)
+
+#define XFS_STATS_ADD(v, inc)  \
+       (per_cpu_ptr(xfsstats.xs_stats, current_cpu())->v += (inc))
 
 extern int xfs_init_procfs(void);
 extern void xfs_cleanup_procfs(void);
index 0dfc53ba62fb9e5652d0411531b9b4df1f903198..e1a35a5104e8e02899ce9cd8af1462c56643d084 100644 (file)
@@ -61,7 +61,6 @@ static kmem_zone_t *xfs_ioend_zone;
 mempool_t *xfs_ioend_pool;
 
 static struct kset *xfs_kset;          /* top-level xfs sysfs dir */
-static struct xfs_kobj xfs_stats_kobj; /* global stats sysfs attrs */
 #ifdef DEBUG
 static struct xfs_kobj xfs_dbg_kobj;   /* global debug sysfs attrs */
 #endif
@@ -1842,11 +1841,18 @@ init_xfs_fs(void)
                goto out_sysctl_unregister;
        }
 
-       xfs_stats_kobj.kobject.kset = xfs_kset;
-       error = xfs_sysfs_init(&xfs_stats_kobj, &xfs_stats_ktype, NULL,
+       xfsstats.xs_kobj.kobject.kset = xfs_kset;
+
+       xfsstats.xs_stats = alloc_percpu(struct xfsstats);
+       if (!xfsstats.xs_stats) {
+               error = -ENOMEM;
+               goto out_kset_unregister;
+       }
+
+       error = xfs_sysfs_init(&xfsstats.xs_kobj, &xfs_stats_ktype, NULL,
                               "stats");
        if (error)
-               goto out_kset_unregister;
+               goto out_free_stats;
 
 #ifdef DEBUG
        xfs_dbg_kobj.kobject.kset = xfs_kset;
@@ -1871,7 +1877,9 @@ init_xfs_fs(void)
        xfs_sysfs_del(&xfs_dbg_kobj);
  out_remove_stats_kobj:
 #endif
-       xfs_sysfs_del(&xfs_stats_kobj);
+       xfs_sysfs_del(&xfsstats.xs_kobj);
+ out_free_stats:
+       free_percpu(xfsstats.xs_stats);
  out_kset_unregister:
        kset_unregister(xfs_kset);
  out_sysctl_unregister:
@@ -1898,7 +1906,8 @@ exit_xfs_fs(void)
 #ifdef DEBUG
        xfs_sysfs_del(&xfs_dbg_kobj);
 #endif
-       xfs_sysfs_del(&xfs_stats_kobj);
+       xfs_sysfs_del(&xfsstats.xs_kobj);
+       free_percpu(xfsstats.xs_stats);
        kset_unregister(xfs_kset);
        xfs_sysctl_unregister();
        xfs_cleanup_procfs();
index 5defabb391cb961a788d6a01ede92ed8a8724489..aed74d3f8da93a9b80b7bafe8b76f004b481ca5a 100644 (file)
@@ -37,7 +37,7 @@ xfs_stats_clear_proc_handler(
        ret = proc_dointvec_minmax(ctl, write, buffer, lenp, ppos);
 
        if (!ret && write && *valp) {
-               xfs_stats_clearall();
+               xfs_stats_clearall(xfsstats.xs_stats);
                xfs_stats_clear = 0;
        }
 
index fa3dc66d82f16e85e183fe67e5979ed51d56f83f..ee70f5dec9dccf088eada0d354b06cb847577a2a 100644 (file)
@@ -131,12 +131,22 @@ struct kobj_type xfs_dbg_ktype = {
 
 /* stats */
 
+static inline struct xstats *
+to_xstats(struct kobject *kobject)
+{
+       struct xfs_kobj *kobj = to_kobj(kobject);
+
+       return container_of(kobj, struct xstats, xs_kobj);
+}
+
 STATIC ssize_t
 stats_show(
        struct kobject  *kobject,
        char            *buf)
 {
-       return xfs_stats_format(buf);
+       struct xstats   *stats = to_xstats(kobject);
+
+       return xfs_stats_format(stats->xs_stats, buf);
 }
 XFS_SYSFS_ATTR_RO(stats);
 
@@ -148,6 +158,7 @@ stats_clear_store(
 {
        int             ret;
        int             val;
+       struct xstats   *stats = to_xstats(kobject);
 
        ret = kstrtoint(buf, 0, &val);
        if (ret)
@@ -155,7 +166,8 @@ stats_clear_store(
 
        if (val != 1)
                return -EINVAL;
-       xfs_stats_clearall();
+
+       xfs_stats_clearall(stats->xs_stats);
        return count;
 }
 XFS_SYSFS_ATTR_WO(stats_clear);