LCOV - code coverage report
Current view: top level - fs/xfs - xfs_sysfs.c (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc3-djwa @ Mon Jul 31 20:08:17 PDT 2023 Lines: 150 220 68.2 %
Date: 2023-07-31 20:08:17 Functions: 22 30 73.3 %

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

Generated by: LCOV version 1.14