diff options
author | Carlos Maiolino <cmaiolino@redhat.com> | 2016-05-18 11:11:27 +1000 |
---|---|---|
committer | Dave Chinner <david@fromorbit.com> | 2016-05-18 11:11:27 +1000 |
commit | e6b3bb78962e65c4ad125598755cfbf2a8779e86 (patch) | |
tree | 0089723eb2f5ea74989458c53558a38181ddc55f /fs/xfs/xfs_sysfs.c | |
parent | e0a431b3a3cc3d0a4c38ccfca8c7320fde40efb6 (diff) | |
download | linux-e6b3bb78962e65c4ad125598755cfbf2a8779e86.tar.gz linux-e6b3bb78962e65c4ad125598755cfbf2a8779e86.tar.bz2 linux-e6b3bb78962e65c4ad125598755cfbf2a8779e86.zip |
xfs: add "fail at unmount" error handling configuration
If we take "retry forever" literally on metadata IO errors, we can
hang at unmount, once it retries those writes forever. This is the
default behavior, unfortunately.
Add an error configuration option for this behavior and default it
to "fail" so that an unmount will trigger actuall errors, a shutdown
and allow the unmount to succeed. It will be noisy, though, as it
will log the errors and shutdown that occurs.
To fix this, we need to mark the filesystem as being in the process
of unmounting. Do this with a mount flag that is added at the
appropriate time (i.e. before the blocking AIL sync). We also need
to add this flag if mount fails after the initial phase of log
recovery has been run.
Signed-off-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Carlos Maiolino <cmaiolino@redhat.com>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
Diffstat (limited to 'fs/xfs/xfs_sysfs.c')
-rw-r--r-- | fs/xfs/xfs_sysfs.c | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/fs/xfs/xfs_sysfs.c b/fs/xfs/xfs_sysfs.c index 084a606840a1..4c2c55086208 100644 --- a/fs/xfs/xfs_sysfs.c +++ b/fs/xfs/xfs_sysfs.c @@ -381,6 +381,13 @@ to_error_cfg(struct kobject *kobject) return container_of(kobj, struct xfs_error_cfg, kobj); } +static inline struct xfs_mount * +err_to_mp(struct kobject *kobject) +{ + struct xfs_kobj *kobj = to_kobj(kobject); + return container_of(kobj, struct xfs_mount, m_error_kobj); +} + static ssize_t max_retries_show( struct kobject *kobject, @@ -447,6 +454,38 @@ retry_timeout_seconds_store( } XFS_SYSFS_ATTR_RW(retry_timeout_seconds); +static ssize_t +fail_at_unmount_show( + struct kobject *kobject, + char *buf) +{ + struct xfs_mount *mp = err_to_mp(kobject); + + return snprintf(buf, PAGE_SIZE, "%d\n", mp->m_fail_unmount); +} + +static ssize_t +fail_at_unmount_store( + struct kobject *kobject, + const char *buf, + size_t count) +{ + struct xfs_mount *mp = err_to_mp(kobject); + int ret; + int val; + + ret = kstrtoint(buf, 0, &val); + if (ret) + return ret; + + if (val < 0 || val > 1) + return -EINVAL; + + mp->m_fail_unmount = val; + return count; +} +XFS_SYSFS_ATTR_RW(fail_at_unmount); + static struct attribute *xfs_error_attrs[] = { ATTR_LIST(max_retries), ATTR_LIST(retry_timeout_seconds), @@ -462,6 +501,7 @@ struct kobj_type xfs_error_cfg_ktype = { struct kobj_type xfs_error_ktype = { .release = xfs_sysfs_release, + .sysfs_ops = &xfs_sysfs_ops, }; /* @@ -548,6 +588,12 @@ xfs_error_sysfs_init( if (error) return error; + error = sysfs_create_file(&mp->m_error_kobj.kobject, + ATTR_LIST(fail_at_unmount)); + + if (error) + goto out_error; + /* .../xfs/<dev>/error/metadata/ */ error = xfs_error_sysfs_init_class(mp, XFS_ERR_METADATA, "metadata", &mp->m_error_meta_kobj, |