0001
0002
0003
0004
0005
0006 #include "xfs.h"
0007
0008 struct xstats xfsstats;
0009
0010 static int counter_val(struct xfsstats __percpu *stats, int idx)
0011 {
0012 int val = 0, cpu;
0013
0014 for_each_possible_cpu(cpu)
0015 val += *(((__u32 *)per_cpu_ptr(stats, cpu) + idx));
0016 return val;
0017 }
0018
0019 int xfs_stats_format(struct xfsstats __percpu *stats, char *buf)
0020 {
0021 int i, j;
0022 int len = 0;
0023 uint64_t xs_xstrat_bytes = 0;
0024 uint64_t xs_write_bytes = 0;
0025 uint64_t xs_read_bytes = 0;
0026 uint64_t defer_relog = 0;
0027
0028 static const struct xstats_entry {
0029 char *desc;
0030 int endpoint;
0031 } xstats[] = {
0032 { "extent_alloc", xfsstats_offset(xs_abt_lookup) },
0033 { "abt", xfsstats_offset(xs_blk_mapr) },
0034 { "blk_map", xfsstats_offset(xs_bmbt_lookup) },
0035 { "bmbt", xfsstats_offset(xs_dir_lookup) },
0036 { "dir", xfsstats_offset(xs_trans_sync) },
0037 { "trans", xfsstats_offset(xs_ig_attempts) },
0038 { "ig", xfsstats_offset(xs_log_writes) },
0039 { "log", xfsstats_offset(xs_try_logspace)},
0040 { "push_ail", xfsstats_offset(xs_xstrat_quick)},
0041 { "xstrat", xfsstats_offset(xs_write_calls) },
0042 { "rw", xfsstats_offset(xs_attr_get) },
0043 { "attr", xfsstats_offset(xs_iflush_count)},
0044 { "icluster", xfsstats_offset(vn_active) },
0045 { "vnodes", xfsstats_offset(xb_get) },
0046 { "buf", xfsstats_offset(xs_abtb_2) },
0047 { "abtb2", xfsstats_offset(xs_abtc_2) },
0048 { "abtc2", xfsstats_offset(xs_bmbt_2) },
0049 { "bmbt2", xfsstats_offset(xs_ibt_2) },
0050 { "ibt2", xfsstats_offset(xs_fibt_2) },
0051 { "fibt2", xfsstats_offset(xs_rmap_2) },
0052 { "rmapbt", xfsstats_offset(xs_refcbt_2) },
0053 { "refcntbt", xfsstats_offset(xs_qm_dqreclaims)},
0054
0055 { "qm", xfsstats_offset(xs_xstrat_bytes)},
0056 };
0057
0058
0059
0060 for (i = j = 0; i < ARRAY_SIZE(xstats); i++) {
0061 len += scnprintf(buf + len, PATH_MAX - len, "%s",
0062 xstats[i].desc);
0063
0064 for (; j < xstats[i].endpoint; j++)
0065 len += scnprintf(buf + len, PATH_MAX - len, " %u",
0066 counter_val(stats, j));
0067 len += scnprintf(buf + len, PATH_MAX - len, "\n");
0068 }
0069
0070 for_each_possible_cpu(i) {
0071 xs_xstrat_bytes += per_cpu_ptr(stats, i)->s.xs_xstrat_bytes;
0072 xs_write_bytes += per_cpu_ptr(stats, i)->s.xs_write_bytes;
0073 xs_read_bytes += per_cpu_ptr(stats, i)->s.xs_read_bytes;
0074 defer_relog += per_cpu_ptr(stats, i)->s.defer_relog;
0075 }
0076
0077 len += scnprintf(buf + len, PATH_MAX-len, "xpc %Lu %Lu %Lu\n",
0078 xs_xstrat_bytes, xs_write_bytes, xs_read_bytes);
0079 len += scnprintf(buf + len, PATH_MAX-len, "defer_relog %llu\n",
0080 defer_relog);
0081 len += scnprintf(buf + len, PATH_MAX-len, "debug %u\n",
0082 #if defined(DEBUG)
0083 1);
0084 #else
0085 0);
0086 #endif
0087
0088 return len;
0089 }
0090
0091 void xfs_stats_clearall(struct xfsstats __percpu *stats)
0092 {
0093 int c;
0094 uint32_t vn_active;
0095
0096 xfs_notice(NULL, "Clearing xfsstats");
0097 for_each_possible_cpu(c) {
0098 preempt_disable();
0099
0100 vn_active = per_cpu_ptr(stats, c)->s.vn_active;
0101 memset(per_cpu_ptr(stats, c), 0, sizeof(*stats));
0102 per_cpu_ptr(stats, c)->s.vn_active = vn_active;
0103 preempt_enable();
0104 }
0105 }
0106
0107 #ifdef CONFIG_PROC_FS
0108
0109 #ifdef CONFIG_XFS_QUOTA
0110
0111 #define XFSSTAT_START_XQMSTAT xfsstats_offset(xs_qm_dqreclaims)
0112 #define XFSSTAT_END_XQMSTAT xfsstats_offset(xs_qm_dquot)
0113
0114 static int xqm_proc_show(struct seq_file *m, void *v)
0115 {
0116
0117 seq_printf(m, "%d\t%d\t%d\t%u\n",
0118 0, counter_val(xfsstats.xs_stats, XFSSTAT_END_XQMSTAT),
0119 0, counter_val(xfsstats.xs_stats, XFSSTAT_END_XQMSTAT + 1));
0120 return 0;
0121 }
0122
0123
0124 static int xqmstat_proc_show(struct seq_file *m, void *v)
0125 {
0126 int j;
0127
0128 seq_printf(m, "qm");
0129 for (j = XFSSTAT_START_XQMSTAT; j < XFSSTAT_END_XQMSTAT; j++)
0130 seq_printf(m, " %u", counter_val(xfsstats.xs_stats, j));
0131 seq_putc(m, '\n');
0132 return 0;
0133 }
0134 #endif
0135
0136 int
0137 xfs_init_procfs(void)
0138 {
0139 if (!proc_mkdir("fs/xfs", NULL))
0140 return -ENOMEM;
0141
0142 if (!proc_symlink("fs/xfs/stat", NULL,
0143 "/sys/fs/xfs/stats/stats"))
0144 goto out;
0145
0146 #ifdef CONFIG_XFS_QUOTA
0147 if (!proc_create_single("fs/xfs/xqmstat", 0, NULL, xqmstat_proc_show))
0148 goto out;
0149 if (!proc_create_single("fs/xfs/xqm", 0, NULL, xqm_proc_show))
0150 goto out;
0151 #endif
0152 return 0;
0153
0154 out:
0155 remove_proc_subtree("fs/xfs", NULL);
0156 return -ENOMEM;
0157 }
0158
0159 void
0160 xfs_cleanup_procfs(void)
0161 {
0162 remove_proc_subtree("fs/xfs", NULL);
0163 }
0164 #endif