From: Darrick J. Wong <darrick.wong@xxxxxxxxxx> Move the open-coded logic that reports metadata IO read / corruption errors and stales the buffer into xfs_buf_read_map so that it's all consistent. Signed-off-by: Darrick J. Wong <darrick.wong@xxxxxxxxxx> --- fs/xfs/libxfs/xfs_attr_remote.c | 10 ------- fs/xfs/xfs_buf.c | 53 +++++++++++++++++++++++++++++---------- fs/xfs/xfs_log_recover.c | 10 ------- fs/xfs/xfs_symlink.c | 10 ------- fs/xfs/xfs_trans_buf.c | 34 +++++++------------------ 5 files changed, 49 insertions(+), 68 deletions(-) diff --git a/fs/xfs/libxfs/xfs_attr_remote.c b/fs/xfs/libxfs/xfs_attr_remote.c index 46f055804433..8b7f74b3bea2 100644 --- a/fs/xfs/libxfs/xfs_attr_remote.c +++ b/fs/xfs/libxfs/xfs_attr_remote.c @@ -422,16 +422,6 @@ xfs_attr_rmtval_get( 0, &bp, &xfs_attr3_rmt_buf_ops); if (error) return error; - error = bp->b_error; - if (error) { - xfs_buf_ioerror_alert(bp, __func__); - xfs_buf_relse(bp); - - /* bad CRC means corrupted metadata */ - if (error == -EFSBADCRC) - error = -EFSCORRUPTED; - return error; - } error = xfs_attr_rmtval_copyout(mp, bp, args->dp->i_ino, &offset, &valuelen, diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c index 306394300863..c0b4d516fa2c 100644 --- a/fs/xfs/xfs_buf.c +++ b/fs/xfs/xfs_buf.c @@ -817,28 +817,55 @@ xfs_buf_read_map( trace_xfs_buf_read(bp, flags, _RET_IP_); - if (!(bp->b_flags & XBF_DONE)) { + if (bp->b_flags & XBF_DONE) { + /* Buffer already read; all we need to do is check it. */ + xfs_buf_reverify(bp, ops); + + /* Readahead already finished; drop the buffer and exit. */ + if (flags & XBF_ASYNC) { + xfs_buf_relse(bp); + return 0; + } + + /* We do not want read in the flags */ + bp->b_flags &= ~XBF_READ; + ASSERT(bp->b_ops != NULL || ops == NULL); + } else { + /* Initiate the buffer read and wait. */ XFS_STATS_INC(target->bt_mount, xb_get_read); bp->b_ops = ops; _xfs_buf_read(bp, flags); - *bpp = bp; - return 0; + + /* Readahead iodone already dropped the buffer, so exit. */ + if (flags & XBF_ASYNC) + return 0; } - xfs_buf_reverify(bp, ops); + /* + * If we've had a read error, then the contents of the buffer are + * invalid and should not be used. To ensure that a followup read tries + * to pull the buffer from disk again, we clear the XBF_DONE flag and + * mark the buffer stale. This ensures that anyone who has a current + * reference to the buffer will interpret it's contents correctly and + * future cache lookups will also treat it as an empty, uninitialised + * buffer. + */ + if (bp->b_error) { + error = bp->b_error; - if (flags & XBF_ASYNC) { - /* - * Read ahead call which is already satisfied, - * drop the buffer - */ + if (!XFS_FORCED_SHUTDOWN(target->bt_mount)) + xfs_buf_ioerror_alert(bp, __func__); + + bp->b_flags &= ~XBF_DONE; + xfs_buf_stale(bp); xfs_buf_relse(bp); - return 0; + + /* bad CRC means corrupted metadata */ + if (error == -EFSBADCRC) + error = -EFSCORRUPTED; + return error; } - /* We do not want read in the flags */ - bp->b_flags &= ~XBF_READ; - ASSERT(bp->b_ops != NULL || ops == NULL); *bpp = bp; return 0; } diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index b29806846916..ac79537d3275 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -2749,11 +2749,6 @@ xlog_recover_buffer_pass2( buf_flags, &bp, NULL); if (error) return error; - error = bp->b_error; - if (error) { - xfs_buf_ioerror_alert(bp, "xlog_recover_do..(read#1)"); - goto out_release; - } /* * Recover the buffer only if we get an LSN from it and it's less than @@ -2954,11 +2949,6 @@ xlog_recover_inode_pass2( 0, &bp, &xfs_inode_buf_ops); if (error) goto error; - error = bp->b_error; - if (error) { - xfs_buf_ioerror_alert(bp, "xlog_recover_do..(read#2)"); - goto out_release; - } ASSERT(in_f->ilf_fields & XFS_ILOG_CORE); dip = xfs_buf_offset(bp, in_f->ilf_boffset); diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c index a283d6d6fb46..d762d42ed0ff 100644 --- a/fs/xfs/xfs_symlink.c +++ b/fs/xfs/xfs_symlink.c @@ -57,16 +57,6 @@ xfs_readlink_bmap_ilocked( &bp, &xfs_symlink_buf_ops); if (error) return error; - error = bp->b_error; - if (error) { - xfs_buf_ioerror_alert(bp, __func__); - xfs_buf_relse(bp); - - /* bad CRC means corrupted metadata */ - if (error == -EFSBADCRC) - error = -EFSCORRUPTED; - goto out; - } byte_cnt = XFS_SYMLINK_BUF_SPACE(mp, byte_cnt); if (pathlen < byte_cnt) byte_cnt = pathlen; diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c index babbfddbe505..449be0f8c10f 100644 --- a/fs/xfs/xfs_trans_buf.c +++ b/fs/xfs/xfs_trans_buf.c @@ -303,32 +303,16 @@ xfs_trans_read_buf_map( } error = xfs_buf_read_map(target, map, nmaps, flags, &bp, ops); - if (error) - return error; - - /* - * If we've had a read error, then the contents of the buffer are - * invalid and should not be used. To ensure that a followup read tries - * to pull the buffer from disk again, we clear the XBF_DONE flag and - * mark the buffer stale. This ensures that anyone who has a current - * reference to the buffer will interpret it's contents correctly and - * future cache lookups will also treat it as an empty, uninitialised - * buffer. - */ - if (bp->b_error) { - error = bp->b_error; - if (!XFS_FORCED_SHUTDOWN(mp)) - xfs_buf_ioerror_alert(bp, __func__); - bp->b_flags &= ~XBF_DONE; - xfs_buf_stale(bp); - + switch (error) { + case 0: + break; + case -EFSCORRUPTED: + case -EIO: if (tp && (tp->t_flags & XFS_TRANS_DIRTY)) - xfs_force_shutdown(tp->t_mountp, SHUTDOWN_META_IO_ERROR); - xfs_buf_relse(bp); - - /* bad CRC means corrupted metadata */ - if (error == -EFSBADCRC) - error = -EFSCORRUPTED; + xfs_force_shutdown(tp->t_mountp, + SHUTDOWN_META_IO_ERROR); + /* fall through */ + default: return error; }