Line data Source code
1 : // SPDX-License-Identifier: GPL-2.0
2 : /*
3 : * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
4 : * All Rights Reserved.
5 : */
6 : #include "xfs.h"
7 :
8 : struct xstats xfsstats;
9 :
10 58900 : static int counter_val(struct xfsstats __percpu *stats, int idx)
11 : {
12 58900 : int val = 0, cpu;
13 :
14 176700 : for_each_possible_cpu(cpu)
15 117800 : val += *(((__u32 *)per_cpu_ptr(stats, cpu) + idx));
16 58900 : return val;
17 : }
18 :
19 310 : int xfs_stats_format(struct xfsstats __percpu *stats, char *buf)
20 : {
21 310 : int i, j;
22 310 : int len = 0;
23 310 : uint64_t xs_xstrat_bytes = 0;
24 310 : uint64_t xs_write_bytes = 0;
25 310 : uint64_t xs_read_bytes = 0;
26 310 : uint64_t defer_relog = 0;
27 :
28 310 : static const struct xstats_entry {
29 : char *desc;
30 : int endpoint;
31 : } xstats[] = {
32 : { "extent_alloc", xfsstats_offset(xs_abt_lookup) },
33 : { "abt", xfsstats_offset(xs_blk_mapr) },
34 : { "blk_map", xfsstats_offset(xs_bmbt_lookup) },
35 : { "bmbt", xfsstats_offset(xs_dir_lookup) },
36 : { "dir", xfsstats_offset(xs_trans_sync) },
37 : { "trans", xfsstats_offset(xs_ig_attempts) },
38 : { "ig", xfsstats_offset(xs_log_writes) },
39 : { "log", xfsstats_offset(xs_try_logspace)},
40 : { "push_ail", xfsstats_offset(xs_xstrat_quick)},
41 : { "xstrat", xfsstats_offset(xs_write_calls) },
42 : { "rw", xfsstats_offset(xs_attr_get) },
43 : { "attr", xfsstats_offset(xs_iflush_count)},
44 : { "icluster", xfsstats_offset(vn_active) },
45 : { "vnodes", xfsstats_offset(xb_get) },
46 : { "buf", xfsstats_offset(xs_abtb_2) },
47 : { "abtb2", xfsstats_offset(xs_abtc_2) },
48 : { "abtc2", xfsstats_offset(xs_bmbt_2) },
49 : { "bmbt2", xfsstats_offset(xs_ibt_2) },
50 : { "ibt2", xfsstats_offset(xs_fibt_2) },
51 : { "fibt2", xfsstats_offset(xs_rmap_2) },
52 : { "rmapbt", xfsstats_offset(xs_refcbt_2) },
53 : { "refcntbt", xfsstats_offset(xs_qm_dqreclaims)},
54 : /* we print both series of quota information together */
55 : { "qm", xfsstats_offset(xs_xstrat_bytes)},
56 : };
57 :
58 : /* Loop over all stats groups */
59 :
60 7440 : for (i = j = 0; i < ARRAY_SIZE(xstats); i++) {
61 14260 : len += scnprintf(buf + len, PATH_MAX - len, "%s",
62 7130 : xstats[i].desc);
63 : /* inner loop does each group */
64 66030 : for (; j < xstats[i].endpoint; j++)
65 58900 : len += scnprintf(buf + len, PATH_MAX - len, " %u",
66 : counter_val(stats, j));
67 7130 : len += scnprintf(buf + len, PATH_MAX - len, "\n");
68 : }
69 : /* extra precision counters */
70 930 : for_each_possible_cpu(i) {
71 620 : xs_xstrat_bytes += per_cpu_ptr(stats, i)->s.xs_xstrat_bytes;
72 620 : xs_write_bytes += per_cpu_ptr(stats, i)->s.xs_write_bytes;
73 620 : xs_read_bytes += per_cpu_ptr(stats, i)->s.xs_read_bytes;
74 620 : defer_relog += per_cpu_ptr(stats, i)->s.defer_relog;
75 : }
76 :
77 310 : len += scnprintf(buf + len, PATH_MAX-len, "xpc %llu %llu %llu\n",
78 : xs_xstrat_bytes, xs_write_bytes, xs_read_bytes);
79 310 : len += scnprintf(buf + len, PATH_MAX-len, "defer_relog %llu\n",
80 : defer_relog);
81 310 : len += scnprintf(buf + len, PATH_MAX-len, "debug %u\n",
82 : #if defined(DEBUG)
83 : 1);
84 : #else
85 : 0);
86 : #endif
87 :
88 310 : return len;
89 : }
90 :
91 0 : void xfs_stats_clearall(struct xfsstats __percpu *stats)
92 : {
93 0 : int c;
94 0 : uint32_t vn_active;
95 :
96 0 : xfs_notice(NULL, "Clearing xfsstats");
97 0 : for_each_possible_cpu(c) {
98 0 : preempt_disable();
99 : /* save vn_active, it's a universal truth! */
100 0 : vn_active = per_cpu_ptr(stats, c)->s.vn_active;
101 0 : memset(per_cpu_ptr(stats, c), 0, sizeof(*stats));
102 0 : per_cpu_ptr(stats, c)->s.vn_active = vn_active;
103 0 : preempt_enable();
104 : }
105 0 : }
106 :
107 : #ifdef CONFIG_PROC_FS
108 : /* legacy quota interfaces */
109 : #ifdef CONFIG_XFS_QUOTA
110 :
111 : #define XFSSTAT_START_XQMSTAT xfsstats_offset(xs_qm_dqreclaims)
112 : #define XFSSTAT_END_XQMSTAT xfsstats_offset(xs_qm_dquot)
113 :
114 0 : static int xqm_proc_show(struct seq_file *m, void *v)
115 : {
116 : /* maximum; incore; ratio free to inuse; freelist; rtquota */
117 0 : seq_printf(m, "%d\t%d\t%d\t%u\t%u\n",
118 : 0, counter_val(xfsstats.xs_stats, XFSSTAT_END_XQMSTAT),
119 : 0, counter_val(xfsstats.xs_stats, XFSSTAT_END_XQMSTAT + 1),
120 : #ifdef CONFIG_XFS_RT
121 : 1
122 : #else
123 : 0
124 : #endif
125 : );
126 0 : return 0;
127 : }
128 :
129 : /* legacy quota stats interface no 2 */
130 0 : static int xqmstat_proc_show(struct seq_file *m, void *v)
131 : {
132 0 : int j;
133 :
134 0 : seq_puts(m, "qm");
135 0 : for (j = XFSSTAT_START_XQMSTAT; j < XFSSTAT_END_XQMSTAT; j++)
136 0 : seq_printf(m, " %u", counter_val(xfsstats.xs_stats, j));
137 0 : seq_putc(m, '\n');
138 0 : return 0;
139 : }
140 : #endif /* CONFIG_XFS_QUOTA */
141 :
142 : int
143 12 : xfs_init_procfs(void)
144 : {
145 12 : if (!proc_mkdir("fs/xfs", NULL))
146 : return -ENOMEM;
147 :
148 12 : if (!proc_symlink("fs/xfs/stat", NULL,
149 : "/sys/fs/xfs/stats/stats"))
150 0 : goto out;
151 :
152 : #ifdef CONFIG_XFS_QUOTA
153 12 : if (!proc_create_single("fs/xfs/xqmstat", 0, NULL, xqmstat_proc_show))
154 0 : goto out;
155 12 : if (!proc_create_single("fs/xfs/xqm", 0, NULL, xqm_proc_show))
156 0 : goto out;
157 : #endif
158 : return 0;
159 :
160 0 : out:
161 0 : remove_proc_subtree("fs/xfs", NULL);
162 0 : return -ENOMEM;
163 : }
164 :
165 : void
166 12 : xfs_cleanup_procfs(void)
167 : {
168 12 : remove_proc_subtree("fs/xfs", NULL);
169 12 : }
170 : #endif /* CONFIG_PROC_FS */
|