]> asedeno.scripts.mit.edu Git - linux.git/blob - fs/xfs/xfs_sysfs.c
Merge branch 'x86-boot-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux.git] / fs / xfs / xfs_sysfs.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2014 Red Hat, Inc.
4  * All Rights Reserved.
5  */
6
7 #include "xfs.h"
8 #include "xfs_shared.h"
9 #include "xfs_format.h"
10 #include "xfs_log_format.h"
11 #include "xfs_trans_resv.h"
12 #include "xfs_sysfs.h"
13 #include "xfs_log.h"
14 #include "xfs_log_priv.h"
15 #include "xfs_stats.h"
16 #include "xfs_mount.h"
17
18 struct xfs_sysfs_attr {
19         struct attribute attr;
20         ssize_t (*show)(struct kobject *kobject, char *buf);
21         ssize_t (*store)(struct kobject *kobject, const char *buf,
22                          size_t count);
23 };
24
25 static inline struct xfs_sysfs_attr *
26 to_attr(struct attribute *attr)
27 {
28         return container_of(attr, struct xfs_sysfs_attr, attr);
29 }
30
31 #define XFS_SYSFS_ATTR_RW(name) \
32         static struct xfs_sysfs_attr xfs_sysfs_attr_##name = __ATTR_RW(name)
33 #define XFS_SYSFS_ATTR_RO(name) \
34         static struct xfs_sysfs_attr xfs_sysfs_attr_##name = __ATTR_RO(name)
35 #define XFS_SYSFS_ATTR_WO(name) \
36         static struct xfs_sysfs_attr xfs_sysfs_attr_##name = __ATTR_WO(name)
37
38 #define ATTR_LIST(name) &xfs_sysfs_attr_##name.attr
39
40 STATIC ssize_t
41 xfs_sysfs_object_show(
42         struct kobject          *kobject,
43         struct attribute        *attr,
44         char                    *buf)
45 {
46         struct xfs_sysfs_attr *xfs_attr = to_attr(attr);
47
48         return xfs_attr->show ? xfs_attr->show(kobject, buf) : 0;
49 }
50
51 STATIC ssize_t
52 xfs_sysfs_object_store(
53         struct kobject          *kobject,
54         struct attribute        *attr,
55         const char              *buf,
56         size_t                  count)
57 {
58         struct xfs_sysfs_attr *xfs_attr = to_attr(attr);
59
60         return xfs_attr->store ? xfs_attr->store(kobject, buf, count) : 0;
61 }
62
63 static const struct sysfs_ops xfs_sysfs_ops = {
64         .show = xfs_sysfs_object_show,
65         .store = xfs_sysfs_object_store,
66 };
67
68 /*
69  * xfs_mount kobject. The mp kobject also serves as the per-mount parent object
70  * that is identified by the fsname under sysfs.
71  */
72
73 static inline struct xfs_mount *
74 to_mp(struct kobject *kobject)
75 {
76         struct xfs_kobj *kobj = to_kobj(kobject);
77
78         return container_of(kobj, struct xfs_mount, m_kobj);
79 }
80
81 static struct attribute *xfs_mp_attrs[] = {
82         NULL,
83 };
84
85 struct kobj_type xfs_mp_ktype = {
86         .release = xfs_sysfs_release,
87         .sysfs_ops = &xfs_sysfs_ops,
88         .default_attrs = xfs_mp_attrs,
89 };
90
91 #ifdef DEBUG
92 /* debug */
93
94 STATIC ssize_t
95 bug_on_assert_store(
96         struct kobject          *kobject,
97         const char              *buf,
98         size_t                  count)
99 {
100         int                     ret;
101         int                     val;
102
103         ret = kstrtoint(buf, 0, &val);
104         if (ret)
105                 return ret;
106
107         if (val == 1)
108                 xfs_globals.bug_on_assert = true;
109         else if (val == 0)
110                 xfs_globals.bug_on_assert = false;
111         else
112                 return -EINVAL;
113
114         return count;
115 }
116
117 STATIC ssize_t
118 bug_on_assert_show(
119         struct kobject          *kobject,
120         char                    *buf)
121 {
122         return snprintf(buf, PAGE_SIZE, "%d\n", xfs_globals.bug_on_assert ? 1 : 0);
123 }
124 XFS_SYSFS_ATTR_RW(bug_on_assert);
125
126 STATIC ssize_t
127 log_recovery_delay_store(
128         struct kobject  *kobject,
129         const char      *buf,
130         size_t          count)
131 {
132         int             ret;
133         int             val;
134
135         ret = kstrtoint(buf, 0, &val);
136         if (ret)
137                 return ret;
138
139         if (val < 0 || val > 60)
140                 return -EINVAL;
141
142         xfs_globals.log_recovery_delay = val;
143
144         return count;
145 }
146
147 STATIC ssize_t
148 log_recovery_delay_show(
149         struct kobject  *kobject,
150         char            *buf)
151 {
152         return snprintf(buf, PAGE_SIZE, "%d\n", xfs_globals.log_recovery_delay);
153 }
154 XFS_SYSFS_ATTR_RW(log_recovery_delay);
155
156 STATIC ssize_t
157 mount_delay_store(
158         struct kobject  *kobject,
159         const char      *buf,
160         size_t          count)
161 {
162         int             ret;
163         int             val;
164
165         ret = kstrtoint(buf, 0, &val);
166         if (ret)
167                 return ret;
168
169         if (val < 0 || val > 60)
170                 return -EINVAL;
171
172         xfs_globals.mount_delay = val;
173
174         return count;
175 }
176
177 STATIC ssize_t
178 mount_delay_show(
179         struct kobject  *kobject,
180         char            *buf)
181 {
182         return snprintf(buf, PAGE_SIZE, "%d\n", xfs_globals.mount_delay);
183 }
184 XFS_SYSFS_ATTR_RW(mount_delay);
185
186 static ssize_t
187 always_cow_store(
188         struct kobject  *kobject,
189         const char      *buf,
190         size_t          count)
191 {
192         ssize_t         ret;
193
194         ret = kstrtobool(buf, &xfs_globals.always_cow);
195         if (ret < 0)
196                 return ret;
197         return count;
198 }
199
200 static ssize_t
201 always_cow_show(
202         struct kobject  *kobject,
203         char            *buf)
204 {
205         return snprintf(buf, PAGE_SIZE, "%d\n", xfs_globals.always_cow);
206 }
207 XFS_SYSFS_ATTR_RW(always_cow);
208
209 static struct attribute *xfs_dbg_attrs[] = {
210         ATTR_LIST(bug_on_assert),
211         ATTR_LIST(log_recovery_delay),
212         ATTR_LIST(mount_delay),
213         ATTR_LIST(always_cow),
214         NULL,
215 };
216
217 struct kobj_type xfs_dbg_ktype = {
218         .release = xfs_sysfs_release,
219         .sysfs_ops = &xfs_sysfs_ops,
220         .default_attrs = xfs_dbg_attrs,
221 };
222
223 #endif /* DEBUG */
224
225 /* stats */
226
227 static inline struct xstats *
228 to_xstats(struct kobject *kobject)
229 {
230         struct xfs_kobj *kobj = to_kobj(kobject);
231
232         return container_of(kobj, struct xstats, xs_kobj);
233 }
234
235 STATIC ssize_t
236 stats_show(
237         struct kobject  *kobject,
238         char            *buf)
239 {
240         struct xstats   *stats = to_xstats(kobject);
241
242         return xfs_stats_format(stats->xs_stats, buf);
243 }
244 XFS_SYSFS_ATTR_RO(stats);
245
246 STATIC ssize_t
247 stats_clear_store(
248         struct kobject  *kobject,
249         const char      *buf,
250         size_t          count)
251 {
252         int             ret;
253         int             val;
254         struct xstats   *stats = to_xstats(kobject);
255
256         ret = kstrtoint(buf, 0, &val);
257         if (ret)
258                 return ret;
259
260         if (val != 1)
261                 return -EINVAL;
262
263         xfs_stats_clearall(stats->xs_stats);
264         return count;
265 }
266 XFS_SYSFS_ATTR_WO(stats_clear);
267
268 static struct attribute *xfs_stats_attrs[] = {
269         ATTR_LIST(stats),
270         ATTR_LIST(stats_clear),
271         NULL,
272 };
273
274 struct kobj_type xfs_stats_ktype = {
275         .release = xfs_sysfs_release,
276         .sysfs_ops = &xfs_sysfs_ops,
277         .default_attrs = xfs_stats_attrs,
278 };
279
280 /* xlog */
281
282 static inline struct xlog *
283 to_xlog(struct kobject *kobject)
284 {
285         struct xfs_kobj *kobj = to_kobj(kobject);
286
287         return container_of(kobj, struct xlog, l_kobj);
288 }
289
290 STATIC ssize_t
291 log_head_lsn_show(
292         struct kobject  *kobject,
293         char            *buf)
294 {
295         int cycle;
296         int block;
297         struct xlog *log = to_xlog(kobject);
298
299         spin_lock(&log->l_icloglock);
300         cycle = log->l_curr_cycle;
301         block = log->l_curr_block;
302         spin_unlock(&log->l_icloglock);
303
304         return snprintf(buf, PAGE_SIZE, "%d:%d\n", cycle, block);
305 }
306 XFS_SYSFS_ATTR_RO(log_head_lsn);
307
308 STATIC ssize_t
309 log_tail_lsn_show(
310         struct kobject  *kobject,
311         char            *buf)
312 {
313         int cycle;
314         int block;
315         struct xlog *log = to_xlog(kobject);
316
317         xlog_crack_atomic_lsn(&log->l_tail_lsn, &cycle, &block);
318         return snprintf(buf, PAGE_SIZE, "%d:%d\n", cycle, block);
319 }
320 XFS_SYSFS_ATTR_RO(log_tail_lsn);
321
322 STATIC ssize_t
323 reserve_grant_head_show(
324         struct kobject  *kobject,
325         char            *buf)
326
327 {
328         int cycle;
329         int bytes;
330         struct xlog *log = to_xlog(kobject);
331
332         xlog_crack_grant_head(&log->l_reserve_head.grant, &cycle, &bytes);
333         return snprintf(buf, PAGE_SIZE, "%d:%d\n", cycle, bytes);
334 }
335 XFS_SYSFS_ATTR_RO(reserve_grant_head);
336
337 STATIC ssize_t
338 write_grant_head_show(
339         struct kobject  *kobject,
340         char            *buf)
341 {
342         int cycle;
343         int bytes;
344         struct xlog *log = to_xlog(kobject);
345
346         xlog_crack_grant_head(&log->l_write_head.grant, &cycle, &bytes);
347         return snprintf(buf, PAGE_SIZE, "%d:%d\n", cycle, bytes);
348 }
349 XFS_SYSFS_ATTR_RO(write_grant_head);
350
351 static struct attribute *xfs_log_attrs[] = {
352         ATTR_LIST(log_head_lsn),
353         ATTR_LIST(log_tail_lsn),
354         ATTR_LIST(reserve_grant_head),
355         ATTR_LIST(write_grant_head),
356         NULL,
357 };
358
359 struct kobj_type xfs_log_ktype = {
360         .release = xfs_sysfs_release,
361         .sysfs_ops = &xfs_sysfs_ops,
362         .default_attrs = xfs_log_attrs,
363 };
364
365 /*
366  * Metadata IO error configuration
367  *
368  * The sysfs structure here is:
369  *      ...xfs/<dev>/error/<class>/<errno>/<error_attrs>
370  *
371  * where <class> allows us to discriminate between data IO and metadata IO,
372  * and any other future type of IO (e.g. special inode or directory error
373  * handling) we care to support.
374  */
375 static inline struct xfs_error_cfg *
376 to_error_cfg(struct kobject *kobject)
377 {
378         struct xfs_kobj *kobj = to_kobj(kobject);
379         return container_of(kobj, struct xfs_error_cfg, kobj);
380 }
381
382 static inline struct xfs_mount *
383 err_to_mp(struct kobject *kobject)
384 {
385         struct xfs_kobj *kobj = to_kobj(kobject);
386         return container_of(kobj, struct xfs_mount, m_error_kobj);
387 }
388
389 static ssize_t
390 max_retries_show(
391         struct kobject  *kobject,
392         char            *buf)
393 {
394         int             retries;
395         struct xfs_error_cfg *cfg = to_error_cfg(kobject);
396
397         if (cfg->max_retries == XFS_ERR_RETRY_FOREVER)
398                 retries = -1;
399         else
400                 retries = cfg->max_retries;
401
402         return snprintf(buf, PAGE_SIZE, "%d\n", retries);
403 }
404
405 static ssize_t
406 max_retries_store(
407         struct kobject  *kobject,
408         const char      *buf,
409         size_t          count)
410 {
411         struct xfs_error_cfg *cfg = to_error_cfg(kobject);
412         int             ret;
413         int             val;
414
415         ret = kstrtoint(buf, 0, &val);
416         if (ret)
417                 return ret;
418
419         if (val < -1)
420                 return -EINVAL;
421
422         if (val == -1)
423                 cfg->max_retries = XFS_ERR_RETRY_FOREVER;
424         else
425                 cfg->max_retries = val;
426         return count;
427 }
428 XFS_SYSFS_ATTR_RW(max_retries);
429
430 static ssize_t
431 retry_timeout_seconds_show(
432         struct kobject  *kobject,
433         char            *buf)
434 {
435         int             timeout;
436         struct xfs_error_cfg *cfg = to_error_cfg(kobject);
437
438         if (cfg->retry_timeout == XFS_ERR_RETRY_FOREVER)
439                 timeout = -1;
440         else
441                 timeout = jiffies_to_msecs(cfg->retry_timeout) / MSEC_PER_SEC;
442
443         return snprintf(buf, PAGE_SIZE, "%d\n", timeout);
444 }
445
446 static ssize_t
447 retry_timeout_seconds_store(
448         struct kobject  *kobject,
449         const char      *buf,
450         size_t          count)
451 {
452         struct xfs_error_cfg *cfg = to_error_cfg(kobject);
453         int             ret;
454         int             val;
455
456         ret = kstrtoint(buf, 0, &val);
457         if (ret)
458                 return ret;
459
460         /* 1 day timeout maximum, -1 means infinite */
461         if (val < -1 || val > 86400)
462                 return -EINVAL;
463
464         if (val == -1)
465                 cfg->retry_timeout = XFS_ERR_RETRY_FOREVER;
466         else {
467                 cfg->retry_timeout = msecs_to_jiffies(val * MSEC_PER_SEC);
468                 ASSERT(msecs_to_jiffies(val * MSEC_PER_SEC) < LONG_MAX);
469         }
470         return count;
471 }
472 XFS_SYSFS_ATTR_RW(retry_timeout_seconds);
473
474 static ssize_t
475 fail_at_unmount_show(
476         struct kobject  *kobject,
477         char            *buf)
478 {
479         struct xfs_mount        *mp = err_to_mp(kobject);
480
481         return snprintf(buf, PAGE_SIZE, "%d\n", mp->m_fail_unmount);
482 }
483
484 static ssize_t
485 fail_at_unmount_store(
486         struct kobject  *kobject,
487         const char      *buf,
488         size_t          count)
489 {
490         struct xfs_mount        *mp = err_to_mp(kobject);
491         int             ret;
492         int             val;
493
494         ret = kstrtoint(buf, 0, &val);
495         if (ret)
496                 return ret;
497
498         if (val < 0 || val > 1)
499                 return -EINVAL;
500
501         mp->m_fail_unmount = val;
502         return count;
503 }
504 XFS_SYSFS_ATTR_RW(fail_at_unmount);
505
506 static struct attribute *xfs_error_attrs[] = {
507         ATTR_LIST(max_retries),
508         ATTR_LIST(retry_timeout_seconds),
509         NULL,
510 };
511
512
513 static struct kobj_type xfs_error_cfg_ktype = {
514         .release = xfs_sysfs_release,
515         .sysfs_ops = &xfs_sysfs_ops,
516         .default_attrs = xfs_error_attrs,
517 };
518
519 static struct kobj_type xfs_error_ktype = {
520         .release = xfs_sysfs_release,
521         .sysfs_ops = &xfs_sysfs_ops,
522 };
523
524 /*
525  * Error initialization tables. These need to be ordered in the same
526  * order as the enums used to index the array. All class init tables need to
527  * define a "default" behaviour as the first entry, all other entries can be
528  * empty.
529  */
530 struct xfs_error_init {
531         char            *name;
532         int             max_retries;
533         int             retry_timeout;  /* in seconds */
534 };
535
536 static const struct xfs_error_init xfs_error_meta_init[XFS_ERR_ERRNO_MAX] = {
537         { .name = "default",
538           .max_retries = XFS_ERR_RETRY_FOREVER,
539           .retry_timeout = XFS_ERR_RETRY_FOREVER,
540         },
541         { .name = "EIO",
542           .max_retries = XFS_ERR_RETRY_FOREVER,
543           .retry_timeout = XFS_ERR_RETRY_FOREVER,
544         },
545         { .name = "ENOSPC",
546           .max_retries = XFS_ERR_RETRY_FOREVER,
547           .retry_timeout = XFS_ERR_RETRY_FOREVER,
548         },
549         { .name = "ENODEV",
550           .max_retries = 0,     /* We can't recover from devices disappearing */
551           .retry_timeout = 0,
552         },
553 };
554
555 static int
556 xfs_error_sysfs_init_class(
557         struct xfs_mount        *mp,
558         int                     class,
559         const char              *parent_name,
560         struct xfs_kobj         *parent_kobj,
561         const struct xfs_error_init init[])
562 {
563         struct xfs_error_cfg    *cfg;
564         int                     error;
565         int                     i;
566
567         ASSERT(class < XFS_ERR_CLASS_MAX);
568
569         error = xfs_sysfs_init(parent_kobj, &xfs_error_ktype,
570                                 &mp->m_error_kobj, parent_name);
571         if (error)
572                 return error;
573
574         for (i = 0; i < XFS_ERR_ERRNO_MAX; i++) {
575                 cfg = &mp->m_error_cfg[class][i];
576                 error = xfs_sysfs_init(&cfg->kobj, &xfs_error_cfg_ktype,
577                                         parent_kobj, init[i].name);
578                 if (error)
579                         goto out_error;
580
581                 cfg->max_retries = init[i].max_retries;
582                 if (init[i].retry_timeout == XFS_ERR_RETRY_FOREVER)
583                         cfg->retry_timeout = XFS_ERR_RETRY_FOREVER;
584                 else
585                         cfg->retry_timeout = msecs_to_jiffies(
586                                         init[i].retry_timeout * MSEC_PER_SEC);
587         }
588         return 0;
589
590 out_error:
591         /* unwind the entries that succeeded */
592         for (i--; i >= 0; i--) {
593                 cfg = &mp->m_error_cfg[class][i];
594                 xfs_sysfs_del(&cfg->kobj);
595         }
596         xfs_sysfs_del(parent_kobj);
597         return error;
598 }
599
600 int
601 xfs_error_sysfs_init(
602         struct xfs_mount        *mp)
603 {
604         int                     error;
605
606         /* .../xfs/<dev>/error/ */
607         error = xfs_sysfs_init(&mp->m_error_kobj, &xfs_error_ktype,
608                                 &mp->m_kobj, "error");
609         if (error)
610                 return error;
611
612         error = sysfs_create_file(&mp->m_error_kobj.kobject,
613                                   ATTR_LIST(fail_at_unmount));
614
615         if (error)
616                 goto out_error;
617
618         /* .../xfs/<dev>/error/metadata/ */
619         error = xfs_error_sysfs_init_class(mp, XFS_ERR_METADATA,
620                                 "metadata", &mp->m_error_meta_kobj,
621                                 xfs_error_meta_init);
622         if (error)
623                 goto out_error;
624
625         return 0;
626
627 out_error:
628         xfs_sysfs_del(&mp->m_error_kobj);
629         return error;
630 }
631
632 void
633 xfs_error_sysfs_del(
634         struct xfs_mount        *mp)
635 {
636         struct xfs_error_cfg    *cfg;
637         int                     i, j;
638
639         for (i = 0; i < XFS_ERR_CLASS_MAX; i++) {
640                 for (j = 0; j < XFS_ERR_ERRNO_MAX; j++) {
641                         cfg = &mp->m_error_cfg[i][j];
642
643                         xfs_sysfs_del(&cfg->kobj);
644                 }
645         }
646         xfs_sysfs_del(&mp->m_error_meta_kobj);
647         xfs_sysfs_del(&mp->m_error_kobj);
648 }
649
650 struct xfs_error_cfg *
651 xfs_error_get_cfg(
652         struct xfs_mount        *mp,
653         int                     error_class,
654         int                     error)
655 {
656         struct xfs_error_cfg    *cfg;
657
658         if (error < 0)
659                 error = -error;
660
661         switch (error) {
662         case EIO:
663                 cfg = &mp->m_error_cfg[error_class][XFS_ERR_EIO];
664                 break;
665         case ENOSPC:
666                 cfg = &mp->m_error_cfg[error_class][XFS_ERR_ENOSPC];
667                 break;
668         case ENODEV:
669                 cfg = &mp->m_error_cfg[error_class][XFS_ERR_ENODEV];
670                 break;
671         default:
672                 cfg = &mp->m_error_cfg[error_class][XFS_ERR_DEFAULT];
673                 break;
674         }
675
676         return cfg;
677 }