10b61f8a4SDave Chinner // SPDX-License-Identifier: GPL-2.0
2a31b1d3dSBrian Foster /*
3a31b1d3dSBrian Foster * Copyright (c) 2014 Red Hat, Inc.
4a31b1d3dSBrian Foster * All Rights Reserved.
5a31b1d3dSBrian Foster */
6a31b1d3dSBrian Foster
7a31b1d3dSBrian Foster #include "xfs.h"
8192852beSCarlos Maiolino #include "xfs_shared.h"
9801cc4e1SBrian Foster #include "xfs_format.h"
10baff4e44SBrian Foster #include "xfs_log_format.h"
11801cc4e1SBrian Foster #include "xfs_trans_resv.h"
12192852beSCarlos Maiolino #include "xfs_sysfs.h"
130020a190SDave Chinner #include "xfs_log.h"
14baff4e44SBrian Foster #include "xfs_log_priv.h"
15801cc4e1SBrian Foster #include "xfs_mount.h"
16a31b1d3dSBrian Foster
17a31b1d3dSBrian Foster struct xfs_sysfs_attr {
18a31b1d3dSBrian Foster struct attribute attr;
19a27c2640SBill O'Donnell ssize_t (*show)(struct kobject *kobject, char *buf);
20a27c2640SBill O'Donnell ssize_t (*store)(struct kobject *kobject, const char *buf,
21a27c2640SBill O'Donnell size_t count);
22a31b1d3dSBrian Foster };
23a31b1d3dSBrian Foster
24a31b1d3dSBrian Foster static inline struct xfs_sysfs_attr *
to_attr(struct attribute * attr)25a31b1d3dSBrian Foster to_attr(struct attribute *attr)
26a31b1d3dSBrian Foster {
27a31b1d3dSBrian Foster return container_of(attr, struct xfs_sysfs_attr, attr);
28a31b1d3dSBrian Foster }
29a31b1d3dSBrian Foster
30a31b1d3dSBrian Foster #define XFS_SYSFS_ATTR_RW(name) \
31a31b1d3dSBrian Foster static struct xfs_sysfs_attr xfs_sysfs_attr_##name = __ATTR_RW(name)
32a31b1d3dSBrian Foster #define XFS_SYSFS_ATTR_RO(name) \
33a31b1d3dSBrian Foster static struct xfs_sysfs_attr xfs_sysfs_attr_##name = __ATTR_RO(name)
34bb230c12SBill O'Donnell #define XFS_SYSFS_ATTR_WO(name) \
35bb230c12SBill O'Donnell static struct xfs_sysfs_attr xfs_sysfs_attr_##name = __ATTR_WO(name)
36a31b1d3dSBrian Foster
37a31b1d3dSBrian Foster #define ATTR_LIST(name) &xfs_sysfs_attr_##name.attr
38a31b1d3dSBrian Foster
39a27c2640SBill O'Donnell STATIC ssize_t
xfs_sysfs_object_show(struct kobject * kobject,struct attribute * attr,char * buf)40a27c2640SBill O'Donnell xfs_sysfs_object_show(
41a27c2640SBill O'Donnell struct kobject *kobject,
42a27c2640SBill O'Donnell struct attribute *attr,
43a27c2640SBill O'Donnell char *buf)
44a27c2640SBill O'Donnell {
45a27c2640SBill O'Donnell struct xfs_sysfs_attr *xfs_attr = to_attr(attr);
46a27c2640SBill O'Donnell
47a27c2640SBill O'Donnell return xfs_attr->show ? xfs_attr->show(kobject, buf) : 0;
48a27c2640SBill O'Donnell }
49a27c2640SBill O'Donnell
50a27c2640SBill O'Donnell STATIC ssize_t
xfs_sysfs_object_store(struct kobject * kobject,struct attribute * attr,const char * buf,size_t count)51a27c2640SBill O'Donnell xfs_sysfs_object_store(
52a27c2640SBill O'Donnell struct kobject *kobject,
53a27c2640SBill O'Donnell struct attribute *attr,
54a27c2640SBill O'Donnell const char *buf,
55a27c2640SBill O'Donnell size_t count)
56a27c2640SBill O'Donnell {
57a27c2640SBill O'Donnell struct xfs_sysfs_attr *xfs_attr = to_attr(attr);
58a27c2640SBill O'Donnell
59a27c2640SBill O'Donnell return xfs_attr->store ? xfs_attr->store(kobject, buf, count) : 0;
60a27c2640SBill O'Donnell }
61a27c2640SBill O'Donnell
62a27c2640SBill O'Donnell static const struct sysfs_ops xfs_sysfs_ops = {
63a27c2640SBill O'Donnell .show = xfs_sysfs_object_show,
64a27c2640SBill O'Donnell .store = xfs_sysfs_object_store,
65a27c2640SBill O'Donnell };
66a27c2640SBill O'Donnell
67801cc4e1SBrian Foster static struct attribute *xfs_mp_attrs[] = {
68801cc4e1SBrian Foster NULL,
69801cc4e1SBrian Foster };
70219aac5dSGreg Kroah-Hartman ATTRIBUTE_GROUPS(xfs_mp);
71801cc4e1SBrian Foster
72*2ee83335SThomas Weißschuh const struct kobj_type xfs_mp_ktype = {
73801cc4e1SBrian Foster .release = xfs_sysfs_release,
74801cc4e1SBrian Foster .sysfs_ops = &xfs_sysfs_ops,
75219aac5dSGreg Kroah-Hartman .default_groups = xfs_mp_groups,
76801cc4e1SBrian Foster };
77801cc4e1SBrian Foster
7865b65735SBrian Foster #ifdef DEBUG
7965b65735SBrian Foster /* debug */
8065b65735SBrian Foster
812e227178SBrian Foster STATIC ssize_t
bug_on_assert_store(struct kobject * kobject,const char * buf,size_t count)82ccdab3d6SBrian Foster bug_on_assert_store(
83ccdab3d6SBrian Foster struct kobject *kobject,
84ccdab3d6SBrian Foster const char *buf,
85ccdab3d6SBrian Foster size_t count)
86ccdab3d6SBrian Foster {
87ccdab3d6SBrian Foster int ret;
88ccdab3d6SBrian Foster int val;
89ccdab3d6SBrian Foster
90ccdab3d6SBrian Foster ret = kstrtoint(buf, 0, &val);
91ccdab3d6SBrian Foster if (ret)
92ccdab3d6SBrian Foster return ret;
93ccdab3d6SBrian Foster
94ccdab3d6SBrian Foster if (val == 1)
95ccdab3d6SBrian Foster xfs_globals.bug_on_assert = true;
96ccdab3d6SBrian Foster else if (val == 0)
97ccdab3d6SBrian Foster xfs_globals.bug_on_assert = false;
98ccdab3d6SBrian Foster else
99ccdab3d6SBrian Foster return -EINVAL;
100ccdab3d6SBrian Foster
101ccdab3d6SBrian Foster return count;
102ccdab3d6SBrian Foster }
103ccdab3d6SBrian Foster
104ccdab3d6SBrian Foster STATIC ssize_t
bug_on_assert_show(struct kobject * kobject,char * buf)105ccdab3d6SBrian Foster bug_on_assert_show(
106ccdab3d6SBrian Foster struct kobject *kobject,
107ccdab3d6SBrian Foster char *buf)
108ccdab3d6SBrian Foster {
10953eb47b4SQing Wang return sysfs_emit(buf, "%d\n", xfs_globals.bug_on_assert);
110ccdab3d6SBrian Foster }
111ccdab3d6SBrian Foster XFS_SYSFS_ATTR_RW(bug_on_assert);
112ccdab3d6SBrian Foster
113ccdab3d6SBrian Foster STATIC ssize_t
log_recovery_delay_store(struct kobject * kobject,const char * buf,size_t count)1142e227178SBrian Foster log_recovery_delay_store(
115a27c2640SBill O'Donnell struct kobject *kobject,
1162e227178SBrian Foster const char *buf,
117a27c2640SBill O'Donnell size_t count)
1182e227178SBrian Foster {
1192e227178SBrian Foster int ret;
1202e227178SBrian Foster int val;
1212e227178SBrian Foster
1222e227178SBrian Foster ret = kstrtoint(buf, 0, &val);
1232e227178SBrian Foster if (ret)
1242e227178SBrian Foster return ret;
1252e227178SBrian Foster
1262e227178SBrian Foster if (val < 0 || val > 60)
1272e227178SBrian Foster return -EINVAL;
1282e227178SBrian Foster
1292e227178SBrian Foster xfs_globals.log_recovery_delay = val;
1302e227178SBrian Foster
1312e227178SBrian Foster return count;
1322e227178SBrian Foster }
1332e227178SBrian Foster
1342e227178SBrian Foster STATIC ssize_t
log_recovery_delay_show(struct kobject * kobject,char * buf)1352e227178SBrian Foster log_recovery_delay_show(
136a27c2640SBill O'Donnell struct kobject *kobject,
137a27c2640SBill O'Donnell char *buf)
1382e227178SBrian Foster {
13953eb47b4SQing Wang return sysfs_emit(buf, "%d\n", xfs_globals.log_recovery_delay);
1402e227178SBrian Foster }
1412e227178SBrian Foster XFS_SYSFS_ATTR_RW(log_recovery_delay);
1422e227178SBrian Foster
143dae5cd81SDave Chinner STATIC ssize_t
mount_delay_store(struct kobject * kobject,const char * buf,size_t count)144dae5cd81SDave Chinner mount_delay_store(
145dae5cd81SDave Chinner struct kobject *kobject,
146dae5cd81SDave Chinner const char *buf,
147dae5cd81SDave Chinner size_t count)
148dae5cd81SDave Chinner {
149dae5cd81SDave Chinner int ret;
150dae5cd81SDave Chinner int val;
151dae5cd81SDave Chinner
152dae5cd81SDave Chinner ret = kstrtoint(buf, 0, &val);
153dae5cd81SDave Chinner if (ret)
154dae5cd81SDave Chinner return ret;
155dae5cd81SDave Chinner
156dae5cd81SDave Chinner if (val < 0 || val > 60)
157dae5cd81SDave Chinner return -EINVAL;
158dae5cd81SDave Chinner
159dae5cd81SDave Chinner xfs_globals.mount_delay = val;
160dae5cd81SDave Chinner
161dae5cd81SDave Chinner return count;
162dae5cd81SDave Chinner }
163dae5cd81SDave Chinner
164dae5cd81SDave Chinner STATIC ssize_t
mount_delay_show(struct kobject * kobject,char * buf)165dae5cd81SDave Chinner mount_delay_show(
166dae5cd81SDave Chinner struct kobject *kobject,
167dae5cd81SDave Chinner char *buf)
168dae5cd81SDave Chinner {
16953eb47b4SQing Wang return sysfs_emit(buf, "%d\n", xfs_globals.mount_delay);
170dae5cd81SDave Chinner }
171dae5cd81SDave Chinner XFS_SYSFS_ATTR_RW(mount_delay);
172dae5cd81SDave Chinner
17366ae56a5SChristoph Hellwig static ssize_t
always_cow_store(struct kobject * kobject,const char * buf,size_t count)17466ae56a5SChristoph Hellwig always_cow_store(
17566ae56a5SChristoph Hellwig struct kobject *kobject,
17666ae56a5SChristoph Hellwig const char *buf,
17766ae56a5SChristoph Hellwig size_t count)
17866ae56a5SChristoph Hellwig {
17966ae56a5SChristoph Hellwig ssize_t ret;
18066ae56a5SChristoph Hellwig
18166ae56a5SChristoph Hellwig ret = kstrtobool(buf, &xfs_globals.always_cow);
18266ae56a5SChristoph Hellwig if (ret < 0)
18366ae56a5SChristoph Hellwig return ret;
18466ae56a5SChristoph Hellwig return count;
18566ae56a5SChristoph Hellwig }
18666ae56a5SChristoph Hellwig
18766ae56a5SChristoph Hellwig static ssize_t
always_cow_show(struct kobject * kobject,char * buf)18866ae56a5SChristoph Hellwig always_cow_show(
18966ae56a5SChristoph Hellwig struct kobject *kobject,
19066ae56a5SChristoph Hellwig char *buf)
19166ae56a5SChristoph Hellwig {
19253eb47b4SQing Wang return sysfs_emit(buf, "%d\n", xfs_globals.always_cow);
19366ae56a5SChristoph Hellwig }
19466ae56a5SChristoph Hellwig XFS_SYSFS_ATTR_RW(always_cow);
19566ae56a5SChristoph Hellwig
19640786717SDarrick J. Wong #ifdef DEBUG
19740786717SDarrick J. Wong /*
19840786717SDarrick J. Wong * Override how many threads the parallel work queue is allowed to create.
19940786717SDarrick J. Wong * This has to be a debug-only global (instead of an errortag) because one of
20040786717SDarrick J. Wong * the main users of parallel workqueues is mount time quotacheck.
20140786717SDarrick J. Wong */
20240786717SDarrick J. Wong STATIC ssize_t
pwork_threads_store(struct kobject * kobject,const char * buf,size_t count)20340786717SDarrick J. Wong pwork_threads_store(
20440786717SDarrick J. Wong struct kobject *kobject,
20540786717SDarrick J. Wong const char *buf,
20640786717SDarrick J. Wong size_t count)
20740786717SDarrick J. Wong {
20840786717SDarrick J. Wong int ret;
20940786717SDarrick J. Wong int val;
21040786717SDarrick J. Wong
21140786717SDarrick J. Wong ret = kstrtoint(buf, 0, &val);
21240786717SDarrick J. Wong if (ret)
21340786717SDarrick J. Wong return ret;
21440786717SDarrick J. Wong
21540786717SDarrick J. Wong if (val < -1 || val > num_possible_cpus())
21640786717SDarrick J. Wong return -EINVAL;
21740786717SDarrick J. Wong
21840786717SDarrick J. Wong xfs_globals.pwork_threads = val;
21940786717SDarrick J. Wong
22040786717SDarrick J. Wong return count;
22140786717SDarrick J. Wong }
22240786717SDarrick J. Wong
22340786717SDarrick J. Wong STATIC ssize_t
pwork_threads_show(struct kobject * kobject,char * buf)22440786717SDarrick J. Wong pwork_threads_show(
22540786717SDarrick J. Wong struct kobject *kobject,
22640786717SDarrick J. Wong char *buf)
22740786717SDarrick J. Wong {
22853eb47b4SQing Wang return sysfs_emit(buf, "%d\n", xfs_globals.pwork_threads);
22940786717SDarrick J. Wong }
23040786717SDarrick J. Wong XFS_SYSFS_ATTR_RW(pwork_threads);
231535e2f75SAllison Henderson
232535e2f75SAllison Henderson static ssize_t
larp_store(struct kobject * kobject,const char * buf,size_t count)233535e2f75SAllison Henderson larp_store(
234535e2f75SAllison Henderson struct kobject *kobject,
235535e2f75SAllison Henderson const char *buf,
236535e2f75SAllison Henderson size_t count)
237535e2f75SAllison Henderson {
238535e2f75SAllison Henderson ssize_t ret;
239535e2f75SAllison Henderson
240535e2f75SAllison Henderson ret = kstrtobool(buf, &xfs_globals.larp);
241535e2f75SAllison Henderson if (ret < 0)
242535e2f75SAllison Henderson return ret;
243535e2f75SAllison Henderson return count;
244535e2f75SAllison Henderson }
245535e2f75SAllison Henderson
246535e2f75SAllison Henderson STATIC ssize_t
larp_show(struct kobject * kobject,char * buf)247535e2f75SAllison Henderson larp_show(
248535e2f75SAllison Henderson struct kobject *kobject,
249535e2f75SAllison Henderson char *buf)
250535e2f75SAllison Henderson {
251535e2f75SAllison Henderson return snprintf(buf, PAGE_SIZE, "%d\n", xfs_globals.larp);
252535e2f75SAllison Henderson }
253535e2f75SAllison Henderson XFS_SYSFS_ATTR_RW(larp);
25440786717SDarrick J. Wong #endif /* DEBUG */
25540786717SDarrick J. Wong
25665b65735SBrian Foster static struct attribute *xfs_dbg_attrs[] = {
257ccdab3d6SBrian Foster ATTR_LIST(bug_on_assert),
2582e227178SBrian Foster ATTR_LIST(log_recovery_delay),
259dae5cd81SDave Chinner ATTR_LIST(mount_delay),
26066ae56a5SChristoph Hellwig ATTR_LIST(always_cow),
26140786717SDarrick J. Wong #ifdef DEBUG
26240786717SDarrick J. Wong ATTR_LIST(pwork_threads),
263535e2f75SAllison Henderson ATTR_LIST(larp),
26440786717SDarrick J. Wong #endif
26565b65735SBrian Foster NULL,
26665b65735SBrian Foster };
267219aac5dSGreg Kroah-Hartman ATTRIBUTE_GROUPS(xfs_dbg);
26865b65735SBrian Foster
269*2ee83335SThomas Weißschuh const struct kobj_type xfs_dbg_ktype = {
27065b65735SBrian Foster .release = xfs_sysfs_release,
271a27c2640SBill O'Donnell .sysfs_ops = &xfs_sysfs_ops,
272219aac5dSGreg Kroah-Hartman .default_groups = xfs_dbg_groups,
27365b65735SBrian Foster };
27465b65735SBrian Foster
27565b65735SBrian Foster #endif /* DEBUG */
27665b65735SBrian Foster
277bb230c12SBill O'Donnell /* stats */
278bb230c12SBill O'Donnell
27980529c45SBill O'Donnell static inline struct xstats *
to_xstats(struct kobject * kobject)28080529c45SBill O'Donnell to_xstats(struct kobject *kobject)
28180529c45SBill O'Donnell {
28280529c45SBill O'Donnell struct xfs_kobj *kobj = to_kobj(kobject);
28380529c45SBill O'Donnell
28480529c45SBill O'Donnell return container_of(kobj, struct xstats, xs_kobj);
28580529c45SBill O'Donnell }
28680529c45SBill O'Donnell
287bb230c12SBill O'Donnell STATIC ssize_t
stats_show(struct kobject * kobject,char * buf)288bb230c12SBill O'Donnell stats_show(
289a27c2640SBill O'Donnell struct kobject *kobject,
290a27c2640SBill O'Donnell char *buf)
291bb230c12SBill O'Donnell {
29280529c45SBill O'Donnell struct xstats *stats = to_xstats(kobject);
29380529c45SBill O'Donnell
29480529c45SBill O'Donnell return xfs_stats_format(stats->xs_stats, buf);
295bb230c12SBill O'Donnell }
296bb230c12SBill O'Donnell XFS_SYSFS_ATTR_RO(stats);
297bb230c12SBill O'Donnell
298bb230c12SBill O'Donnell STATIC ssize_t
stats_clear_store(struct kobject * kobject,const char * buf,size_t count)299bb230c12SBill O'Donnell stats_clear_store(
300a27c2640SBill O'Donnell struct kobject *kobject,
301bb230c12SBill O'Donnell const char *buf,
302a27c2640SBill O'Donnell size_t count)
303bb230c12SBill O'Donnell {
304bb230c12SBill O'Donnell int ret;
305bb230c12SBill O'Donnell int val;
30680529c45SBill O'Donnell struct xstats *stats = to_xstats(kobject);
307bb230c12SBill O'Donnell
308bb230c12SBill O'Donnell ret = kstrtoint(buf, 0, &val);
309bb230c12SBill O'Donnell if (ret)
310bb230c12SBill O'Donnell return ret;
311bb230c12SBill O'Donnell
312bb230c12SBill O'Donnell if (val != 1)
313bb230c12SBill O'Donnell return -EINVAL;
31480529c45SBill O'Donnell
31580529c45SBill O'Donnell xfs_stats_clearall(stats->xs_stats);
316bb230c12SBill O'Donnell return count;
317bb230c12SBill O'Donnell }
318bb230c12SBill O'Donnell XFS_SYSFS_ATTR_WO(stats_clear);
319bb230c12SBill O'Donnell
320bb230c12SBill O'Donnell static struct attribute *xfs_stats_attrs[] = {
321bb230c12SBill O'Donnell ATTR_LIST(stats),
322bb230c12SBill O'Donnell ATTR_LIST(stats_clear),
323bb230c12SBill O'Donnell NULL,
324bb230c12SBill O'Donnell };
325219aac5dSGreg Kroah-Hartman ATTRIBUTE_GROUPS(xfs_stats);
326bb230c12SBill O'Donnell
327*2ee83335SThomas Weißschuh const struct kobj_type xfs_stats_ktype = {
328bb230c12SBill O'Donnell .release = xfs_sysfs_release,
329a27c2640SBill O'Donnell .sysfs_ops = &xfs_sysfs_ops,
330219aac5dSGreg Kroah-Hartman .default_groups = xfs_stats_groups,
331bb230c12SBill O'Donnell };
332bb230c12SBill O'Donnell
333baff4e44SBrian Foster /* xlog */
334baff4e44SBrian Foster
335a27c2640SBill O'Donnell static inline struct xlog *
to_xlog(struct kobject * kobject)336a27c2640SBill O'Donnell to_xlog(struct kobject *kobject)
337a27c2640SBill O'Donnell {
338a27c2640SBill O'Donnell struct xfs_kobj *kobj = to_kobj(kobject);
339a27c2640SBill O'Donnell
340a27c2640SBill O'Donnell return container_of(kobj, struct xlog, l_kobj);
341a27c2640SBill O'Donnell }
342a27c2640SBill O'Donnell
34380d6d698SBrian Foster STATIC ssize_t
log_head_lsn_show(struct kobject * kobject,char * buf)34480d6d698SBrian Foster log_head_lsn_show(
345a27c2640SBill O'Donnell struct kobject *kobject,
346a27c2640SBill O'Donnell char *buf)
34780d6d698SBrian Foster {
34880d6d698SBrian Foster int cycle;
34980d6d698SBrian Foster int block;
350a27c2640SBill O'Donnell struct xlog *log = to_xlog(kobject);
35180d6d698SBrian Foster
35280d6d698SBrian Foster spin_lock(&log->l_icloglock);
35380d6d698SBrian Foster cycle = log->l_curr_cycle;
35480d6d698SBrian Foster block = log->l_curr_block;
35580d6d698SBrian Foster spin_unlock(&log->l_icloglock);
35680d6d698SBrian Foster
35753eb47b4SQing Wang return sysfs_emit(buf, "%d:%d\n", cycle, block);
35880d6d698SBrian Foster }
35980d6d698SBrian Foster XFS_SYSFS_ATTR_RO(log_head_lsn);
36080d6d698SBrian Foster
36180d6d698SBrian Foster STATIC ssize_t
log_tail_lsn_show(struct kobject * kobject,char * buf)36280d6d698SBrian Foster log_tail_lsn_show(
363a27c2640SBill O'Donnell struct kobject *kobject,
364a27c2640SBill O'Donnell char *buf)
36580d6d698SBrian Foster {
36680d6d698SBrian Foster int cycle;
36780d6d698SBrian Foster int block;
368a27c2640SBill O'Donnell struct xlog *log = to_xlog(kobject);
36980d6d698SBrian Foster
37080d6d698SBrian Foster xlog_crack_atomic_lsn(&log->l_tail_lsn, &cycle, &block);
37153eb47b4SQing Wang return sysfs_emit(buf, "%d:%d\n", cycle, block);
37280d6d698SBrian Foster }
37380d6d698SBrian Foster XFS_SYSFS_ATTR_RO(log_tail_lsn);
37480d6d698SBrian Foster
37580d6d698SBrian Foster STATIC ssize_t
reserve_grant_head_show(struct kobject * kobject,char * buf)37680d6d698SBrian Foster reserve_grant_head_show(
377a27c2640SBill O'Donnell struct kobject *kobject,
378a27c2640SBill O'Donnell char *buf)
379a27c2640SBill O'Donnell
38080d6d698SBrian Foster {
38180d6d698SBrian Foster int cycle;
38280d6d698SBrian Foster int bytes;
383a27c2640SBill O'Donnell struct xlog *log = to_xlog(kobject);
38480d6d698SBrian Foster
38580d6d698SBrian Foster xlog_crack_grant_head(&log->l_reserve_head.grant, &cycle, &bytes);
38653eb47b4SQing Wang return sysfs_emit(buf, "%d:%d\n", cycle, bytes);
38780d6d698SBrian Foster }
38880d6d698SBrian Foster XFS_SYSFS_ATTR_RO(reserve_grant_head);
38980d6d698SBrian Foster
39080d6d698SBrian Foster STATIC ssize_t
write_grant_head_show(struct kobject * kobject,char * buf)39180d6d698SBrian Foster write_grant_head_show(
392a27c2640SBill O'Donnell struct kobject *kobject,
393a27c2640SBill O'Donnell char *buf)
39480d6d698SBrian Foster {
39580d6d698SBrian Foster int cycle;
39680d6d698SBrian Foster int bytes;
397a27c2640SBill O'Donnell struct xlog *log = to_xlog(kobject);
39880d6d698SBrian Foster
39980d6d698SBrian Foster xlog_crack_grant_head(&log->l_write_head.grant, &cycle, &bytes);
40053eb47b4SQing Wang return sysfs_emit(buf, "%d:%d\n", cycle, bytes);
40180d6d698SBrian Foster }
40280d6d698SBrian Foster XFS_SYSFS_ATTR_RO(write_grant_head);
40380d6d698SBrian Foster
404baff4e44SBrian Foster static struct attribute *xfs_log_attrs[] = {
40580d6d698SBrian Foster ATTR_LIST(log_head_lsn),
40680d6d698SBrian Foster ATTR_LIST(log_tail_lsn),
40780d6d698SBrian Foster ATTR_LIST(reserve_grant_head),
40880d6d698SBrian Foster ATTR_LIST(write_grant_head),
409baff4e44SBrian Foster NULL,
410baff4e44SBrian Foster };
411219aac5dSGreg Kroah-Hartman ATTRIBUTE_GROUPS(xfs_log);
412baff4e44SBrian Foster
413*2ee83335SThomas Weißschuh const struct kobj_type xfs_log_ktype = {
414baff4e44SBrian Foster .release = xfs_sysfs_release,
415a27c2640SBill O'Donnell .sysfs_ops = &xfs_sysfs_ops,
416219aac5dSGreg Kroah-Hartman .default_groups = xfs_log_groups,
417baff4e44SBrian Foster };
418192852beSCarlos Maiolino
419192852beSCarlos Maiolino /*
420192852beSCarlos Maiolino * Metadata IO error configuration
421192852beSCarlos Maiolino *
422192852beSCarlos Maiolino * The sysfs structure here is:
423192852beSCarlos Maiolino * ...xfs/<dev>/error/<class>/<errno>/<error_attrs>
424192852beSCarlos Maiolino *
425192852beSCarlos Maiolino * where <class> allows us to discriminate between data IO and metadata IO,
426192852beSCarlos Maiolino * and any other future type of IO (e.g. special inode or directory error
427192852beSCarlos Maiolino * handling) we care to support.
428192852beSCarlos Maiolino */
429192852beSCarlos Maiolino static inline struct xfs_error_cfg *
to_error_cfg(struct kobject * kobject)430192852beSCarlos Maiolino to_error_cfg(struct kobject *kobject)
431192852beSCarlos Maiolino {
432192852beSCarlos Maiolino struct xfs_kobj *kobj = to_kobj(kobject);
433192852beSCarlos Maiolino return container_of(kobj, struct xfs_error_cfg, kobj);
434192852beSCarlos Maiolino }
435192852beSCarlos Maiolino
436e6b3bb78SCarlos Maiolino static inline struct xfs_mount *
err_to_mp(struct kobject * kobject)437e6b3bb78SCarlos Maiolino err_to_mp(struct kobject *kobject)
438e6b3bb78SCarlos Maiolino {
439e6b3bb78SCarlos Maiolino struct xfs_kobj *kobj = to_kobj(kobject);
440e6b3bb78SCarlos Maiolino return container_of(kobj, struct xfs_mount, m_error_kobj);
441e6b3bb78SCarlos Maiolino }
442e6b3bb78SCarlos Maiolino
443a5ea70d2SCarlos Maiolino static ssize_t
max_retries_show(struct kobject * kobject,char * buf)444a5ea70d2SCarlos Maiolino max_retries_show(
445a5ea70d2SCarlos Maiolino struct kobject *kobject,
446a5ea70d2SCarlos Maiolino char *buf)
447a5ea70d2SCarlos Maiolino {
44877169812SEric Sandeen int retries;
449a5ea70d2SCarlos Maiolino struct xfs_error_cfg *cfg = to_error_cfg(kobject);
450a5ea70d2SCarlos Maiolino
451ff97f239SCarlos Maiolino if (cfg->max_retries == XFS_ERR_RETRY_FOREVER)
45277169812SEric Sandeen retries = -1;
45377169812SEric Sandeen else
45477169812SEric Sandeen retries = cfg->max_retries;
45577169812SEric Sandeen
45653eb47b4SQing Wang return sysfs_emit(buf, "%d\n", retries);
457a5ea70d2SCarlos Maiolino }
458a5ea70d2SCarlos Maiolino
459a5ea70d2SCarlos Maiolino static ssize_t
max_retries_store(struct kobject * kobject,const char * buf,size_t count)460a5ea70d2SCarlos Maiolino max_retries_store(
461a5ea70d2SCarlos Maiolino struct kobject *kobject,
462a5ea70d2SCarlos Maiolino const char *buf,
463a5ea70d2SCarlos Maiolino size_t count)
464a5ea70d2SCarlos Maiolino {
465a5ea70d2SCarlos Maiolino struct xfs_error_cfg *cfg = to_error_cfg(kobject);
466a5ea70d2SCarlos Maiolino int ret;
467a5ea70d2SCarlos Maiolino int val;
468a5ea70d2SCarlos Maiolino
469a5ea70d2SCarlos Maiolino ret = kstrtoint(buf, 0, &val);
470a5ea70d2SCarlos Maiolino if (ret)
471a5ea70d2SCarlos Maiolino return ret;
472a5ea70d2SCarlos Maiolino
473a5ea70d2SCarlos Maiolino if (val < -1)
474a5ea70d2SCarlos Maiolino return -EINVAL;
475a5ea70d2SCarlos Maiolino
47677169812SEric Sandeen if (val == -1)
477ff97f239SCarlos Maiolino cfg->max_retries = XFS_ERR_RETRY_FOREVER;
47877169812SEric Sandeen else
479a5ea70d2SCarlos Maiolino cfg->max_retries = val;
480a5ea70d2SCarlos Maiolino return count;
481a5ea70d2SCarlos Maiolino }
482a5ea70d2SCarlos Maiolino XFS_SYSFS_ATTR_RW(max_retries);
483a5ea70d2SCarlos Maiolino
484a5ea70d2SCarlos Maiolino static ssize_t
retry_timeout_seconds_show(struct kobject * kobject,char * buf)485a5ea70d2SCarlos Maiolino retry_timeout_seconds_show(
486a5ea70d2SCarlos Maiolino struct kobject *kobject,
487a5ea70d2SCarlos Maiolino char *buf)
488a5ea70d2SCarlos Maiolino {
48977169812SEric Sandeen int timeout;
490a5ea70d2SCarlos Maiolino struct xfs_error_cfg *cfg = to_error_cfg(kobject);
491a5ea70d2SCarlos Maiolino
49277169812SEric Sandeen if (cfg->retry_timeout == XFS_ERR_RETRY_FOREVER)
49377169812SEric Sandeen timeout = -1;
49477169812SEric Sandeen else
49577169812SEric Sandeen timeout = jiffies_to_msecs(cfg->retry_timeout) / MSEC_PER_SEC;
49677169812SEric Sandeen
49753eb47b4SQing Wang return sysfs_emit(buf, "%d\n", timeout);
498a5ea70d2SCarlos Maiolino }
499a5ea70d2SCarlos Maiolino
500a5ea70d2SCarlos Maiolino static ssize_t
retry_timeout_seconds_store(struct kobject * kobject,const char * buf,size_t count)501a5ea70d2SCarlos Maiolino retry_timeout_seconds_store(
502a5ea70d2SCarlos Maiolino struct kobject *kobject,
503a5ea70d2SCarlos Maiolino const char *buf,
504a5ea70d2SCarlos Maiolino size_t count)
505a5ea70d2SCarlos Maiolino {
506a5ea70d2SCarlos Maiolino struct xfs_error_cfg *cfg = to_error_cfg(kobject);
507a5ea70d2SCarlos Maiolino int ret;
508a5ea70d2SCarlos Maiolino int val;
509a5ea70d2SCarlos Maiolino
510a5ea70d2SCarlos Maiolino ret = kstrtoint(buf, 0, &val);
511a5ea70d2SCarlos Maiolino if (ret)
512a5ea70d2SCarlos Maiolino return ret;
513a5ea70d2SCarlos Maiolino
51477169812SEric Sandeen /* 1 day timeout maximum, -1 means infinite */
51577169812SEric Sandeen if (val < -1 || val > 86400)
516a5ea70d2SCarlos Maiolino return -EINVAL;
517a5ea70d2SCarlos Maiolino
51877169812SEric Sandeen if (val == -1)
51977169812SEric Sandeen cfg->retry_timeout = XFS_ERR_RETRY_FOREVER;
52077169812SEric Sandeen else {
521a5ea70d2SCarlos Maiolino cfg->retry_timeout = msecs_to_jiffies(val * MSEC_PER_SEC);
52277169812SEric Sandeen ASSERT(msecs_to_jiffies(val * MSEC_PER_SEC) < LONG_MAX);
52377169812SEric Sandeen }
524a5ea70d2SCarlos Maiolino return count;
525a5ea70d2SCarlos Maiolino }
526a5ea70d2SCarlos Maiolino XFS_SYSFS_ATTR_RW(retry_timeout_seconds);
527a5ea70d2SCarlos Maiolino
528e6b3bb78SCarlos Maiolino static ssize_t
fail_at_unmount_show(struct kobject * kobject,char * buf)529e6b3bb78SCarlos Maiolino fail_at_unmount_show(
530e6b3bb78SCarlos Maiolino struct kobject *kobject,
531e6b3bb78SCarlos Maiolino char *buf)
532e6b3bb78SCarlos Maiolino {
533e6b3bb78SCarlos Maiolino struct xfs_mount *mp = err_to_mp(kobject);
534e6b3bb78SCarlos Maiolino
53553eb47b4SQing Wang return sysfs_emit(buf, "%d\n", mp->m_fail_unmount);
536e6b3bb78SCarlos Maiolino }
537e6b3bb78SCarlos Maiolino
538e6b3bb78SCarlos Maiolino static ssize_t
fail_at_unmount_store(struct kobject * kobject,const char * buf,size_t count)539e6b3bb78SCarlos Maiolino fail_at_unmount_store(
540e6b3bb78SCarlos Maiolino struct kobject *kobject,
541e6b3bb78SCarlos Maiolino const char *buf,
542e6b3bb78SCarlos Maiolino size_t count)
543e6b3bb78SCarlos Maiolino {
544e6b3bb78SCarlos Maiolino struct xfs_mount *mp = err_to_mp(kobject);
545e6b3bb78SCarlos Maiolino int ret;
546e6b3bb78SCarlos Maiolino int val;
547e6b3bb78SCarlos Maiolino
548e6b3bb78SCarlos Maiolino ret = kstrtoint(buf, 0, &val);
549e6b3bb78SCarlos Maiolino if (ret)
550e6b3bb78SCarlos Maiolino return ret;
551e6b3bb78SCarlos Maiolino
552e6b3bb78SCarlos Maiolino if (val < 0 || val > 1)
553e6b3bb78SCarlos Maiolino return -EINVAL;
554e6b3bb78SCarlos Maiolino
555e6b3bb78SCarlos Maiolino mp->m_fail_unmount = val;
556e6b3bb78SCarlos Maiolino return count;
557e6b3bb78SCarlos Maiolino }
558e6b3bb78SCarlos Maiolino XFS_SYSFS_ATTR_RW(fail_at_unmount);
559e6b3bb78SCarlos Maiolino
560a5ea70d2SCarlos Maiolino static struct attribute *xfs_error_attrs[] = {
561a5ea70d2SCarlos Maiolino ATTR_LIST(max_retries),
562a5ea70d2SCarlos Maiolino ATTR_LIST(retry_timeout_seconds),
563a5ea70d2SCarlos Maiolino NULL,
564a5ea70d2SCarlos Maiolino };
565219aac5dSGreg Kroah-Hartman ATTRIBUTE_GROUPS(xfs_error);
566a5ea70d2SCarlos Maiolino
567*2ee83335SThomas Weißschuh static const struct kobj_type xfs_error_cfg_ktype = {
568192852beSCarlos Maiolino .release = xfs_sysfs_release,
569192852beSCarlos Maiolino .sysfs_ops = &xfs_sysfs_ops,
570219aac5dSGreg Kroah-Hartman .default_groups = xfs_error_groups,
571192852beSCarlos Maiolino };
572192852beSCarlos Maiolino
573*2ee83335SThomas Weißschuh static const struct kobj_type xfs_error_ktype = {
574192852beSCarlos Maiolino .release = xfs_sysfs_release,
575e6b3bb78SCarlos Maiolino .sysfs_ops = &xfs_sysfs_ops,
576192852beSCarlos Maiolino };
577192852beSCarlos Maiolino
578ef6a50fbSCarlos Maiolino /*
579ef6a50fbSCarlos Maiolino * Error initialization tables. These need to be ordered in the same
580ef6a50fbSCarlos Maiolino * order as the enums used to index the array. All class init tables need to
581ef6a50fbSCarlos Maiolino * define a "default" behaviour as the first entry, all other entries can be
582ef6a50fbSCarlos Maiolino * empty.
583ef6a50fbSCarlos Maiolino */
584ef6a50fbSCarlos Maiolino struct xfs_error_init {
585ef6a50fbSCarlos Maiolino char *name;
586ef6a50fbSCarlos Maiolino int max_retries;
587a5ea70d2SCarlos Maiolino int retry_timeout; /* in seconds */
588ef6a50fbSCarlos Maiolino };
589ef6a50fbSCarlos Maiolino
590ef6a50fbSCarlos Maiolino static const struct xfs_error_init xfs_error_meta_init[XFS_ERR_ERRNO_MAX] = {
591ef6a50fbSCarlos Maiolino { .name = "default",
592e0a431b3SCarlos Maiolino .max_retries = XFS_ERR_RETRY_FOREVER,
59377169812SEric Sandeen .retry_timeout = XFS_ERR_RETRY_FOREVER,
594ef6a50fbSCarlos Maiolino },
595e0a431b3SCarlos Maiolino { .name = "EIO",
596e0a431b3SCarlos Maiolino .max_retries = XFS_ERR_RETRY_FOREVER,
59777169812SEric Sandeen .retry_timeout = XFS_ERR_RETRY_FOREVER,
598e0a431b3SCarlos Maiolino },
599e0a431b3SCarlos Maiolino { .name = "ENOSPC",
600e0a431b3SCarlos Maiolino .max_retries = XFS_ERR_RETRY_FOREVER,
60177169812SEric Sandeen .retry_timeout = XFS_ERR_RETRY_FOREVER,
602e0a431b3SCarlos Maiolino },
603e0a431b3SCarlos Maiolino { .name = "ENODEV",
60477169812SEric Sandeen .max_retries = 0, /* We can't recover from devices disappearing */
60577169812SEric Sandeen .retry_timeout = 0,
606e0a431b3SCarlos Maiolino },
607ef6a50fbSCarlos Maiolino };
608ef6a50fbSCarlos Maiolino
609ef6a50fbSCarlos Maiolino static int
xfs_error_sysfs_init_class(struct xfs_mount * mp,int class,const char * parent_name,struct xfs_kobj * parent_kobj,const struct xfs_error_init init[])610ef6a50fbSCarlos Maiolino xfs_error_sysfs_init_class(
611ef6a50fbSCarlos Maiolino struct xfs_mount *mp,
612ef6a50fbSCarlos Maiolino int class,
613ef6a50fbSCarlos Maiolino const char *parent_name,
614ef6a50fbSCarlos Maiolino struct xfs_kobj *parent_kobj,
615ef6a50fbSCarlos Maiolino const struct xfs_error_init init[])
616ef6a50fbSCarlos Maiolino {
617ef6a50fbSCarlos Maiolino struct xfs_error_cfg *cfg;
618ef6a50fbSCarlos Maiolino int error;
619ef6a50fbSCarlos Maiolino int i;
620ef6a50fbSCarlos Maiolino
621ef6a50fbSCarlos Maiolino ASSERT(class < XFS_ERR_CLASS_MAX);
622ef6a50fbSCarlos Maiolino
623ef6a50fbSCarlos Maiolino error = xfs_sysfs_init(parent_kobj, &xfs_error_ktype,
624ef6a50fbSCarlos Maiolino &mp->m_error_kobj, parent_name);
625ef6a50fbSCarlos Maiolino if (error)
626ef6a50fbSCarlos Maiolino return error;
627ef6a50fbSCarlos Maiolino
628ef6a50fbSCarlos Maiolino for (i = 0; i < XFS_ERR_ERRNO_MAX; i++) {
629ef6a50fbSCarlos Maiolino cfg = &mp->m_error_cfg[class][i];
630ef6a50fbSCarlos Maiolino error = xfs_sysfs_init(&cfg->kobj, &xfs_error_cfg_ktype,
631ef6a50fbSCarlos Maiolino parent_kobj, init[i].name);
632ef6a50fbSCarlos Maiolino if (error)
633ef6a50fbSCarlos Maiolino goto out_error;
634ef6a50fbSCarlos Maiolino
635ef6a50fbSCarlos Maiolino cfg->max_retries = init[i].max_retries;
63677169812SEric Sandeen if (init[i].retry_timeout == XFS_ERR_RETRY_FOREVER)
63777169812SEric Sandeen cfg->retry_timeout = XFS_ERR_RETRY_FOREVER;
63877169812SEric Sandeen else
639a5ea70d2SCarlos Maiolino cfg->retry_timeout = msecs_to_jiffies(
640a5ea70d2SCarlos Maiolino init[i].retry_timeout * MSEC_PER_SEC);
641ef6a50fbSCarlos Maiolino }
642ef6a50fbSCarlos Maiolino return 0;
643ef6a50fbSCarlos Maiolino
644ef6a50fbSCarlos Maiolino out_error:
645ef6a50fbSCarlos Maiolino /* unwind the entries that succeeded */
646ef6a50fbSCarlos Maiolino for (i--; i >= 0; i--) {
647ef6a50fbSCarlos Maiolino cfg = &mp->m_error_cfg[class][i];
648ef6a50fbSCarlos Maiolino xfs_sysfs_del(&cfg->kobj);
649ef6a50fbSCarlos Maiolino }
650ef6a50fbSCarlos Maiolino xfs_sysfs_del(parent_kobj);
651ef6a50fbSCarlos Maiolino return error;
652ef6a50fbSCarlos Maiolino }
653ef6a50fbSCarlos Maiolino
654192852beSCarlos Maiolino int
xfs_error_sysfs_init(struct xfs_mount * mp)655192852beSCarlos Maiolino xfs_error_sysfs_init(
656192852beSCarlos Maiolino struct xfs_mount *mp)
657192852beSCarlos Maiolino {
658192852beSCarlos Maiolino int error;
659192852beSCarlos Maiolino
660192852beSCarlos Maiolino /* .../xfs/<dev>/error/ */
661192852beSCarlos Maiolino error = xfs_sysfs_init(&mp->m_error_kobj, &xfs_error_ktype,
662192852beSCarlos Maiolino &mp->m_kobj, "error");
663ffd40ef6SCarlos Maiolino if (error)
664ffd40ef6SCarlos Maiolino return error;
665ffd40ef6SCarlos Maiolino
666e6b3bb78SCarlos Maiolino error = sysfs_create_file(&mp->m_error_kobj.kobject,
667e6b3bb78SCarlos Maiolino ATTR_LIST(fail_at_unmount));
668e6b3bb78SCarlos Maiolino
669e6b3bb78SCarlos Maiolino if (error)
670e6b3bb78SCarlos Maiolino goto out_error;
671e6b3bb78SCarlos Maiolino
672ffd40ef6SCarlos Maiolino /* .../xfs/<dev>/error/metadata/ */
673ef6a50fbSCarlos Maiolino error = xfs_error_sysfs_init_class(mp, XFS_ERR_METADATA,
674ef6a50fbSCarlos Maiolino "metadata", &mp->m_error_meta_kobj,
675ef6a50fbSCarlos Maiolino xfs_error_meta_init);
676ffd40ef6SCarlos Maiolino if (error)
677ffd40ef6SCarlos Maiolino goto out_error;
678ffd40ef6SCarlos Maiolino
679ffd40ef6SCarlos Maiolino return 0;
680ffd40ef6SCarlos Maiolino
681ffd40ef6SCarlos Maiolino out_error:
682ffd40ef6SCarlos Maiolino xfs_sysfs_del(&mp->m_error_kobj);
683192852beSCarlos Maiolino return error;
684192852beSCarlos Maiolino }
685192852beSCarlos Maiolino
686192852beSCarlos Maiolino void
xfs_error_sysfs_del(struct xfs_mount * mp)687192852beSCarlos Maiolino xfs_error_sysfs_del(
688192852beSCarlos Maiolino struct xfs_mount *mp)
689192852beSCarlos Maiolino {
690ffd40ef6SCarlos Maiolino struct xfs_error_cfg *cfg;
691ffd40ef6SCarlos Maiolino int i, j;
692ffd40ef6SCarlos Maiolino
693ffd40ef6SCarlos Maiolino for (i = 0; i < XFS_ERR_CLASS_MAX; i++) {
694ffd40ef6SCarlos Maiolino for (j = 0; j < XFS_ERR_ERRNO_MAX; j++) {
695ffd40ef6SCarlos Maiolino cfg = &mp->m_error_cfg[i][j];
696ffd40ef6SCarlos Maiolino
697ffd40ef6SCarlos Maiolino xfs_sysfs_del(&cfg->kobj);
698ffd40ef6SCarlos Maiolino }
699ffd40ef6SCarlos Maiolino }
700ffd40ef6SCarlos Maiolino xfs_sysfs_del(&mp->m_error_meta_kobj);
701192852beSCarlos Maiolino xfs_sysfs_del(&mp->m_error_kobj);
702192852beSCarlos Maiolino }
703df309390SCarlos Maiolino
704df309390SCarlos Maiolino struct xfs_error_cfg *
xfs_error_get_cfg(struct xfs_mount * mp,int error_class,int error)705df309390SCarlos Maiolino xfs_error_get_cfg(
706df309390SCarlos Maiolino struct xfs_mount *mp,
707df309390SCarlos Maiolino int error_class,
708df309390SCarlos Maiolino int error)
709df309390SCarlos Maiolino {
710df309390SCarlos Maiolino struct xfs_error_cfg *cfg;
711df309390SCarlos Maiolino
712e97f6c54SEric Sandeen if (error < 0)
713e97f6c54SEric Sandeen error = -error;
714e97f6c54SEric Sandeen
715df309390SCarlos Maiolino switch (error) {
716e0a431b3SCarlos Maiolino case EIO:
717e0a431b3SCarlos Maiolino cfg = &mp->m_error_cfg[error_class][XFS_ERR_EIO];
718e0a431b3SCarlos Maiolino break;
719e0a431b3SCarlos Maiolino case ENOSPC:
720e0a431b3SCarlos Maiolino cfg = &mp->m_error_cfg[error_class][XFS_ERR_ENOSPC];
721e0a431b3SCarlos Maiolino break;
722e0a431b3SCarlos Maiolino case ENODEV:
723e0a431b3SCarlos Maiolino cfg = &mp->m_error_cfg[error_class][XFS_ERR_ENODEV];
724e0a431b3SCarlos Maiolino break;
725df309390SCarlos Maiolino default:
726df309390SCarlos Maiolino cfg = &mp->m_error_cfg[error_class][XFS_ERR_DEFAULT];
727df309390SCarlos Maiolino break;
728df309390SCarlos Maiolino }
729df309390SCarlos Maiolino
730df309390SCarlos Maiolino return cfg;
731df309390SCarlos Maiolino }
732