From: Allison Henderson <allison.henderson@xxxxxxxxxx> Check to see if the _xfs_buf_read fails. If so loop over the available mirrors and retry the read Signed-off-by: Allison Henderson <allison.henderson@xxxxxxxxxx> --- fs/xfs/xfs_buf.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c index 6098195ecaf4..2c250221cb78 100644 --- a/fs/xfs/xfs_buf.c +++ b/fs/xfs/xfs_buf.c @@ -21,6 +21,7 @@ #include <linux/migrate.h> #include <linux/backing-dev.h> #include <linux/freezer.h> +#include <linux/blkdev.h> #include "xfs_format.h" #include "xfs_log_format.h" @@ -824,6 +825,9 @@ xfs_buf_read_map( const struct xfs_buf_ops *ops) { struct xfs_buf *bp; + struct request_queue *q; + unsigned long i; + int retries = 0; flags |= XBF_READ; @@ -836,7 +840,27 @@ xfs_buf_read_map( if (!(bp->b_flags & XBF_DONE)) { XFS_STATS_INC(target->bt_mount, xb_get_read); bp->b_ops = ops; - _xfs_buf_read(bp, flags); + q = bdev_get_queue(bp->b_target->bt_bdev); + + if (bp->b_alt_retry) + retries = blk_queue_get_mirrors(q); + + for (i = 0; i <= retries; i++) { + bp->b_error = 0; + _xfs_buf_read(bp, flags); + + switch (bp->b_error) { + case -EIO: + case -EFSCORRUPTED: + case -EFSBADCRC: + /* loop again */ + continue; + default: + goto retry_done; + } + + } +retry_done: return bp; } -- 2.17.1