Commit | Line | Data |
---|---|---|
a31b1d3d BF |
1 | /* |
2 | * Copyright (c) 2014 Red Hat, Inc. | |
3 | * All Rights Reserved. | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or | |
6 | * modify it under the terms of the GNU General Public License as | |
7 | * published by the Free Software Foundation. | |
8 | * | |
9 | * This program is distributed in the hope that it would be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License | |
15 | * along with this program; if not, write the Free Software Foundation, | |
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
17 | */ | |
18 | ||
19 | #include "xfs.h" | |
20 | #include "xfs_sysfs.h" | |
801cc4e1 | 21 | #include "xfs_format.h" |
baff4e44 | 22 | #include "xfs_log_format.h" |
801cc4e1 | 23 | #include "xfs_trans_resv.h" |
baff4e44 BF |
24 | #include "xfs_log.h" |
25 | #include "xfs_log_priv.h" | |
bb230c12 | 26 | #include "xfs_stats.h" |
801cc4e1 | 27 | #include "xfs_mount.h" |
a31b1d3d BF |
28 | |
29 | struct xfs_sysfs_attr { | |
30 | struct attribute attr; | |
a27c2640 BD |
31 | ssize_t (*show)(struct kobject *kobject, char *buf); |
32 | ssize_t (*store)(struct kobject *kobject, const char *buf, | |
33 | size_t count); | |
a31b1d3d BF |
34 | }; |
35 | ||
36 | static inline struct xfs_sysfs_attr * | |
37 | to_attr(struct attribute *attr) | |
38 | { | |
39 | return container_of(attr, struct xfs_sysfs_attr, attr); | |
40 | } | |
41 | ||
42 | #define XFS_SYSFS_ATTR_RW(name) \ | |
43 | static struct xfs_sysfs_attr xfs_sysfs_attr_##name = __ATTR_RW(name) | |
44 | #define XFS_SYSFS_ATTR_RO(name) \ | |
45 | static struct xfs_sysfs_attr xfs_sysfs_attr_##name = __ATTR_RO(name) | |
bb230c12 BD |
46 | #define XFS_SYSFS_ATTR_WO(name) \ |
47 | static struct xfs_sysfs_attr xfs_sysfs_attr_##name = __ATTR_WO(name) | |
a31b1d3d BF |
48 | |
49 | #define ATTR_LIST(name) &xfs_sysfs_attr_##name.attr | |
50 | ||
a27c2640 BD |
51 | STATIC ssize_t |
52 | xfs_sysfs_object_show( | |
53 | struct kobject *kobject, | |
54 | struct attribute *attr, | |
55 | char *buf) | |
56 | { | |
57 | struct xfs_sysfs_attr *xfs_attr = to_attr(attr); | |
58 | ||
59 | return xfs_attr->show ? xfs_attr->show(kobject, buf) : 0; | |
60 | } | |
61 | ||
62 | STATIC ssize_t | |
63 | xfs_sysfs_object_store( | |
64 | struct kobject *kobject, | |
65 | struct attribute *attr, | |
66 | const char *buf, | |
67 | size_t count) | |
68 | { | |
69 | struct xfs_sysfs_attr *xfs_attr = to_attr(attr); | |
70 | ||
71 | return xfs_attr->store ? xfs_attr->store(kobject, buf, count) : 0; | |
72 | } | |
73 | ||
74 | static const struct sysfs_ops xfs_sysfs_ops = { | |
75 | .show = xfs_sysfs_object_show, | |
76 | .store = xfs_sysfs_object_store, | |
77 | }; | |
78 | ||
801cc4e1 BF |
79 | /* |
80 | * xfs_mount kobject. The mp kobject also serves as the per-mount parent object | |
81 | * that is identified by the fsname under sysfs. | |
82 | */ | |
83 | ||
84 | static inline struct xfs_mount * | |
85 | to_mp(struct kobject *kobject) | |
86 | { | |
87 | struct xfs_kobj *kobj = to_kobj(kobject); | |
88 | ||
89 | return container_of(kobj, struct xfs_mount, m_kobj); | |
90 | } | |
91 | ||
92 | #ifdef DEBUG | |
93 | ||
94 | STATIC ssize_t | |
95 | fail_writes_store( | |
96 | struct kobject *kobject, | |
97 | const char *buf, | |
98 | size_t count) | |
99 | { | |
100 | struct xfs_mount *mp = to_mp(kobject); | |
101 | int ret; | |
102 | int val; | |
103 | ||
104 | ret = kstrtoint(buf, 0, &val); | |
105 | if (ret) | |
106 | return ret; | |
107 | ||
108 | if (val == 1) | |
109 | mp->m_fail_writes = true; | |
110 | else if (val == 0) | |
111 | mp->m_fail_writes = false; | |
112 | else | |
113 | return -EINVAL; | |
114 | ||
115 | return count; | |
116 | } | |
117 | ||
118 | STATIC ssize_t | |
119 | fail_writes_show( | |
120 | struct kobject *kobject, | |
121 | char *buf) | |
122 | { | |
123 | struct xfs_mount *mp = to_mp(kobject); | |
124 | ||
125 | return snprintf(buf, PAGE_SIZE, "%d\n", mp->m_fail_writes ? 1 : 0); | |
126 | } | |
127 | XFS_SYSFS_ATTR_RW(fail_writes); | |
128 | ||
129 | #endif /* DEBUG */ | |
130 | ||
131 | static struct attribute *xfs_mp_attrs[] = { | |
132 | #ifdef DEBUG | |
133 | ATTR_LIST(fail_writes), | |
134 | #endif | |
135 | NULL, | |
136 | }; | |
137 | ||
138 | struct kobj_type xfs_mp_ktype = { | |
139 | .release = xfs_sysfs_release, | |
140 | .sysfs_ops = &xfs_sysfs_ops, | |
141 | .default_attrs = xfs_mp_attrs, | |
142 | }; | |
143 | ||
65b65735 BF |
144 | #ifdef DEBUG |
145 | /* debug */ | |
146 | ||
2e227178 BF |
147 | STATIC ssize_t |
148 | log_recovery_delay_store( | |
a27c2640 | 149 | struct kobject *kobject, |
2e227178 | 150 | const char *buf, |
a27c2640 | 151 | size_t count) |
2e227178 BF |
152 | { |
153 | int ret; | |
154 | int val; | |
155 | ||
156 | ret = kstrtoint(buf, 0, &val); | |
157 | if (ret) | |
158 | return ret; | |
159 | ||
160 | if (val < 0 || val > 60) | |
161 | return -EINVAL; | |
162 | ||
163 | xfs_globals.log_recovery_delay = val; | |
164 | ||
165 | return count; | |
166 | } | |
167 | ||
168 | STATIC ssize_t | |
169 | log_recovery_delay_show( | |
a27c2640 BD |
170 | struct kobject *kobject, |
171 | char *buf) | |
2e227178 BF |
172 | { |
173 | return snprintf(buf, PAGE_SIZE, "%d\n", xfs_globals.log_recovery_delay); | |
174 | } | |
175 | XFS_SYSFS_ATTR_RW(log_recovery_delay); | |
176 | ||
65b65735 | 177 | static struct attribute *xfs_dbg_attrs[] = { |
2e227178 | 178 | ATTR_LIST(log_recovery_delay), |
65b65735 BF |
179 | NULL, |
180 | }; | |
181 | ||
65b65735 BF |
182 | struct kobj_type xfs_dbg_ktype = { |
183 | .release = xfs_sysfs_release, | |
a27c2640 | 184 | .sysfs_ops = &xfs_sysfs_ops, |
65b65735 BF |
185 | .default_attrs = xfs_dbg_attrs, |
186 | }; | |
187 | ||
188 | #endif /* DEBUG */ | |
189 | ||
bb230c12 BD |
190 | /* stats */ |
191 | ||
80529c45 BD |
192 | static inline struct xstats * |
193 | to_xstats(struct kobject *kobject) | |
194 | { | |
195 | struct xfs_kobj *kobj = to_kobj(kobject); | |
196 | ||
197 | return container_of(kobj, struct xstats, xs_kobj); | |
198 | } | |
199 | ||
bb230c12 BD |
200 | STATIC ssize_t |
201 | stats_show( | |
a27c2640 BD |
202 | struct kobject *kobject, |
203 | char *buf) | |
bb230c12 | 204 | { |
80529c45 BD |
205 | struct xstats *stats = to_xstats(kobject); |
206 | ||
207 | return xfs_stats_format(stats->xs_stats, buf); | |
bb230c12 BD |
208 | } |
209 | XFS_SYSFS_ATTR_RO(stats); | |
210 | ||
211 | STATIC ssize_t | |
212 | stats_clear_store( | |
a27c2640 | 213 | struct kobject *kobject, |
bb230c12 | 214 | const char *buf, |
a27c2640 | 215 | size_t count) |
bb230c12 BD |
216 | { |
217 | int ret; | |
218 | int val; | |
80529c45 | 219 | struct xstats *stats = to_xstats(kobject); |
bb230c12 BD |
220 | |
221 | ret = kstrtoint(buf, 0, &val); | |
222 | if (ret) | |
223 | return ret; | |
224 | ||
225 | if (val != 1) | |
226 | return -EINVAL; | |
80529c45 BD |
227 | |
228 | xfs_stats_clearall(stats->xs_stats); | |
bb230c12 BD |
229 | return count; |
230 | } | |
231 | XFS_SYSFS_ATTR_WO(stats_clear); | |
232 | ||
233 | static struct attribute *xfs_stats_attrs[] = { | |
234 | ATTR_LIST(stats), | |
235 | ATTR_LIST(stats_clear), | |
236 | NULL, | |
237 | }; | |
238 | ||
bb230c12 BD |
239 | struct kobj_type xfs_stats_ktype = { |
240 | .release = xfs_sysfs_release, | |
a27c2640 | 241 | .sysfs_ops = &xfs_sysfs_ops, |
bb230c12 BD |
242 | .default_attrs = xfs_stats_attrs, |
243 | }; | |
244 | ||
baff4e44 BF |
245 | /* xlog */ |
246 | ||
a27c2640 BD |
247 | static inline struct xlog * |
248 | to_xlog(struct kobject *kobject) | |
249 | { | |
250 | struct xfs_kobj *kobj = to_kobj(kobject); | |
251 | ||
252 | return container_of(kobj, struct xlog, l_kobj); | |
253 | } | |
254 | ||
80d6d698 BF |
255 | STATIC ssize_t |
256 | log_head_lsn_show( | |
a27c2640 BD |
257 | struct kobject *kobject, |
258 | char *buf) | |
80d6d698 | 259 | { |
80d6d698 BF |
260 | int cycle; |
261 | int block; | |
a27c2640 | 262 | struct xlog *log = to_xlog(kobject); |
80d6d698 BF |
263 | |
264 | spin_lock(&log->l_icloglock); | |
265 | cycle = log->l_curr_cycle; | |
266 | block = log->l_curr_block; | |
267 | spin_unlock(&log->l_icloglock); | |
268 | ||
269 | return snprintf(buf, PAGE_SIZE, "%d:%d\n", cycle, block); | |
270 | } | |
271 | XFS_SYSFS_ATTR_RO(log_head_lsn); | |
272 | ||
273 | STATIC ssize_t | |
274 | log_tail_lsn_show( | |
a27c2640 BD |
275 | struct kobject *kobject, |
276 | char *buf) | |
80d6d698 | 277 | { |
80d6d698 BF |
278 | int cycle; |
279 | int block; | |
a27c2640 | 280 | struct xlog *log = to_xlog(kobject); |
80d6d698 BF |
281 | |
282 | xlog_crack_atomic_lsn(&log->l_tail_lsn, &cycle, &block); | |
283 | return snprintf(buf, PAGE_SIZE, "%d:%d\n", cycle, block); | |
284 | } | |
285 | XFS_SYSFS_ATTR_RO(log_tail_lsn); | |
286 | ||
287 | STATIC ssize_t | |
288 | reserve_grant_head_show( | |
a27c2640 BD |
289 | struct kobject *kobject, |
290 | char *buf) | |
291 | ||
80d6d698 | 292 | { |
80d6d698 BF |
293 | int cycle; |
294 | int bytes; | |
a27c2640 | 295 | struct xlog *log = to_xlog(kobject); |
80d6d698 BF |
296 | |
297 | xlog_crack_grant_head(&log->l_reserve_head.grant, &cycle, &bytes); | |
298 | return snprintf(buf, PAGE_SIZE, "%d:%d\n", cycle, bytes); | |
299 | } | |
300 | XFS_SYSFS_ATTR_RO(reserve_grant_head); | |
301 | ||
302 | STATIC ssize_t | |
303 | write_grant_head_show( | |
a27c2640 BD |
304 | struct kobject *kobject, |
305 | char *buf) | |
80d6d698 | 306 | { |
80d6d698 BF |
307 | int cycle; |
308 | int bytes; | |
a27c2640 | 309 | struct xlog *log = to_xlog(kobject); |
80d6d698 BF |
310 | |
311 | xlog_crack_grant_head(&log->l_write_head.grant, &cycle, &bytes); | |
312 | return snprintf(buf, PAGE_SIZE, "%d:%d\n", cycle, bytes); | |
313 | } | |
314 | XFS_SYSFS_ATTR_RO(write_grant_head); | |
315 | ||
609adfc2 BF |
316 | #ifdef DEBUG |
317 | STATIC ssize_t | |
318 | log_badcrc_factor_store( | |
319 | struct kobject *kobject, | |
320 | const char *buf, | |
321 | size_t count) | |
322 | { | |
323 | struct xlog *log = to_xlog(kobject); | |
324 | int ret; | |
325 | uint32_t val; | |
326 | ||
327 | ret = kstrtouint(buf, 0, &val); | |
328 | if (ret) | |
329 | return ret; | |
330 | ||
331 | log->l_badcrc_factor = val; | |
332 | ||
333 | return count; | |
334 | } | |
335 | ||
336 | STATIC ssize_t | |
337 | log_badcrc_factor_show( | |
338 | struct kobject *kobject, | |
339 | char *buf) | |
340 | { | |
341 | struct xlog *log = to_xlog(kobject); | |
342 | ||
343 | return snprintf(buf, PAGE_SIZE, "%d\n", log->l_badcrc_factor); | |
344 | } | |
345 | ||
346 | XFS_SYSFS_ATTR_RW(log_badcrc_factor); | |
347 | #endif /* DEBUG */ | |
348 | ||
baff4e44 | 349 | static struct attribute *xfs_log_attrs[] = { |
80d6d698 BF |
350 | ATTR_LIST(log_head_lsn), |
351 | ATTR_LIST(log_tail_lsn), | |
352 | ATTR_LIST(reserve_grant_head), | |
353 | ATTR_LIST(write_grant_head), | |
609adfc2 BF |
354 | #ifdef DEBUG |
355 | ATTR_LIST(log_badcrc_factor), | |
356 | #endif | |
baff4e44 BF |
357 | NULL, |
358 | }; | |
359 | ||
baff4e44 BF |
360 | struct kobj_type xfs_log_ktype = { |
361 | .release = xfs_sysfs_release, | |
a27c2640 | 362 | .sysfs_ops = &xfs_sysfs_ops, |
baff4e44 BF |
363 | .default_attrs = xfs_log_attrs, |
364 | }; |