diff options
author | Eric Sandeen <sandeen@redhat.com> | 2016-09-13 17:51:30 -0400 |
---|---|---|
committer | Dave Chinner <david@fromorbit.com> | 2016-09-13 17:51:30 -0400 |
commit | 77169812739dd800bc3620d781a77c50c75165cc (patch) | |
tree | 7334746af19c67795c61b45287b33b1151c6d6eb /fs/xfs | |
parent | 79c350e45ebc5a718cc2d7114b45ad560069423d (diff) |
xfs: normalize "infinite" retries in error configs
As it stands today, the "fail immediately" vs. "retry forever"
values for max_retries and retry_timeout_seconds in the xfs metadata
error configurations are not consistent.
A retry_timeout_seconds of 0 means "retry forever," but a
max_retries of 0 means "fail immediately."
retry_timeout_seconds < 0 is disallowed, while max_retries == -1
means "retry forever."
Make this consistent across the error configs, such that a value of
0 means "fail immediately" (i.e. wait 0 seconds, or retry 0 times),
and a value of -1 always means "retry forever."
This makes retry_timeout a signed long to accommodate the -1, even
though it stores jiffies. Given our limit of a 1 day maximum
timeout, this should be sufficient even at much higher HZ values
than we have available today.
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r-- | fs/xfs/xfs_buf_item.c | 5 | ||||
-rw-r--r-- | fs/xfs/xfs_mount.h | 8 | ||||
-rw-r--r-- | fs/xfs/xfs_sysfs.c | 47 |
3 files changed, 45 insertions, 15 deletions
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c index 3a279979c39d..2975cb2319f4 100644 --- a/fs/xfs/xfs_buf_item.c +++ b/fs/xfs/xfs_buf_item.c | |||
@@ -1095,7 +1095,8 @@ xfs_buf_iodone_callback_error( | |||
1095 | bp->b_last_error != bp->b_error) { | 1095 | bp->b_last_error != bp->b_error) { |
1096 | bp->b_flags |= (XBF_WRITE | XBF_DONE | XBF_WRITE_FAIL); | 1096 | bp->b_flags |= (XBF_WRITE | XBF_DONE | XBF_WRITE_FAIL); |
1097 | bp->b_last_error = bp->b_error; | 1097 | bp->b_last_error = bp->b_error; |
1098 | if (cfg->retry_timeout && !bp->b_first_retry_time) | 1098 | if (cfg->retry_timeout != XFS_ERR_RETRY_FOREVER && |
1099 | !bp->b_first_retry_time) | ||
1099 | bp->b_first_retry_time = jiffies; | 1100 | bp->b_first_retry_time = jiffies; |
1100 | 1101 | ||
1101 | xfs_buf_ioerror(bp, 0); | 1102 | xfs_buf_ioerror(bp, 0); |
@@ -1111,7 +1112,7 @@ xfs_buf_iodone_callback_error( | |||
1111 | if (cfg->max_retries != XFS_ERR_RETRY_FOREVER && | 1112 | if (cfg->max_retries != XFS_ERR_RETRY_FOREVER && |
1112 | ++bp->b_retries > cfg->max_retries) | 1113 | ++bp->b_retries > cfg->max_retries) |
1113 | goto permanent_error; | 1114 | goto permanent_error; |
1114 | if (cfg->retry_timeout && | 1115 | if (cfg->retry_timeout != XFS_ERR_RETRY_FOREVER && |
1115 | time_after(jiffies, cfg->retry_timeout + bp->b_first_retry_time)) | 1116 | time_after(jiffies, cfg->retry_timeout + bp->b_first_retry_time)) |
1116 | goto permanent_error; | 1117 | goto permanent_error; |
1117 | 1118 | ||
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index b36676cde103..efd4a5526f37 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h | |||
@@ -57,10 +57,16 @@ enum { | |||
57 | 57 | ||
58 | #define XFS_ERR_RETRY_FOREVER -1 | 58 | #define XFS_ERR_RETRY_FOREVER -1 |
59 | 59 | ||
60 | /* | ||
61 | * Although retry_timeout is in jiffies which is normally an unsigned long, | ||
62 | * we limit the retry timeout to 86400 seconds, or one day. So even a | ||
63 | * signed 32-bit long is sufficient for a HZ value up to 24855. Making it | ||
64 | * signed lets us store the special "-1" value, meaning retry forever. | ||
65 | */ | ||
60 | struct xfs_error_cfg { | 66 | struct xfs_error_cfg { |
61 | struct xfs_kobj kobj; | 67 | struct xfs_kobj kobj; |
62 | int max_retries; | 68 | int max_retries; |
63 | unsigned long retry_timeout; /* in jiffies, 0 = no timeout */ | 69 | long retry_timeout; /* in jiffies, -1 = infinite */ |
64 | }; | 70 | }; |
65 | 71 | ||
66 | typedef struct xfs_mount { | 72 | typedef struct xfs_mount { |
diff --git a/fs/xfs/xfs_sysfs.c b/fs/xfs/xfs_sysfs.c index 79cfd3fc5324..5f8d55d29a11 100644 --- a/fs/xfs/xfs_sysfs.c +++ b/fs/xfs/xfs_sysfs.c | |||
@@ -393,9 +393,15 @@ max_retries_show( | |||
393 | struct kobject *kobject, | 393 | struct kobject *kobject, |
394 | char *buf) | 394 | char *buf) |
395 | { | 395 | { |
396 | int retries; | ||
396 | struct xfs_error_cfg *cfg = to_error_cfg(kobject); | 397 | struct xfs_error_cfg *cfg = to_error_cfg(kobject); |
397 | 398 | ||
398 | return snprintf(buf, PAGE_SIZE, "%d\n", cfg->max_retries); | 399 | if (cfg->retry_timeout == XFS_ERR_RETRY_FOREVER) |
400 | retries = -1; | ||
401 | else | ||
402 | retries = cfg->max_retries; | ||
403 | |||
404 | return snprintf(buf, PAGE_SIZE, "%d\n", retries); | ||
399 | } | 405 | } |
400 | 406 | ||
401 | static ssize_t | 407 | static ssize_t |
@@ -415,7 +421,10 @@ max_retries_store( | |||
415 | if (val < -1) | 421 | if (val < -1) |
416 | return -EINVAL; | 422 | return -EINVAL; |
417 | 423 | ||
418 | cfg->max_retries = val; | 424 | if (val == -1) |
425 | cfg->retry_timeout = XFS_ERR_RETRY_FOREVER; | ||
426 | else | ||
427 | cfg->max_retries = val; | ||
419 | return count; | 428 | return count; |
420 | } | 429 | } |
421 | XFS_SYSFS_ATTR_RW(max_retries); | 430 | XFS_SYSFS_ATTR_RW(max_retries); |
@@ -425,10 +434,15 @@ retry_timeout_seconds_show( | |||
425 | struct kobject *kobject, | 434 | struct kobject *kobject, |
426 | char *buf) | 435 | char *buf) |
427 | { | 436 | { |
437 | int timeout; | ||
428 | struct xfs_error_cfg *cfg = to_error_cfg(kobject); | 438 | struct xfs_error_cfg *cfg = to_error_cfg(kobject); |
429 | 439 | ||
430 | return snprintf(buf, PAGE_SIZE, "%ld\n", | 440 | if (cfg->retry_timeout == XFS_ERR_RETRY_FOREVER) |
431 | jiffies_to_msecs(cfg->retry_timeout) / MSEC_PER_SEC); | 441 | timeout = -1; |
442 | else | ||
443 | timeout = jiffies_to_msecs(cfg->retry_timeout) / MSEC_PER_SEC; | ||
444 | |||
445 | return snprintf(buf, PAGE_SIZE, "%d\n", timeout); | ||
432 | } | 446 | } |
433 | 447 | ||
434 | static ssize_t | 448 | static ssize_t |
@@ -445,11 +459,16 @@ retry_timeout_seconds_store( | |||
445 | if (ret) | 459 | if (ret) |
446 | return ret; | 460 | return ret; |
447 | 461 | ||
448 | /* 1 day timeout maximum */ | 462 | /* 1 day timeout maximum, -1 means infinite */ |
449 | if (val < 0 || val > 86400) | 463 | if (val < -1 || val > 86400) |
450 | return -EINVAL; | 464 | return -EINVAL; |
451 | 465 | ||
452 | cfg->retry_timeout = msecs_to_jiffies(val * MSEC_PER_SEC); | 466 | if (val == -1) |
467 | cfg->retry_timeout = XFS_ERR_RETRY_FOREVER; | ||
468 | else { | ||
469 | cfg->retry_timeout = msecs_to_jiffies(val * MSEC_PER_SEC); | ||
470 | ASSERT(msecs_to_jiffies(val * MSEC_PER_SEC) < LONG_MAX); | ||
471 | } | ||
453 | return count; | 472 | return count; |
454 | } | 473 | } |
455 | XFS_SYSFS_ATTR_RW(retry_timeout_seconds); | 474 | XFS_SYSFS_ATTR_RW(retry_timeout_seconds); |
@@ -519,18 +538,19 @@ struct xfs_error_init { | |||
519 | static const struct xfs_error_init xfs_error_meta_init[XFS_ERR_ERRNO_MAX] = { | 538 | static const struct xfs_error_init xfs_error_meta_init[XFS_ERR_ERRNO_MAX] = { |
520 | { .name = "default", | 539 | { .name = "default", |
521 | .max_retries = XFS_ERR_RETRY_FOREVER, | 540 | .max_retries = XFS_ERR_RETRY_FOREVER, |
522 | .retry_timeout = 0, | 541 | .retry_timeout = XFS_ERR_RETRY_FOREVER, |
523 | }, | 542 | }, |
524 | { .name = "EIO", | 543 | { .name = "EIO", |
525 | .max_retries = XFS_ERR_RETRY_FOREVER, | 544 | .max_retries = XFS_ERR_RETRY_FOREVER, |
526 | .retry_timeout = 0, | 545 | .retry_timeout = XFS_ERR_RETRY_FOREVER, |
527 | }, | 546 | }, |
528 | { .name = "ENOSPC", | 547 | { .name = "ENOSPC", |
529 | .max_retries = XFS_ERR_RETRY_FOREVER, | 548 | .max_retries = XFS_ERR_RETRY_FOREVER, |
530 | .retry_timeout = 0, | 549 | .retry_timeout = XFS_ERR_RETRY_FOREVER, |
531 | }, | 550 | }, |
532 | { .name = "ENODEV", | 551 | { .name = "ENODEV", |
533 | .max_retries = 0, | 552 | .max_retries = 0, /* We can't recover from devices disappearing */ |
553 | .retry_timeout = 0, | ||
534 | }, | 554 | }, |
535 | }; | 555 | }; |
536 | 556 | ||
@@ -561,7 +581,10 @@ xfs_error_sysfs_init_class( | |||
561 | goto out_error; | 581 | goto out_error; |
562 | 582 | ||
563 | cfg->max_retries = init[i].max_retries; | 583 | cfg->max_retries = init[i].max_retries; |
564 | cfg->retry_timeout = msecs_to_jiffies( | 584 | if (init[i].retry_timeout == XFS_ERR_RETRY_FOREVER) |
585 | cfg->retry_timeout = XFS_ERR_RETRY_FOREVER; | ||
586 | else | ||
587 | cfg->retry_timeout = msecs_to_jiffies( | ||
565 | init[i].retry_timeout * MSEC_PER_SEC); | 588 | init[i].retry_timeout * MSEC_PER_SEC); |
566 | } | 589 | } |
567 | return 0; | 590 | return 0; |