Skip to content

Commit 07cc6bb

Browse files
Eric SandeenLinuxMinion
authored andcommitted
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 <[email protected]> Reviewed-by: Dave Chinner <[email protected]> Signed-off-by: Dave Chinner <[email protected]> (cherry picked from commit 7716981) Orabug: 26130728 Signed-off-by: Kirtikar Kashyap <[email protected]> Reviewed-by: Jack Vogel <[email protected]>
1 parent a0e423a commit 07cc6bb

File tree

3 files changed

+45
-15
lines changed

3 files changed

+45
-15
lines changed

fs/xfs/xfs_buf_item.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1093,7 +1093,8 @@ xfs_buf_iodone_callback_error(
10931093
bp->b_flags |= (XBF_WRITE | XBF_ASYNC |
10941094
XBF_DONE | XBF_WRITE_FAIL);
10951095
bp->b_last_error = bp->b_error;
1096-
if (cfg->retry_timeout && !bp->b_first_retry_time)
1096+
if (cfg->retry_timeout != XFS_ERR_RETRY_FOREVER &&
1097+
!bp->b_first_retry_time)
10971098
bp->b_first_retry_time = jiffies;
10981099

10991100
xfs_buf_ioerror(bp, 0);
@@ -1109,7 +1110,7 @@ xfs_buf_iodone_callback_error(
11091110
if (cfg->max_retries != XFS_ERR_RETRY_FOREVER &&
11101111
++bp->b_retries > cfg->max_retries)
11111112
goto permanent_error;
1112-
if (cfg->retry_timeout &&
1113+
if (cfg->retry_timeout != XFS_ERR_RETRY_FOREVER &&
11131114
time_after(jiffies, cfg->retry_timeout + bp->b_first_retry_time))
11141115
goto permanent_error;
11151116

fs/xfs/xfs_mount.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,16 @@ enum {
5757

5858
#define XFS_ERR_RETRY_FOREVER -1
5959

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+
*/
6066
struct xfs_error_cfg {
6167
struct xfs_kobj kobj;
6268
int max_retries;
63-
unsigned long retry_timeout; /* in jiffies, 0 = no timeout */
69+
long retry_timeout; /* in jiffies, -1 = infinite */
6470
};
6571

6672
typedef struct xfs_mount {

fs/xfs/xfs_sysfs.c

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -302,9 +302,15 @@ max_retries_show(
302302
struct kobject *kobject,
303303
char *buf)
304304
{
305+
int retries;
305306
struct xfs_error_cfg *cfg = to_error_cfg(kobject);
306307

307-
return snprintf(buf, PAGE_SIZE, "%d\n", cfg->max_retries);
308+
if (cfg->retry_timeout == XFS_ERR_RETRY_FOREVER)
309+
retries = -1;
310+
else
311+
retries = cfg->max_retries;
312+
313+
return snprintf(buf, PAGE_SIZE, "%d\n", retries);
308314
}
309315

310316
static ssize_t
@@ -324,7 +330,10 @@ max_retries_store(
324330
if (val < -1)
325331
return -EINVAL;
326332

327-
cfg->max_retries = val;
333+
if (val == -1)
334+
cfg->retry_timeout = XFS_ERR_RETRY_FOREVER;
335+
else
336+
cfg->max_retries = val;
328337
return count;
329338
}
330339
XFS_SYSFS_ATTR_RW(max_retries);
@@ -334,10 +343,15 @@ retry_timeout_seconds_show(
334343
struct kobject *kobject,
335344
char *buf)
336345
{
346+
int timeout;
337347
struct xfs_error_cfg *cfg = to_error_cfg(kobject);
338348

339-
return snprintf(buf, PAGE_SIZE, "%ld\n",
340-
jiffies_to_msecs(cfg->retry_timeout) / MSEC_PER_SEC);
349+
if (cfg->retry_timeout == XFS_ERR_RETRY_FOREVER)
350+
timeout = -1;
351+
else
352+
timeout = jiffies_to_msecs(cfg->retry_timeout) / MSEC_PER_SEC;
353+
354+
return snprintf(buf, PAGE_SIZE, "%d\n", timeout);
341355
}
342356

343357
static ssize_t
@@ -354,11 +368,16 @@ retry_timeout_seconds_store(
354368
if (ret)
355369
return ret;
356370

357-
/* 1 day timeout maximum */
358-
if (val < 0 || val > 86400)
371+
/* 1 day timeout maximum, -1 means infinite */
372+
if (val < -1 || val > 86400)
359373
return -EINVAL;
360374

361-
cfg->retry_timeout = msecs_to_jiffies(val * MSEC_PER_SEC);
375+
if (val == -1)
376+
cfg->retry_timeout = XFS_ERR_RETRY_FOREVER;
377+
else {
378+
cfg->retry_timeout = msecs_to_jiffies(val * MSEC_PER_SEC);
379+
ASSERT(msecs_to_jiffies(val * MSEC_PER_SEC) < LONG_MAX);
380+
}
362381
return count;
363382
}
364383
XFS_SYSFS_ATTR_RW(retry_timeout_seconds);
@@ -428,18 +447,19 @@ struct xfs_error_init {
428447
static const struct xfs_error_init xfs_error_meta_init[XFS_ERR_ERRNO_MAX] = {
429448
{ .name = "default",
430449
.max_retries = XFS_ERR_RETRY_FOREVER,
431-
.retry_timeout = 0,
450+
.retry_timeout = XFS_ERR_RETRY_FOREVER,
432451
},
433452
{ .name = "EIO",
434453
.max_retries = XFS_ERR_RETRY_FOREVER,
435-
.retry_timeout = 0,
454+
.retry_timeout = XFS_ERR_RETRY_FOREVER,
436455
},
437456
{ .name = "ENOSPC",
438457
.max_retries = XFS_ERR_RETRY_FOREVER,
439-
.retry_timeout = 0,
458+
.retry_timeout = XFS_ERR_RETRY_FOREVER,
440459
},
441460
{ .name = "ENODEV",
442-
.max_retries = 0,
461+
.max_retries = 0, /* We can't recover from devices disappearing */
462+
.retry_timeout = 0,
443463
},
444464
};
445465

@@ -470,7 +490,10 @@ xfs_error_sysfs_init_class(
470490
goto out_error;
471491

472492
cfg->max_retries = init[i].max_retries;
473-
cfg->retry_timeout = msecs_to_jiffies(
493+
if (init[i].retry_timeout == XFS_ERR_RETRY_FOREVER)
494+
cfg->retry_timeout = XFS_ERR_RETRY_FOREVER;
495+
else
496+
cfg->retry_timeout = msecs_to_jiffies(
474497
init[i].retry_timeout * MSEC_PER_SEC);
475498
}
476499
return 0;

0 commit comments

Comments
 (0)