blob: ec6e0e2f95d66dff0d11eced92abf54a1880ff27 [file] [log] [blame]
Brian Fostera31b1d32014-07-15 08:07:01 +10001/*
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"
Carlos Maiolino192852b2016-05-18 10:58:51 +100020#include "xfs_shared.h"
Brian Foster801cc4e2016-03-15 11:42:44 +110021#include "xfs_format.h"
Brian Fosterbaff4e42014-07-15 08:07:29 +100022#include "xfs_log_format.h"
Brian Foster801cc4e2016-03-15 11:42:44 +110023#include "xfs_trans_resv.h"
Carlos Maiolino192852b2016-05-18 10:58:51 +100024#include "xfs_sysfs.h"
Brian Fosterbaff4e42014-07-15 08:07:29 +100025#include "xfs_log.h"
26#include "xfs_log_priv.h"
Bill O'Donnellbb230c12015-10-12 05:15:45 +110027#include "xfs_stats.h"
Brian Foster801cc4e2016-03-15 11:42:44 +110028#include "xfs_mount.h"
Brian Fostera31b1d32014-07-15 08:07:01 +100029
30struct xfs_sysfs_attr {
31 struct attribute attr;
Bill O'Donnella27c26402015-10-12 05:18:45 +110032 ssize_t (*show)(struct kobject *kobject, char *buf);
33 ssize_t (*store)(struct kobject *kobject, const char *buf,
34 size_t count);
Brian Fostera31b1d32014-07-15 08:07:01 +100035};
36
37static inline struct xfs_sysfs_attr *
38to_attr(struct attribute *attr)
39{
40 return container_of(attr, struct xfs_sysfs_attr, attr);
41}
42
43#define XFS_SYSFS_ATTR_RW(name) \
44 static struct xfs_sysfs_attr xfs_sysfs_attr_##name = __ATTR_RW(name)
45#define XFS_SYSFS_ATTR_RO(name) \
46 static struct xfs_sysfs_attr xfs_sysfs_attr_##name = __ATTR_RO(name)
Bill O'Donnellbb230c12015-10-12 05:15:45 +110047#define XFS_SYSFS_ATTR_WO(name) \
48 static struct xfs_sysfs_attr xfs_sysfs_attr_##name = __ATTR_WO(name)
Brian Fostera31b1d32014-07-15 08:07:01 +100049
50#define ATTR_LIST(name) &xfs_sysfs_attr_##name.attr
51
Bill O'Donnella27c26402015-10-12 05:18:45 +110052STATIC ssize_t
53xfs_sysfs_object_show(
54 struct kobject *kobject,
55 struct attribute *attr,
56 char *buf)
57{
58 struct xfs_sysfs_attr *xfs_attr = to_attr(attr);
59
60 return xfs_attr->show ? xfs_attr->show(kobject, buf) : 0;
61}
62
63STATIC ssize_t
64xfs_sysfs_object_store(
65 struct kobject *kobject,
66 struct attribute *attr,
67 const char *buf,
68 size_t count)
69{
70 struct xfs_sysfs_attr *xfs_attr = to_attr(attr);
71
72 return xfs_attr->store ? xfs_attr->store(kobject, buf, count) : 0;
73}
74
75static const struct sysfs_ops xfs_sysfs_ops = {
76 .show = xfs_sysfs_object_show,
77 .store = xfs_sysfs_object_store,
78};
79
Brian Foster801cc4e2016-03-15 11:42:44 +110080/*
81 * xfs_mount kobject. The mp kobject also serves as the per-mount parent object
82 * that is identified by the fsname under sysfs.
83 */
84
85static inline struct xfs_mount *
86to_mp(struct kobject *kobject)
87{
88 struct xfs_kobj *kobj = to_kobj(kobject);
89
90 return container_of(kobj, struct xfs_mount, m_kobj);
91}
92
93#ifdef DEBUG
94
95STATIC ssize_t
Brian Foster9dbddd72017-02-13 22:48:17 -080096drop_writes_store(
Brian Foster801cc4e2016-03-15 11:42:44 +110097 struct kobject *kobject,
98 const char *buf,
99 size_t count)
100{
101 struct xfs_mount *mp = to_mp(kobject);
102 int ret;
103 int val;
104
105 ret = kstrtoint(buf, 0, &val);
106 if (ret)
107 return ret;
108
109 if (val == 1)
Brian Foster9dbddd72017-02-13 22:48:17 -0800110 mp->m_drop_writes = true;
Brian Foster801cc4e2016-03-15 11:42:44 +1100111 else if (val == 0)
Brian Foster9dbddd72017-02-13 22:48:17 -0800112 mp->m_drop_writes = false;
Brian Foster801cc4e2016-03-15 11:42:44 +1100113 else
114 return -EINVAL;
115
116 return count;
117}
118
119STATIC ssize_t
Brian Foster9dbddd72017-02-13 22:48:17 -0800120drop_writes_show(
Brian Foster801cc4e2016-03-15 11:42:44 +1100121 struct kobject *kobject,
122 char *buf)
123{
124 struct xfs_mount *mp = to_mp(kobject);
125
Brian Foster9dbddd72017-02-13 22:48:17 -0800126 return snprintf(buf, PAGE_SIZE, "%d\n", mp->m_drop_writes ? 1 : 0);
Brian Foster801cc4e2016-03-15 11:42:44 +1100127}
Brian Foster9dbddd72017-02-13 22:48:17 -0800128XFS_SYSFS_ATTR_RW(drop_writes);
Brian Foster801cc4e2016-03-15 11:42:44 +1100129
130#endif /* DEBUG */
131
132static struct attribute *xfs_mp_attrs[] = {
133#ifdef DEBUG
Brian Foster9dbddd72017-02-13 22:48:17 -0800134 ATTR_LIST(drop_writes),
Brian Foster801cc4e2016-03-15 11:42:44 +1100135#endif
136 NULL,
137};
138
139struct kobj_type xfs_mp_ktype = {
140 .release = xfs_sysfs_release,
141 .sysfs_ops = &xfs_sysfs_ops,
142 .default_attrs = xfs_mp_attrs,
143};
144
Brian Foster65b65732014-09-09 11:52:42 +1000145#ifdef DEBUG
146/* debug */
147
Brian Foster2e227172014-09-09 11:56:13 +1000148STATIC ssize_t
Brian Fosterccdab3d2017-06-14 21:29:12 -0700149bug_on_assert_store(
150 struct kobject *kobject,
151 const char *buf,
152 size_t count)
153{
154 int ret;
155 int val;
156
157 ret = kstrtoint(buf, 0, &val);
158 if (ret)
159 return ret;
160
161 if (val == 1)
162 xfs_globals.bug_on_assert = true;
163 else if (val == 0)
164 xfs_globals.bug_on_assert = false;
165 else
166 return -EINVAL;
167
168 return count;
169}
170
171STATIC ssize_t
172bug_on_assert_show(
173 struct kobject *kobject,
174 char *buf)
175{
176 return snprintf(buf, PAGE_SIZE, "%d\n", xfs_globals.bug_on_assert ? 1 : 0);
177}
178XFS_SYSFS_ATTR_RW(bug_on_assert);
179
180STATIC ssize_t
Brian Foster2e227172014-09-09 11:56:13 +1000181log_recovery_delay_store(
Bill O'Donnella27c26402015-10-12 05:18:45 +1100182 struct kobject *kobject,
Brian Foster2e227172014-09-09 11:56:13 +1000183 const char *buf,
Bill O'Donnella27c26402015-10-12 05:18:45 +1100184 size_t count)
Brian Foster2e227172014-09-09 11:56:13 +1000185{
186 int ret;
187 int val;
188
189 ret = kstrtoint(buf, 0, &val);
190 if (ret)
191 return ret;
192
193 if (val < 0 || val > 60)
194 return -EINVAL;
195
196 xfs_globals.log_recovery_delay = val;
197
198 return count;
199}
200
201STATIC ssize_t
202log_recovery_delay_show(
Bill O'Donnella27c26402015-10-12 05:18:45 +1100203 struct kobject *kobject,
204 char *buf)
Brian Foster2e227172014-09-09 11:56:13 +1000205{
206 return snprintf(buf, PAGE_SIZE, "%d\n", xfs_globals.log_recovery_delay);
207}
208XFS_SYSFS_ATTR_RW(log_recovery_delay);
209
Brian Foster65b65732014-09-09 11:52:42 +1000210static struct attribute *xfs_dbg_attrs[] = {
Brian Fosterccdab3d2017-06-14 21:29:12 -0700211 ATTR_LIST(bug_on_assert),
Brian Foster2e227172014-09-09 11:56:13 +1000212 ATTR_LIST(log_recovery_delay),
Brian Foster65b65732014-09-09 11:52:42 +1000213 NULL,
214};
215
Brian Foster65b65732014-09-09 11:52:42 +1000216struct kobj_type xfs_dbg_ktype = {
217 .release = xfs_sysfs_release,
Bill O'Donnella27c26402015-10-12 05:18:45 +1100218 .sysfs_ops = &xfs_sysfs_ops,
Brian Foster65b65732014-09-09 11:52:42 +1000219 .default_attrs = xfs_dbg_attrs,
220};
221
222#endif /* DEBUG */
223
Bill O'Donnellbb230c12015-10-12 05:15:45 +1100224/* stats */
225
Bill O'Donnell80529c42015-10-12 05:19:45 +1100226static inline struct xstats *
227to_xstats(struct kobject *kobject)
228{
229 struct xfs_kobj *kobj = to_kobj(kobject);
230
231 return container_of(kobj, struct xstats, xs_kobj);
232}
233
Bill O'Donnellbb230c12015-10-12 05:15:45 +1100234STATIC ssize_t
235stats_show(
Bill O'Donnella27c26402015-10-12 05:18:45 +1100236 struct kobject *kobject,
237 char *buf)
Bill O'Donnellbb230c12015-10-12 05:15:45 +1100238{
Bill O'Donnell80529c42015-10-12 05:19:45 +1100239 struct xstats *stats = to_xstats(kobject);
240
241 return xfs_stats_format(stats->xs_stats, buf);
Bill O'Donnellbb230c12015-10-12 05:15:45 +1100242}
243XFS_SYSFS_ATTR_RO(stats);
244
245STATIC ssize_t
246stats_clear_store(
Bill O'Donnella27c26402015-10-12 05:18:45 +1100247 struct kobject *kobject,
Bill O'Donnellbb230c12015-10-12 05:15:45 +1100248 const char *buf,
Bill O'Donnella27c26402015-10-12 05:18:45 +1100249 size_t count)
Bill O'Donnellbb230c12015-10-12 05:15:45 +1100250{
251 int ret;
252 int val;
Bill O'Donnell80529c42015-10-12 05:19:45 +1100253 struct xstats *stats = to_xstats(kobject);
Bill O'Donnellbb230c12015-10-12 05:15:45 +1100254
255 ret = kstrtoint(buf, 0, &val);
256 if (ret)
257 return ret;
258
259 if (val != 1)
260 return -EINVAL;
Bill O'Donnell80529c42015-10-12 05:19:45 +1100261
262 xfs_stats_clearall(stats->xs_stats);
Bill O'Donnellbb230c12015-10-12 05:15:45 +1100263 return count;
264}
265XFS_SYSFS_ATTR_WO(stats_clear);
266
267static struct attribute *xfs_stats_attrs[] = {
268 ATTR_LIST(stats),
269 ATTR_LIST(stats_clear),
270 NULL,
271};
272
Bill O'Donnellbb230c12015-10-12 05:15:45 +1100273struct kobj_type xfs_stats_ktype = {
274 .release = xfs_sysfs_release,
Bill O'Donnella27c26402015-10-12 05:18:45 +1100275 .sysfs_ops = &xfs_sysfs_ops,
Bill O'Donnellbb230c12015-10-12 05:15:45 +1100276 .default_attrs = xfs_stats_attrs,
277};
278
Brian Fosterbaff4e42014-07-15 08:07:29 +1000279/* xlog */
280
Bill O'Donnella27c26402015-10-12 05:18:45 +1100281static inline struct xlog *
282to_xlog(struct kobject *kobject)
283{
284 struct xfs_kobj *kobj = to_kobj(kobject);
285
286 return container_of(kobj, struct xlog, l_kobj);
287}
288
Brian Foster80d6d692014-07-15 08:07:48 +1000289STATIC ssize_t
290log_head_lsn_show(
Bill O'Donnella27c26402015-10-12 05:18:45 +1100291 struct kobject *kobject,
292 char *buf)
Brian Foster80d6d692014-07-15 08:07:48 +1000293{
Brian Foster80d6d692014-07-15 08:07:48 +1000294 int cycle;
295 int block;
Bill O'Donnella27c26402015-10-12 05:18:45 +1100296 struct xlog *log = to_xlog(kobject);
Brian Foster80d6d692014-07-15 08:07:48 +1000297
298 spin_lock(&log->l_icloglock);
299 cycle = log->l_curr_cycle;
300 block = log->l_curr_block;
301 spin_unlock(&log->l_icloglock);
302
303 return snprintf(buf, PAGE_SIZE, "%d:%d\n", cycle, block);
304}
305XFS_SYSFS_ATTR_RO(log_head_lsn);
306
307STATIC ssize_t
308log_tail_lsn_show(
Bill O'Donnella27c26402015-10-12 05:18:45 +1100309 struct kobject *kobject,
310 char *buf)
Brian Foster80d6d692014-07-15 08:07:48 +1000311{
Brian Foster80d6d692014-07-15 08:07:48 +1000312 int cycle;
313 int block;
Bill O'Donnella27c26402015-10-12 05:18:45 +1100314 struct xlog *log = to_xlog(kobject);
Brian Foster80d6d692014-07-15 08:07:48 +1000315
316 xlog_crack_atomic_lsn(&log->l_tail_lsn, &cycle, &block);
317 return snprintf(buf, PAGE_SIZE, "%d:%d\n", cycle, block);
318}
319XFS_SYSFS_ATTR_RO(log_tail_lsn);
320
321STATIC ssize_t
322reserve_grant_head_show(
Bill O'Donnella27c26402015-10-12 05:18:45 +1100323 struct kobject *kobject,
324 char *buf)
325
Brian Foster80d6d692014-07-15 08:07:48 +1000326{
Brian Foster80d6d692014-07-15 08:07:48 +1000327 int cycle;
328 int bytes;
Bill O'Donnella27c26402015-10-12 05:18:45 +1100329 struct xlog *log = to_xlog(kobject);
Brian Foster80d6d692014-07-15 08:07:48 +1000330
331 xlog_crack_grant_head(&log->l_reserve_head.grant, &cycle, &bytes);
332 return snprintf(buf, PAGE_SIZE, "%d:%d\n", cycle, bytes);
333}
334XFS_SYSFS_ATTR_RO(reserve_grant_head);
335
336STATIC ssize_t
337write_grant_head_show(
Bill O'Donnella27c26402015-10-12 05:18:45 +1100338 struct kobject *kobject,
339 char *buf)
Brian Foster80d6d692014-07-15 08:07:48 +1000340{
Brian Foster80d6d692014-07-15 08:07:48 +1000341 int cycle;
342 int bytes;
Bill O'Donnella27c26402015-10-12 05:18:45 +1100343 struct xlog *log = to_xlog(kobject);
Brian Foster80d6d692014-07-15 08:07:48 +1000344
345 xlog_crack_grant_head(&log->l_write_head.grant, &cycle, &bytes);
346 return snprintf(buf, PAGE_SIZE, "%d:%d\n", cycle, bytes);
347}
348XFS_SYSFS_ATTR_RO(write_grant_head);
349
Brian Foster609adfc2016-01-05 07:41:16 +1100350#ifdef DEBUG
351STATIC ssize_t
352log_badcrc_factor_store(
353 struct kobject *kobject,
354 const char *buf,
355 size_t count)
356{
357 struct xlog *log = to_xlog(kobject);
358 int ret;
359 uint32_t val;
360
361 ret = kstrtouint(buf, 0, &val);
362 if (ret)
363 return ret;
364
365 log->l_badcrc_factor = val;
366
367 return count;
368}
369
370STATIC ssize_t
371log_badcrc_factor_show(
372 struct kobject *kobject,
373 char *buf)
374{
375 struct xlog *log = to_xlog(kobject);
376
377 return snprintf(buf, PAGE_SIZE, "%d\n", log->l_badcrc_factor);
378}
379
380XFS_SYSFS_ATTR_RW(log_badcrc_factor);
381#endif /* DEBUG */
382
Brian Fosterbaff4e42014-07-15 08:07:29 +1000383static struct attribute *xfs_log_attrs[] = {
Brian Foster80d6d692014-07-15 08:07:48 +1000384 ATTR_LIST(log_head_lsn),
385 ATTR_LIST(log_tail_lsn),
386 ATTR_LIST(reserve_grant_head),
387 ATTR_LIST(write_grant_head),
Brian Foster609adfc2016-01-05 07:41:16 +1100388#ifdef DEBUG
389 ATTR_LIST(log_badcrc_factor),
390#endif
Brian Fosterbaff4e42014-07-15 08:07:29 +1000391 NULL,
392};
393
Brian Fosterbaff4e42014-07-15 08:07:29 +1000394struct kobj_type xfs_log_ktype = {
395 .release = xfs_sysfs_release,
Bill O'Donnella27c26402015-10-12 05:18:45 +1100396 .sysfs_ops = &xfs_sysfs_ops,
Brian Fosterbaff4e42014-07-15 08:07:29 +1000397 .default_attrs = xfs_log_attrs,
398};
Carlos Maiolino192852b2016-05-18 10:58:51 +1000399
400/*
401 * Metadata IO error configuration
402 *
403 * The sysfs structure here is:
404 * ...xfs/<dev>/error/<class>/<errno>/<error_attrs>
405 *
406 * where <class> allows us to discriminate between data IO and metadata IO,
407 * and any other future type of IO (e.g. special inode or directory error
408 * handling) we care to support.
409 */
Carlos Maiolino192852b2016-05-18 10:58:51 +1000410static inline struct xfs_error_cfg *
411to_error_cfg(struct kobject *kobject)
412{
413 struct xfs_kobj *kobj = to_kobj(kobject);
414 return container_of(kobj, struct xfs_error_cfg, kobj);
415}
416
Carlos Maiolinoe6b3bb72016-05-18 11:11:27 +1000417static inline struct xfs_mount *
418err_to_mp(struct kobject *kobject)
419{
420 struct xfs_kobj *kobj = to_kobj(kobject);
421 return container_of(kobj, struct xfs_mount, m_error_kobj);
422}
423
Carlos Maiolinoa5ea70d2016-05-18 11:08:15 +1000424static ssize_t
425max_retries_show(
426 struct kobject *kobject,
427 char *buf)
428{
Eric Sandeen77169812016-09-14 07:51:30 +1000429 int retries;
Carlos Maiolinoa5ea70d2016-05-18 11:08:15 +1000430 struct xfs_error_cfg *cfg = to_error_cfg(kobject);
431
Carlos Maiolinoff97f232017-01-03 20:34:17 -0800432 if (cfg->max_retries == XFS_ERR_RETRY_FOREVER)
Eric Sandeen77169812016-09-14 07:51:30 +1000433 retries = -1;
434 else
435 retries = cfg->max_retries;
436
437 return snprintf(buf, PAGE_SIZE, "%d\n", retries);
Carlos Maiolinoa5ea70d2016-05-18 11:08:15 +1000438}
439
440static ssize_t
441max_retries_store(
442 struct kobject *kobject,
443 const char *buf,
444 size_t count)
445{
446 struct xfs_error_cfg *cfg = to_error_cfg(kobject);
447 int ret;
448 int val;
449
450 ret = kstrtoint(buf, 0, &val);
451 if (ret)
452 return ret;
453
454 if (val < -1)
455 return -EINVAL;
456
Eric Sandeen77169812016-09-14 07:51:30 +1000457 if (val == -1)
Carlos Maiolinoff97f232017-01-03 20:34:17 -0800458 cfg->max_retries = XFS_ERR_RETRY_FOREVER;
Eric Sandeen77169812016-09-14 07:51:30 +1000459 else
460 cfg->max_retries = val;
Carlos Maiolinoa5ea70d2016-05-18 11:08:15 +1000461 return count;
462}
463XFS_SYSFS_ATTR_RW(max_retries);
464
465static ssize_t
466retry_timeout_seconds_show(
467 struct kobject *kobject,
468 char *buf)
469{
Eric Sandeen77169812016-09-14 07:51:30 +1000470 int timeout;
Carlos Maiolinoa5ea70d2016-05-18 11:08:15 +1000471 struct xfs_error_cfg *cfg = to_error_cfg(kobject);
472
Eric Sandeen77169812016-09-14 07:51:30 +1000473 if (cfg->retry_timeout == XFS_ERR_RETRY_FOREVER)
474 timeout = -1;
475 else
476 timeout = jiffies_to_msecs(cfg->retry_timeout) / MSEC_PER_SEC;
477
478 return snprintf(buf, PAGE_SIZE, "%d\n", timeout);
Carlos Maiolinoa5ea70d2016-05-18 11:08:15 +1000479}
480
481static ssize_t
482retry_timeout_seconds_store(
483 struct kobject *kobject,
484 const char *buf,
485 size_t count)
486{
487 struct xfs_error_cfg *cfg = to_error_cfg(kobject);
488 int ret;
489 int val;
490
491 ret = kstrtoint(buf, 0, &val);
492 if (ret)
493 return ret;
494
Eric Sandeen77169812016-09-14 07:51:30 +1000495 /* 1 day timeout maximum, -1 means infinite */
496 if (val < -1 || val > 86400)
Carlos Maiolinoa5ea70d2016-05-18 11:08:15 +1000497 return -EINVAL;
498
Eric Sandeen77169812016-09-14 07:51:30 +1000499 if (val == -1)
500 cfg->retry_timeout = XFS_ERR_RETRY_FOREVER;
501 else {
502 cfg->retry_timeout = msecs_to_jiffies(val * MSEC_PER_SEC);
503 ASSERT(msecs_to_jiffies(val * MSEC_PER_SEC) < LONG_MAX);
504 }
Carlos Maiolinoa5ea70d2016-05-18 11:08:15 +1000505 return count;
506}
507XFS_SYSFS_ATTR_RW(retry_timeout_seconds);
508
Carlos Maiolinoe6b3bb72016-05-18 11:11:27 +1000509static ssize_t
510fail_at_unmount_show(
511 struct kobject *kobject,
512 char *buf)
513{
514 struct xfs_mount *mp = err_to_mp(kobject);
515
516 return snprintf(buf, PAGE_SIZE, "%d\n", mp->m_fail_unmount);
517}
518
519static ssize_t
520fail_at_unmount_store(
521 struct kobject *kobject,
522 const char *buf,
523 size_t count)
524{
525 struct xfs_mount *mp = err_to_mp(kobject);
526 int ret;
527 int val;
528
529 ret = kstrtoint(buf, 0, &val);
530 if (ret)
531 return ret;
532
533 if (val < 0 || val > 1)
534 return -EINVAL;
535
536 mp->m_fail_unmount = val;
537 return count;
538}
539XFS_SYSFS_ATTR_RW(fail_at_unmount);
540
Carlos Maiolinoa5ea70d2016-05-18 11:08:15 +1000541static struct attribute *xfs_error_attrs[] = {
542 ATTR_LIST(max_retries),
543 ATTR_LIST(retry_timeout_seconds),
544 NULL,
545};
546
547
Eric Biggersf1b82432016-10-20 15:42:30 +1100548static struct kobj_type xfs_error_cfg_ktype = {
Carlos Maiolino192852b2016-05-18 10:58:51 +1000549 .release = xfs_sysfs_release,
550 .sysfs_ops = &xfs_sysfs_ops,
551 .default_attrs = xfs_error_attrs,
552};
553
Eric Biggersf1b82432016-10-20 15:42:30 +1100554static struct kobj_type xfs_error_ktype = {
Carlos Maiolino192852b2016-05-18 10:58:51 +1000555 .release = xfs_sysfs_release,
Carlos Maiolinoe6b3bb72016-05-18 11:11:27 +1000556 .sysfs_ops = &xfs_sysfs_ops,
Carlos Maiolino192852b2016-05-18 10:58:51 +1000557};
558
Carlos Maiolinoef6a50f2016-05-18 11:06:44 +1000559/*
560 * Error initialization tables. These need to be ordered in the same
561 * order as the enums used to index the array. All class init tables need to
562 * define a "default" behaviour as the first entry, all other entries can be
563 * empty.
564 */
565struct xfs_error_init {
566 char *name;
567 int max_retries;
Carlos Maiolinoa5ea70d2016-05-18 11:08:15 +1000568 int retry_timeout; /* in seconds */
Carlos Maiolinoef6a50f2016-05-18 11:06:44 +1000569};
570
571static const struct xfs_error_init xfs_error_meta_init[XFS_ERR_ERRNO_MAX] = {
572 { .name = "default",
Carlos Maiolinoe0a431b32016-05-18 11:09:28 +1000573 .max_retries = XFS_ERR_RETRY_FOREVER,
Eric Sandeen77169812016-09-14 07:51:30 +1000574 .retry_timeout = XFS_ERR_RETRY_FOREVER,
Carlos Maiolinoef6a50f2016-05-18 11:06:44 +1000575 },
Carlos Maiolinoe0a431b32016-05-18 11:09:28 +1000576 { .name = "EIO",
577 .max_retries = XFS_ERR_RETRY_FOREVER,
Eric Sandeen77169812016-09-14 07:51:30 +1000578 .retry_timeout = XFS_ERR_RETRY_FOREVER,
Carlos Maiolinoe0a431b32016-05-18 11:09:28 +1000579 },
580 { .name = "ENOSPC",
581 .max_retries = XFS_ERR_RETRY_FOREVER,
Eric Sandeen77169812016-09-14 07:51:30 +1000582 .retry_timeout = XFS_ERR_RETRY_FOREVER,
Carlos Maiolinoe0a431b32016-05-18 11:09:28 +1000583 },
584 { .name = "ENODEV",
Eric Sandeen77169812016-09-14 07:51:30 +1000585 .max_retries = 0, /* We can't recover from devices disappearing */
586 .retry_timeout = 0,
Carlos Maiolinoe0a431b32016-05-18 11:09:28 +1000587 },
Carlos Maiolinoef6a50f2016-05-18 11:06:44 +1000588};
589
590static int
591xfs_error_sysfs_init_class(
592 struct xfs_mount *mp,
593 int class,
594 const char *parent_name,
595 struct xfs_kobj *parent_kobj,
596 const struct xfs_error_init init[])
597{
598 struct xfs_error_cfg *cfg;
599 int error;
600 int i;
601
602 ASSERT(class < XFS_ERR_CLASS_MAX);
603
604 error = xfs_sysfs_init(parent_kobj, &xfs_error_ktype,
605 &mp->m_error_kobj, parent_name);
606 if (error)
607 return error;
608
609 for (i = 0; i < XFS_ERR_ERRNO_MAX; i++) {
610 cfg = &mp->m_error_cfg[class][i];
611 error = xfs_sysfs_init(&cfg->kobj, &xfs_error_cfg_ktype,
612 parent_kobj, init[i].name);
613 if (error)
614 goto out_error;
615
616 cfg->max_retries = init[i].max_retries;
Eric Sandeen77169812016-09-14 07:51:30 +1000617 if (init[i].retry_timeout == XFS_ERR_RETRY_FOREVER)
618 cfg->retry_timeout = XFS_ERR_RETRY_FOREVER;
619 else
620 cfg->retry_timeout = msecs_to_jiffies(
Carlos Maiolinoa5ea70d2016-05-18 11:08:15 +1000621 init[i].retry_timeout * MSEC_PER_SEC);
Carlos Maiolinoef6a50f2016-05-18 11:06:44 +1000622 }
623 return 0;
624
625out_error:
626 /* unwind the entries that succeeded */
627 for (i--; i >= 0; i--) {
628 cfg = &mp->m_error_cfg[class][i];
629 xfs_sysfs_del(&cfg->kobj);
630 }
631 xfs_sysfs_del(parent_kobj);
632 return error;
633}
634
Carlos Maiolino192852b2016-05-18 10:58:51 +1000635int
636xfs_error_sysfs_init(
637 struct xfs_mount *mp)
638{
639 int error;
640
641 /* .../xfs/<dev>/error/ */
642 error = xfs_sysfs_init(&mp->m_error_kobj, &xfs_error_ktype,
643 &mp->m_kobj, "error");
Carlos Maiolinoffd40ef2016-05-18 11:01:00 +1000644 if (error)
645 return error;
646
Carlos Maiolinoe6b3bb72016-05-18 11:11:27 +1000647 error = sysfs_create_file(&mp->m_error_kobj.kobject,
648 ATTR_LIST(fail_at_unmount));
649
650 if (error)
651 goto out_error;
652
Carlos Maiolinoffd40ef2016-05-18 11:01:00 +1000653 /* .../xfs/<dev>/error/metadata/ */
Carlos Maiolinoef6a50f2016-05-18 11:06:44 +1000654 error = xfs_error_sysfs_init_class(mp, XFS_ERR_METADATA,
655 "metadata", &mp->m_error_meta_kobj,
656 xfs_error_meta_init);
Carlos Maiolinoffd40ef2016-05-18 11:01:00 +1000657 if (error)
658 goto out_error;
659
Carlos Maiolinoffd40ef2016-05-18 11:01:00 +1000660 return 0;
661
Carlos Maiolinoffd40ef2016-05-18 11:01:00 +1000662out_error:
663 xfs_sysfs_del(&mp->m_error_kobj);
Carlos Maiolino192852b2016-05-18 10:58:51 +1000664 return error;
665}
666
667void
668xfs_error_sysfs_del(
669 struct xfs_mount *mp)
670{
Carlos Maiolinoffd40ef2016-05-18 11:01:00 +1000671 struct xfs_error_cfg *cfg;
672 int i, j;
673
674 for (i = 0; i < XFS_ERR_CLASS_MAX; i++) {
675 for (j = 0; j < XFS_ERR_ERRNO_MAX; j++) {
676 cfg = &mp->m_error_cfg[i][j];
677
678 xfs_sysfs_del(&cfg->kobj);
679 }
680 }
681 xfs_sysfs_del(&mp->m_error_meta_kobj);
Carlos Maiolino192852b2016-05-18 10:58:51 +1000682 xfs_sysfs_del(&mp->m_error_kobj);
683}
Carlos Maiolinodf309392016-05-18 11:05:33 +1000684
685struct xfs_error_cfg *
686xfs_error_get_cfg(
687 struct xfs_mount *mp,
688 int error_class,
689 int error)
690{
691 struct xfs_error_cfg *cfg;
692
Eric Sandeene97f6c52016-07-20 10:48:51 +1000693 if (error < 0)
694 error = -error;
695
Carlos Maiolinodf309392016-05-18 11:05:33 +1000696 switch (error) {
Carlos Maiolinoe0a431b32016-05-18 11:09:28 +1000697 case EIO:
698 cfg = &mp->m_error_cfg[error_class][XFS_ERR_EIO];
699 break;
700 case ENOSPC:
701 cfg = &mp->m_error_cfg[error_class][XFS_ERR_ENOSPC];
702 break;
703 case ENODEV:
704 cfg = &mp->m_error_cfg[error_class][XFS_ERR_ENODEV];
705 break;
Carlos Maiolinodf309392016-05-18 11:05:33 +1000706 default:
707 cfg = &mp->m_error_cfg[error_class][XFS_ERR_DEFAULT];
708 break;
709 }
710
711 return cfg;
712}