2 * Copyright (c) 2014 Red Hat, Inc.
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.
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.
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
20 #include "xfs_shared.h"
21 #include "xfs_format.h"
22 #include "xfs_log_format.h"
23 #include "xfs_trans_resv.h"
24 #include "xfs_sysfs.h"
26 #include "xfs_log_priv.h"
27 #include "xfs_stats.h"
28 #include "xfs_mount.h"
30 struct xfs_sysfs_attr
{
31 struct attribute attr
;
32 ssize_t (*show
)(struct kobject
*kobject
, char *buf
);
33 ssize_t (*store
)(struct kobject
*kobject
, const char *buf
,
37 static inline struct xfs_sysfs_attr
*
38 to_attr(struct attribute
*attr
)
40 return container_of(attr
, struct xfs_sysfs_attr
, attr
);
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)
47 #define XFS_SYSFS_ATTR_WO(name) \
48 static struct xfs_sysfs_attr xfs_sysfs_attr_##name = __ATTR_WO(name)
50 #define ATTR_LIST(name) &xfs_sysfs_attr_##name.attr
53 xfs_sysfs_object_show(
54 struct kobject
*kobject
,
55 struct attribute
*attr
,
58 struct xfs_sysfs_attr
*xfs_attr
= to_attr(attr
);
60 return xfs_attr
->show
? xfs_attr
->show(kobject
, buf
) : 0;
64 xfs_sysfs_object_store(
65 struct kobject
*kobject
,
66 struct attribute
*attr
,
70 struct xfs_sysfs_attr
*xfs_attr
= to_attr(attr
);
72 return xfs_attr
->store
? xfs_attr
->store(kobject
, buf
, count
) : 0;
75 static const struct sysfs_ops xfs_sysfs_ops
= {
76 .show
= xfs_sysfs_object_show
,
77 .store
= xfs_sysfs_object_store
,
81 * xfs_mount kobject. The mp kobject also serves as the per-mount parent object
82 * that is identified by the fsname under sysfs.
85 static inline struct xfs_mount
*
86 to_mp(struct kobject
*kobject
)
88 struct xfs_kobj
*kobj
= to_kobj(kobject
);
90 return container_of(kobj
, struct xfs_mount
, m_kobj
);
93 static struct attribute
*xfs_mp_attrs
[] = {
97 struct kobj_type xfs_mp_ktype
= {
98 .release
= xfs_sysfs_release
,
99 .sysfs_ops
= &xfs_sysfs_ops
,
100 .default_attrs
= xfs_mp_attrs
,
108 struct kobject
*kobject
,
115 ret
= kstrtoint(buf
, 0, &val
);
120 xfs_globals
.bug_on_assert
= true;
122 xfs_globals
.bug_on_assert
= false;
131 struct kobject
*kobject
,
134 return snprintf(buf
, PAGE_SIZE
, "%d\n", xfs_globals
.bug_on_assert
? 1 : 0);
136 XFS_SYSFS_ATTR_RW(bug_on_assert
);
139 log_recovery_delay_store(
140 struct kobject
*kobject
,
147 ret
= kstrtoint(buf
, 0, &val
);
151 if (val
< 0 || val
> 60)
154 xfs_globals
.log_recovery_delay
= val
;
160 log_recovery_delay_show(
161 struct kobject
*kobject
,
164 return snprintf(buf
, PAGE_SIZE
, "%d\n", xfs_globals
.log_recovery_delay
);
166 XFS_SYSFS_ATTR_RW(log_recovery_delay
);
168 static struct attribute
*xfs_dbg_attrs
[] = {
169 ATTR_LIST(bug_on_assert
),
170 ATTR_LIST(log_recovery_delay
),
174 struct kobj_type xfs_dbg_ktype
= {
175 .release
= xfs_sysfs_release
,
176 .sysfs_ops
= &xfs_sysfs_ops
,
177 .default_attrs
= xfs_dbg_attrs
,
184 static inline struct xstats
*
185 to_xstats(struct kobject
*kobject
)
187 struct xfs_kobj
*kobj
= to_kobj(kobject
);
189 return container_of(kobj
, struct xstats
, xs_kobj
);
194 struct kobject
*kobject
,
197 struct xstats
*stats
= to_xstats(kobject
);
199 return xfs_stats_format(stats
->xs_stats
, buf
);
201 XFS_SYSFS_ATTR_RO(stats
);
205 struct kobject
*kobject
,
211 struct xstats
*stats
= to_xstats(kobject
);
213 ret
= kstrtoint(buf
, 0, &val
);
220 xfs_stats_clearall(stats
->xs_stats
);
223 XFS_SYSFS_ATTR_WO(stats_clear
);
225 static struct attribute
*xfs_stats_attrs
[] = {
227 ATTR_LIST(stats_clear
),
231 struct kobj_type xfs_stats_ktype
= {
232 .release
= xfs_sysfs_release
,
233 .sysfs_ops
= &xfs_sysfs_ops
,
234 .default_attrs
= xfs_stats_attrs
,
239 static inline struct xlog
*
240 to_xlog(struct kobject
*kobject
)
242 struct xfs_kobj
*kobj
= to_kobj(kobject
);
244 return container_of(kobj
, struct xlog
, l_kobj
);
249 struct kobject
*kobject
,
254 struct xlog
*log
= to_xlog(kobject
);
256 spin_lock(&log
->l_icloglock
);
257 cycle
= log
->l_curr_cycle
;
258 block
= log
->l_curr_block
;
259 spin_unlock(&log
->l_icloglock
);
261 return snprintf(buf
, PAGE_SIZE
, "%d:%d\n", cycle
, block
);
263 XFS_SYSFS_ATTR_RO(log_head_lsn
);
267 struct kobject
*kobject
,
272 struct xlog
*log
= to_xlog(kobject
);
274 xlog_crack_atomic_lsn(&log
->l_tail_lsn
, &cycle
, &block
);
275 return snprintf(buf
, PAGE_SIZE
, "%d:%d\n", cycle
, block
);
277 XFS_SYSFS_ATTR_RO(log_tail_lsn
);
280 reserve_grant_head_show(
281 struct kobject
*kobject
,
287 struct xlog
*log
= to_xlog(kobject
);
289 xlog_crack_grant_head(&log
->l_reserve_head
.grant
, &cycle
, &bytes
);
290 return snprintf(buf
, PAGE_SIZE
, "%d:%d\n", cycle
, bytes
);
292 XFS_SYSFS_ATTR_RO(reserve_grant_head
);
295 write_grant_head_show(
296 struct kobject
*kobject
,
301 struct xlog
*log
= to_xlog(kobject
);
303 xlog_crack_grant_head(&log
->l_write_head
.grant
, &cycle
, &bytes
);
304 return snprintf(buf
, PAGE_SIZE
, "%d:%d\n", cycle
, bytes
);
306 XFS_SYSFS_ATTR_RO(write_grant_head
);
308 static struct attribute
*xfs_log_attrs
[] = {
309 ATTR_LIST(log_head_lsn
),
310 ATTR_LIST(log_tail_lsn
),
311 ATTR_LIST(reserve_grant_head
),
312 ATTR_LIST(write_grant_head
),
316 struct kobj_type xfs_log_ktype
= {
317 .release
= xfs_sysfs_release
,
318 .sysfs_ops
= &xfs_sysfs_ops
,
319 .default_attrs
= xfs_log_attrs
,
323 * Metadata IO error configuration
325 * The sysfs structure here is:
326 * ...xfs/<dev>/error/<class>/<errno>/<error_attrs>
328 * where <class> allows us to discriminate between data IO and metadata IO,
329 * and any other future type of IO (e.g. special inode or directory error
330 * handling) we care to support.
332 static inline struct xfs_error_cfg
*
333 to_error_cfg(struct kobject
*kobject
)
335 struct xfs_kobj
*kobj
= to_kobj(kobject
);
336 return container_of(kobj
, struct xfs_error_cfg
, kobj
);
339 static inline struct xfs_mount
*
340 err_to_mp(struct kobject
*kobject
)
342 struct xfs_kobj
*kobj
= to_kobj(kobject
);
343 return container_of(kobj
, struct xfs_mount
, m_error_kobj
);
348 struct kobject
*kobject
,
352 struct xfs_error_cfg
*cfg
= to_error_cfg(kobject
);
354 if (cfg
->max_retries
== XFS_ERR_RETRY_FOREVER
)
357 retries
= cfg
->max_retries
;
359 return snprintf(buf
, PAGE_SIZE
, "%d\n", retries
);
364 struct kobject
*kobject
,
368 struct xfs_error_cfg
*cfg
= to_error_cfg(kobject
);
372 ret
= kstrtoint(buf
, 0, &val
);
380 cfg
->max_retries
= XFS_ERR_RETRY_FOREVER
;
382 cfg
->max_retries
= val
;
385 XFS_SYSFS_ATTR_RW(max_retries
);
388 retry_timeout_seconds_show(
389 struct kobject
*kobject
,
393 struct xfs_error_cfg
*cfg
= to_error_cfg(kobject
);
395 if (cfg
->retry_timeout
== XFS_ERR_RETRY_FOREVER
)
398 timeout
= jiffies_to_msecs(cfg
->retry_timeout
) / MSEC_PER_SEC
;
400 return snprintf(buf
, PAGE_SIZE
, "%d\n", timeout
);
404 retry_timeout_seconds_store(
405 struct kobject
*kobject
,
409 struct xfs_error_cfg
*cfg
= to_error_cfg(kobject
);
413 ret
= kstrtoint(buf
, 0, &val
);
417 /* 1 day timeout maximum, -1 means infinite */
418 if (val
< -1 || val
> 86400)
422 cfg
->retry_timeout
= XFS_ERR_RETRY_FOREVER
;
424 cfg
->retry_timeout
= msecs_to_jiffies(val
* MSEC_PER_SEC
);
425 ASSERT(msecs_to_jiffies(val
* MSEC_PER_SEC
) < LONG_MAX
);
429 XFS_SYSFS_ATTR_RW(retry_timeout_seconds
);
432 fail_at_unmount_show(
433 struct kobject
*kobject
,
436 struct xfs_mount
*mp
= err_to_mp(kobject
);
438 return snprintf(buf
, PAGE_SIZE
, "%d\n", mp
->m_fail_unmount
);
442 fail_at_unmount_store(
443 struct kobject
*kobject
,
447 struct xfs_mount
*mp
= err_to_mp(kobject
);
451 ret
= kstrtoint(buf
, 0, &val
);
455 if (val
< 0 || val
> 1)
458 mp
->m_fail_unmount
= val
;
461 XFS_SYSFS_ATTR_RW(fail_at_unmount
);
463 static struct attribute
*xfs_error_attrs
[] = {
464 ATTR_LIST(max_retries
),
465 ATTR_LIST(retry_timeout_seconds
),
470 static struct kobj_type xfs_error_cfg_ktype
= {
471 .release
= xfs_sysfs_release
,
472 .sysfs_ops
= &xfs_sysfs_ops
,
473 .default_attrs
= xfs_error_attrs
,
476 static struct kobj_type xfs_error_ktype
= {
477 .release
= xfs_sysfs_release
,
478 .sysfs_ops
= &xfs_sysfs_ops
,
482 * Error initialization tables. These need to be ordered in the same
483 * order as the enums used to index the array. All class init tables need to
484 * define a "default" behaviour as the first entry, all other entries can be
487 struct xfs_error_init
{
490 int retry_timeout
; /* in seconds */
493 static const struct xfs_error_init xfs_error_meta_init
[XFS_ERR_ERRNO_MAX
] = {
495 .max_retries
= XFS_ERR_RETRY_FOREVER
,
496 .retry_timeout
= XFS_ERR_RETRY_FOREVER
,
499 .max_retries
= XFS_ERR_RETRY_FOREVER
,
500 .retry_timeout
= XFS_ERR_RETRY_FOREVER
,
503 .max_retries
= XFS_ERR_RETRY_FOREVER
,
504 .retry_timeout
= XFS_ERR_RETRY_FOREVER
,
507 .max_retries
= 0, /* We can't recover from devices disappearing */
513 xfs_error_sysfs_init_class(
514 struct xfs_mount
*mp
,
516 const char *parent_name
,
517 struct xfs_kobj
*parent_kobj
,
518 const struct xfs_error_init init
[])
520 struct xfs_error_cfg
*cfg
;
524 ASSERT(class < XFS_ERR_CLASS_MAX
);
526 error
= xfs_sysfs_init(parent_kobj
, &xfs_error_ktype
,
527 &mp
->m_error_kobj
, parent_name
);
531 for (i
= 0; i
< XFS_ERR_ERRNO_MAX
; i
++) {
532 cfg
= &mp
->m_error_cfg
[class][i
];
533 error
= xfs_sysfs_init(&cfg
->kobj
, &xfs_error_cfg_ktype
,
534 parent_kobj
, init
[i
].name
);
538 cfg
->max_retries
= init
[i
].max_retries
;
539 if (init
[i
].retry_timeout
== XFS_ERR_RETRY_FOREVER
)
540 cfg
->retry_timeout
= XFS_ERR_RETRY_FOREVER
;
542 cfg
->retry_timeout
= msecs_to_jiffies(
543 init
[i
].retry_timeout
* MSEC_PER_SEC
);
548 /* unwind the entries that succeeded */
549 for (i
--; i
>= 0; i
--) {
550 cfg
= &mp
->m_error_cfg
[class][i
];
551 xfs_sysfs_del(&cfg
->kobj
);
553 xfs_sysfs_del(parent_kobj
);
558 xfs_error_sysfs_init(
559 struct xfs_mount
*mp
)
563 /* .../xfs/<dev>/error/ */
564 error
= xfs_sysfs_init(&mp
->m_error_kobj
, &xfs_error_ktype
,
565 &mp
->m_kobj
, "error");
569 error
= sysfs_create_file(&mp
->m_error_kobj
.kobject
,
570 ATTR_LIST(fail_at_unmount
));
575 /* .../xfs/<dev>/error/metadata/ */
576 error
= xfs_error_sysfs_init_class(mp
, XFS_ERR_METADATA
,
577 "metadata", &mp
->m_error_meta_kobj
,
578 xfs_error_meta_init
);
585 xfs_sysfs_del(&mp
->m_error_kobj
);
591 struct xfs_mount
*mp
)
593 struct xfs_error_cfg
*cfg
;
596 for (i
= 0; i
< XFS_ERR_CLASS_MAX
; i
++) {
597 for (j
= 0; j
< XFS_ERR_ERRNO_MAX
; j
++) {
598 cfg
= &mp
->m_error_cfg
[i
][j
];
600 xfs_sysfs_del(&cfg
->kobj
);
603 xfs_sysfs_del(&mp
->m_error_meta_kobj
);
604 xfs_sysfs_del(&mp
->m_error_kobj
);
607 struct xfs_error_cfg
*
609 struct xfs_mount
*mp
,
613 struct xfs_error_cfg
*cfg
;
620 cfg
= &mp
->m_error_cfg
[error_class
][XFS_ERR_EIO
];
623 cfg
= &mp
->m_error_cfg
[error_class
][XFS_ERR_ENOSPC
];
626 cfg
= &mp
->m_error_cfg
[error_class
][XFS_ERR_ENODEV
];
629 cfg
= &mp
->m_error_cfg
[error_class
][XFS_ERR_DEFAULT
];