xfs: add configuration of error failure speed
On reception of an error, we can fail immediately, perform some bound amount of retries or retry indefinitely. The current behaviour we have is to retry forever. However, we'd like the ability to choose how long the filesystem should try after an error, it can either fail immediately, retry a few times, or retry forever. This is implemented by using max_retries sysfs attribute, to hold the amount of times we allow the filesystem to retry after an error. Being -1 a special case where the filesystem will retry indefinitely. Add both a maximum retry count and a retry timeout so that we can bound by time and/or physical IO attempts. Finally, plumb these into xfs_buf_iodone error processing so that the error behaviour follows the selected configuration. 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>
This commit is contained in:

committed by
Dave Chinner

parent
ef6a50fbb1
commit
a5ea70d25d
@@ -374,10 +374,6 @@ struct kobj_type xfs_log_ktype = {
|
||||
* and any other future type of IO (e.g. special inode or directory error
|
||||
* handling) we care to support.
|
||||
*/
|
||||
static struct attribute *xfs_error_attrs[] = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
static inline struct xfs_error_cfg *
|
||||
to_error_cfg(struct kobject *kobject)
|
||||
{
|
||||
@@ -385,6 +381,79 @@ to_error_cfg(struct kobject *kobject)
|
||||
return container_of(kobj, struct xfs_error_cfg, kobj);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
max_retries_show(
|
||||
struct kobject *kobject,
|
||||
char *buf)
|
||||
{
|
||||
struct xfs_error_cfg *cfg = to_error_cfg(kobject);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", cfg->max_retries);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
max_retries_store(
|
||||
struct kobject *kobject,
|
||||
const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
struct xfs_error_cfg *cfg = to_error_cfg(kobject);
|
||||
int ret;
|
||||
int val;
|
||||
|
||||
ret = kstrtoint(buf, 0, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (val < -1)
|
||||
return -EINVAL;
|
||||
|
||||
cfg->max_retries = val;
|
||||
return count;
|
||||
}
|
||||
XFS_SYSFS_ATTR_RW(max_retries);
|
||||
|
||||
static ssize_t
|
||||
retry_timeout_seconds_show(
|
||||
struct kobject *kobject,
|
||||
char *buf)
|
||||
{
|
||||
struct xfs_error_cfg *cfg = to_error_cfg(kobject);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%ld\n",
|
||||
jiffies_to_msecs(cfg->retry_timeout) / MSEC_PER_SEC);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
retry_timeout_seconds_store(
|
||||
struct kobject *kobject,
|
||||
const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
struct xfs_error_cfg *cfg = to_error_cfg(kobject);
|
||||
int ret;
|
||||
int val;
|
||||
|
||||
ret = kstrtoint(buf, 0, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* 1 day timeout maximum */
|
||||
if (val < 0 || val > 86400)
|
||||
return -EINVAL;
|
||||
|
||||
cfg->retry_timeout = msecs_to_jiffies(val * MSEC_PER_SEC);
|
||||
return count;
|
||||
}
|
||||
XFS_SYSFS_ATTR_RW(retry_timeout_seconds);
|
||||
|
||||
static struct attribute *xfs_error_attrs[] = {
|
||||
ATTR_LIST(max_retries),
|
||||
ATTR_LIST(retry_timeout_seconds),
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
||||
struct kobj_type xfs_error_cfg_ktype = {
|
||||
.release = xfs_sysfs_release,
|
||||
.sysfs_ops = &xfs_sysfs_ops,
|
||||
@@ -404,11 +473,13 @@ struct kobj_type xfs_error_ktype = {
|
||||
struct xfs_error_init {
|
||||
char *name;
|
||||
int max_retries;
|
||||
int retry_timeout; /* in seconds */
|
||||
};
|
||||
|
||||
static const struct xfs_error_init xfs_error_meta_init[XFS_ERR_ERRNO_MAX] = {
|
||||
{ .name = "default",
|
||||
.max_retries = -1,
|
||||
.retry_timeout = 0,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -439,6 +510,8 @@ xfs_error_sysfs_init_class(
|
||||
goto out_error;
|
||||
|
||||
cfg->max_retries = init[i].max_retries;
|
||||
cfg->retry_timeout = msecs_to_jiffies(
|
||||
init[i].retry_timeout * MSEC_PER_SEC);
|
||||
}
|
||||
return 0;
|
||||
|
||||
|
Reference in New Issue
Block a user