diff options
author | Darrick J. Wong <darrick.wong@oracle.com> | 2017-06-20 20:54:47 -0400 |
---|---|---|
committer | Darrick J. Wong <darrick.wong@oracle.com> | 2017-06-27 21:23:20 -0400 |
commit | c684010115221978b17968dbddc8e31a09da85e7 (patch) | |
tree | d54d400178c72c7014718a92b511bd6063ffe345 | |
parent | 31965ef34802f49903bba06dd7c3b96a2e2ed4e4 (diff) |
xfs: expose errortag knobs via sysfs
Creates a /sys/fs/xfs/$dev/errortag/ directory to control the errortag
values directly. This enables us to control the randomness values,
rather than having to accept the defaults.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
-rw-r--r-- | fs/xfs/xfs_error.c | 156 | ||||
-rw-r--r-- | fs/xfs/xfs_error.h | 1 | ||||
-rw-r--r-- | fs/xfs/xfs_mount.h | 1 |
3 files changed, 157 insertions, 1 deletions
diff --git a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c index 52f75bc1abac..e2278af6aed1 100644 --- a/fs/xfs/xfs_error.c +++ b/fs/xfs/xfs_error.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include "xfs_trans_resv.h" | 22 | #include "xfs_trans_resv.h" |
23 | #include "xfs_mount.h" | 23 | #include "xfs_mount.h" |
24 | #include "xfs_error.h" | 24 | #include "xfs_error.h" |
25 | #include "xfs_sysfs.h" | ||
25 | 26 | ||
26 | #ifdef DEBUG | 27 | #ifdef DEBUG |
27 | 28 | ||
@@ -56,6 +57,145 @@ static unsigned int xfs_errortag_random_default[] = { | |||
56 | XFS_RANDOM_AG_RESV_CRITICAL, | 57 | XFS_RANDOM_AG_RESV_CRITICAL, |
57 | }; | 58 | }; |
58 | 59 | ||
60 | struct xfs_errortag_attr { | ||
61 | struct attribute attr; | ||
62 | unsigned int tag; | ||
63 | }; | ||
64 | |||
65 | static inline struct xfs_errortag_attr * | ||
66 | to_attr(struct attribute *attr) | ||
67 | { | ||
68 | return container_of(attr, struct xfs_errortag_attr, attr); | ||
69 | } | ||
70 | |||
71 | static inline struct xfs_mount * | ||
72 | to_mp(struct kobject *kobject) | ||
73 | { | ||
74 | struct xfs_kobj *kobj = to_kobj(kobject); | ||
75 | |||
76 | return container_of(kobj, struct xfs_mount, m_errortag_kobj); | ||
77 | } | ||
78 | |||
79 | STATIC ssize_t | ||
80 | xfs_errortag_attr_store( | ||
81 | struct kobject *kobject, | ||
82 | struct attribute *attr, | ||
83 | const char *buf, | ||
84 | size_t count) | ||
85 | { | ||
86 | struct xfs_mount *mp = to_mp(kobject); | ||
87 | struct xfs_errortag_attr *xfs_attr = to_attr(attr); | ||
88 | int ret; | ||
89 | unsigned int val; | ||
90 | |||
91 | if (strcmp(buf, "default") == 0) { | ||
92 | val = xfs_errortag_random_default[xfs_attr->tag]; | ||
93 | } else { | ||
94 | ret = kstrtouint(buf, 0, &val); | ||
95 | if (ret) | ||
96 | return ret; | ||
97 | } | ||
98 | |||
99 | ret = xfs_errortag_set(mp, xfs_attr->tag, val); | ||
100 | if (ret) | ||
101 | return ret; | ||
102 | return count; | ||
103 | } | ||
104 | |||
105 | STATIC ssize_t | ||
106 | xfs_errortag_attr_show( | ||
107 | struct kobject *kobject, | ||
108 | struct attribute *attr, | ||
109 | char *buf) | ||
110 | { | ||
111 | struct xfs_mount *mp = to_mp(kobject); | ||
112 | struct xfs_errortag_attr *xfs_attr = to_attr(attr); | ||
113 | |||
114 | return snprintf(buf, PAGE_SIZE, "%u\n", | ||
115 | xfs_errortag_get(mp, xfs_attr->tag)); | ||
116 | } | ||
117 | |||
118 | static const struct sysfs_ops xfs_errortag_sysfs_ops = { | ||
119 | .show = xfs_errortag_attr_show, | ||
120 | .store = xfs_errortag_attr_store, | ||
121 | }; | ||
122 | |||
123 | #define XFS_ERRORTAG_ATTR_RW(_name, _tag) \ | ||
124 | static struct xfs_errortag_attr xfs_errortag_attr_##_name = { \ | ||
125 | .attr = {.name = __stringify(_name), \ | ||
126 | .mode = VERIFY_OCTAL_PERMISSIONS(S_IWUSR | S_IRUGO) }, \ | ||
127 | .tag = (_tag), \ | ||
128 | } | ||
129 | |||
130 | #define XFS_ERRORTAG_ATTR_LIST(_name) &xfs_errortag_attr_##_name.attr | ||
131 | |||
132 | XFS_ERRORTAG_ATTR_RW(noerror, XFS_ERRTAG_NOERROR); | ||
133 | XFS_ERRORTAG_ATTR_RW(iflush1, XFS_ERRTAG_IFLUSH_1); | ||
134 | XFS_ERRORTAG_ATTR_RW(iflush2, XFS_ERRTAG_IFLUSH_2); | ||
135 | XFS_ERRORTAG_ATTR_RW(iflush3, XFS_ERRTAG_IFLUSH_3); | ||
136 | XFS_ERRORTAG_ATTR_RW(iflush4, XFS_ERRTAG_IFLUSH_4); | ||
137 | XFS_ERRORTAG_ATTR_RW(iflush5, XFS_ERRTAG_IFLUSH_5); | ||
138 | XFS_ERRORTAG_ATTR_RW(iflush6, XFS_ERRTAG_IFLUSH_6); | ||
139 | XFS_ERRORTAG_ATTR_RW(dareadbuf, XFS_ERRTAG_DA_READ_BUF); | ||
140 | XFS_ERRORTAG_ATTR_RW(btree_chk_lblk, XFS_ERRTAG_BTREE_CHECK_LBLOCK); | ||
141 | XFS_ERRORTAG_ATTR_RW(btree_chk_sblk, XFS_ERRTAG_BTREE_CHECK_SBLOCK); | ||
142 | XFS_ERRORTAG_ATTR_RW(readagf, XFS_ERRTAG_ALLOC_READ_AGF); | ||
143 | XFS_ERRORTAG_ATTR_RW(readagi, XFS_ERRTAG_IALLOC_READ_AGI); | ||
144 | XFS_ERRORTAG_ATTR_RW(itobp, XFS_ERRTAG_ITOBP_INOTOBP); | ||
145 | XFS_ERRORTAG_ATTR_RW(iunlink, XFS_ERRTAG_IUNLINK); | ||
146 | XFS_ERRORTAG_ATTR_RW(iunlinkrm, XFS_ERRTAG_IUNLINK_REMOVE); | ||
147 | XFS_ERRORTAG_ATTR_RW(dirinovalid, XFS_ERRTAG_DIR_INO_VALIDATE); | ||
148 | XFS_ERRORTAG_ATTR_RW(bulkstat, XFS_ERRTAG_BULKSTAT_READ_CHUNK); | ||
149 | XFS_ERRORTAG_ATTR_RW(logiodone, XFS_ERRTAG_IODONE_IOERR); | ||
150 | XFS_ERRORTAG_ATTR_RW(stratread, XFS_ERRTAG_STRATREAD_IOERR); | ||
151 | XFS_ERRORTAG_ATTR_RW(stratcmpl, XFS_ERRTAG_STRATCMPL_IOERR); | ||
152 | XFS_ERRORTAG_ATTR_RW(diowrite, XFS_ERRTAG_DIOWRITE_IOERR); | ||
153 | XFS_ERRORTAG_ATTR_RW(bmapifmt, XFS_ERRTAG_BMAPIFORMAT); | ||
154 | XFS_ERRORTAG_ATTR_RW(free_extent, XFS_ERRTAG_FREE_EXTENT); | ||
155 | XFS_ERRORTAG_ATTR_RW(rmap_finish_one, XFS_ERRTAG_RMAP_FINISH_ONE); | ||
156 | XFS_ERRORTAG_ATTR_RW(refcount_continue_update, XFS_ERRTAG_REFCOUNT_CONTINUE_UPDATE); | ||
157 | XFS_ERRORTAG_ATTR_RW(refcount_finish_one, XFS_ERRTAG_REFCOUNT_FINISH_ONE); | ||
158 | XFS_ERRORTAG_ATTR_RW(bmap_finish_one, XFS_ERRTAG_BMAP_FINISH_ONE); | ||
159 | XFS_ERRORTAG_ATTR_RW(ag_resv_critical, XFS_ERRTAG_AG_RESV_CRITICAL); | ||
160 | |||
161 | static struct attribute *xfs_errortag_attrs[] = { | ||
162 | XFS_ERRORTAG_ATTR_LIST(noerror), | ||
163 | XFS_ERRORTAG_ATTR_LIST(iflush1), | ||
164 | XFS_ERRORTAG_ATTR_LIST(iflush2), | ||
165 | XFS_ERRORTAG_ATTR_LIST(iflush3), | ||
166 | XFS_ERRORTAG_ATTR_LIST(iflush4), | ||
167 | XFS_ERRORTAG_ATTR_LIST(iflush5), | ||
168 | XFS_ERRORTAG_ATTR_LIST(iflush6), | ||
169 | XFS_ERRORTAG_ATTR_LIST(dareadbuf), | ||
170 | XFS_ERRORTAG_ATTR_LIST(btree_chk_lblk), | ||
171 | XFS_ERRORTAG_ATTR_LIST(btree_chk_sblk), | ||
172 | XFS_ERRORTAG_ATTR_LIST(readagf), | ||
173 | XFS_ERRORTAG_ATTR_LIST(readagi), | ||
174 | XFS_ERRORTAG_ATTR_LIST(itobp), | ||
175 | XFS_ERRORTAG_ATTR_LIST(iunlink), | ||
176 | XFS_ERRORTAG_ATTR_LIST(iunlinkrm), | ||
177 | XFS_ERRORTAG_ATTR_LIST(dirinovalid), | ||
178 | XFS_ERRORTAG_ATTR_LIST(bulkstat), | ||
179 | XFS_ERRORTAG_ATTR_LIST(logiodone), | ||
180 | XFS_ERRORTAG_ATTR_LIST(stratread), | ||
181 | XFS_ERRORTAG_ATTR_LIST(stratcmpl), | ||
182 | XFS_ERRORTAG_ATTR_LIST(diowrite), | ||
183 | XFS_ERRORTAG_ATTR_LIST(bmapifmt), | ||
184 | XFS_ERRORTAG_ATTR_LIST(free_extent), | ||
185 | XFS_ERRORTAG_ATTR_LIST(rmap_finish_one), | ||
186 | XFS_ERRORTAG_ATTR_LIST(refcount_continue_update), | ||
187 | XFS_ERRORTAG_ATTR_LIST(refcount_finish_one), | ||
188 | XFS_ERRORTAG_ATTR_LIST(bmap_finish_one), | ||
189 | XFS_ERRORTAG_ATTR_LIST(ag_resv_critical), | ||
190 | NULL, | ||
191 | }; | ||
192 | |||
193 | struct kobj_type xfs_errortag_ktype = { | ||
194 | .release = xfs_sysfs_release, | ||
195 | .sysfs_ops = &xfs_errortag_sysfs_ops, | ||
196 | .default_attrs = xfs_errortag_attrs, | ||
197 | }; | ||
198 | |||
59 | int | 199 | int |
60 | xfs_errortag_init( | 200 | xfs_errortag_init( |
61 | struct xfs_mount *mp) | 201 | struct xfs_mount *mp) |
@@ -64,13 +204,16 @@ xfs_errortag_init( | |||
64 | KM_SLEEP | KM_MAYFAIL); | 204 | KM_SLEEP | KM_MAYFAIL); |
65 | if (!mp->m_errortag) | 205 | if (!mp->m_errortag) |
66 | return -ENOMEM; | 206 | return -ENOMEM; |
67 | return 0; | 207 | |
208 | return xfs_sysfs_init(&mp->m_errortag_kobj, &xfs_errortag_ktype, | ||
209 | &mp->m_kobj, "errortag"); | ||
68 | } | 210 | } |
69 | 211 | ||
70 | void | 212 | void |
71 | xfs_errortag_del( | 213 | xfs_errortag_del( |
72 | struct xfs_mount *mp) | 214 | struct xfs_mount *mp) |
73 | { | 215 | { |
216 | xfs_sysfs_del(&mp->m_errortag_kobj); | ||
74 | kmem_free(mp->m_errortag); | 217 | kmem_free(mp->m_errortag); |
75 | } | 218 | } |
76 | 219 | ||
@@ -96,6 +239,17 @@ xfs_errortag_test( | |||
96 | } | 239 | } |
97 | 240 | ||
98 | int | 241 | int |
242 | xfs_errortag_get( | ||
243 | struct xfs_mount *mp, | ||
244 | unsigned int error_tag) | ||
245 | { | ||
246 | if (error_tag >= XFS_ERRTAG_MAX) | ||
247 | return -EINVAL; | ||
248 | |||
249 | return mp->m_errortag[error_tag]; | ||
250 | } | ||
251 | |||
252 | int | ||
99 | xfs_errortag_set( | 253 | xfs_errortag_set( |
100 | struct xfs_mount *mp, | 254 | struct xfs_mount *mp, |
101 | unsigned int error_tag, | 255 | unsigned int error_tag, |
diff --git a/fs/xfs/xfs_error.h b/fs/xfs/xfs_error.h index b4316d39e1ca..8915bdeb6128 100644 --- a/fs/xfs/xfs_error.h +++ b/fs/xfs/xfs_error.h | |||
@@ -138,6 +138,7 @@ extern bool xfs_errortag_test(struct xfs_mount *mp, const char *expression, | |||
138 | #define XFS_TEST_ERROR(expr, mp, tag, rf) \ | 138 | #define XFS_TEST_ERROR(expr, mp, tag, rf) \ |
139 | ((expr) || xfs_errortag_test((mp), #expr, __FILE__, __LINE__, (tag))) | 139 | ((expr) || xfs_errortag_test((mp), #expr, __FILE__, __LINE__, (tag))) |
140 | 140 | ||
141 | extern int xfs_errortag_get(struct xfs_mount *mp, unsigned int error_tag); | ||
141 | extern int xfs_errortag_set(struct xfs_mount *mp, unsigned int error_tag, | 142 | extern int xfs_errortag_set(struct xfs_mount *mp, unsigned int error_tag, |
142 | unsigned int tag_value); | 143 | unsigned int tag_value); |
143 | extern int xfs_errortag_add(struct xfs_mount *mp, unsigned int error_tag); | 144 | extern int xfs_errortag_add(struct xfs_mount *mp, unsigned int error_tag); |
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index e002ac52a4e6..931e9fc21a1c 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h | |||
@@ -204,6 +204,7 @@ typedef struct xfs_mount { | |||
204 | * error triggers. 1 = always, 2 = half the time, etc. | 204 | * error triggers. 1 = always, 2 = half the time, etc. |
205 | */ | 205 | */ |
206 | unsigned int *m_errortag; | 206 | unsigned int *m_errortag; |
207 | struct xfs_kobj m_errortag_kobj; | ||
207 | 208 | ||
208 | /* | 209 | /* |
209 | * DEBUG mode instrumentation to test and/or trigger delayed allocation | 210 | * DEBUG mode instrumentation to test and/or trigger delayed allocation |