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 57760 : static int counter_val(struct xfsstats __percpu *stats, int idx)
11 : {
12 57760 : int val = 0, cpu;
13 :
14 173280 : for_each_possible_cpu(cpu)
15 115520 : val += *(((__u32 *)per_cpu_ptr(stats, cpu) + idx));
16 57760 : return val;
17 : }
18 :
19 304 : int xfs_stats_format(struct xfsstats __percpu *stats, char *buf)
20 : {
21 304 : int i, j;
22 304 : int len = 0;
23 304 : uint64_t xs_xstrat_bytes = 0;
24 304 : uint64_t xs_write_bytes = 0;
25 304 : uint64_t xs_read_bytes = 0;
26 304 : uint64_t defer_relog = 0;
27 :
28 304 : 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 7296 : for (i = j = 0; i < ARRAY_SIZE(xstats); i++) {
61 20976 : len += scnprintf(buf + len, PATH_MAX - len, "%s",
62 6992 : xstats[i].desc);
63 : /* inner loop does each group */
64 64752 : for (; j < xstats[i].endpoint; j++)
65 57760 : len += scnprintf(buf + len, PATH_MAX - len, " %u",
66 : counter_val(stats, j));
67 6992 : len += scnprintf(buf + len, PATH_MAX - len, "\n");
68 : }
69 : /* extra precision counters */
70 912 : for_each_possible_cpu(i) {
71 608 : xs_xstrat_bytes += per_cpu_ptr(stats, i)->s.xs_xstrat_bytes;
72 608 : xs_write_bytes += per_cpu_ptr(stats, i)->s.xs_write_bytes;
73 608 : xs_read_bytes += per_cpu_ptr(stats, i)->s.xs_read_bytes;
74 608 : defer_relog += per_cpu_ptr(stats, i)->s.defer_relog;
75 : }
76 :
77 304 : len += scnprintf(buf + len, PATH_MAX-len, "xpc %llu %llu %llu\n",
78 : xs_xstrat_bytes, xs_write_bytes, xs_read_bytes);
79 304 : len += scnprintf(buf + len, PATH_MAX-len, "defer_relog %llu\n",
80 : defer_relog);
81 304 : len += scnprintf(buf + len, PATH_MAX-len, "debug %u\n",
82 : #if defined(DEBUG)
83 : 1);
84 : #else
85 : 0);
86 : #endif
87 :
88 304 : 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 */
117 0 : seq_printf(m, "%d\t%d\t%d\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 0 : return 0;
121 : }
122 :
123 : /* legacy quota stats interface no 2 */
124 0 : static int xqmstat_proc_show(struct seq_file *m, void *v)
125 : {
126 0 : int j;
127 :
128 0 : seq_puts(m, "qm");
129 0 : for (j = XFSSTAT_START_XQMSTAT; j < XFSSTAT_END_XQMSTAT; j++)
130 0 : seq_printf(m, " %u", counter_val(xfsstats.xs_stats, j));
131 0 : seq_putc(m, '\n');
132 0 : return 0;
133 : }
134 : #endif /* CONFIG_XFS_QUOTA */
135 :
136 : int
137 12 : xfs_init_procfs(void)
138 : {
139 12 : if (!proc_mkdir("fs/xfs", NULL))
140 : return -ENOMEM;
141 :
142 12 : if (!proc_symlink("fs/xfs/stat", NULL,
143 : "/sys/fs/xfs/stats/stats"))
144 0 : goto out;
145 :
146 : #ifdef CONFIG_XFS_QUOTA
147 12 : if (!proc_create_single("fs/xfs/xqmstat", 0, NULL, xqmstat_proc_show))
148 0 : goto out;
149 12 : if (!proc_create_single("fs/xfs/xqm", 0, NULL, xqm_proc_show))
150 0 : goto out;
151 : #endif
152 : return 0;
153 :
154 0 : out:
155 0 : remove_proc_subtree("fs/xfs", NULL);
156 0 : return -ENOMEM;
157 : }
158 :
159 : void
160 12 : xfs_cleanup_procfs(void)
161 : {
162 12 : remove_proc_subtree("fs/xfs", NULL);
163 12 : }
164 : #endif /* CONFIG_PROC_FS */
|