diff mbox series

[3/7] xfs: fix buffer corruption reporting when xfs_dir3_free_header_check fails

Message ID 158388765361.939165.18143580183240823438.stgit@magnolia (mailing list archive)
State Accepted
Headers show
Series xfs: fix errors in various verifiers | expand

Commit Message

Darrick J. Wong March 11, 2020, 12:47 a.m. UTC
From: Darrick J. Wong <darrick.wong@oracle.com>

xfs_verifier_error is supposed to be called on a corrupt metadata buffer
from within a buffer verifier function, whereas xfs_buf_corruption_error
is the function to be called when a piece of code has read a buffer and
catches something that a read verifier cannot.  The first function sets
b_error anticipating that the low level buffer handling code will see
the nonzero b_error and clear XBF_DONE on the buffer, whereas the second
function does not.

Since xfs_dir3_free_header_check examines fields in the dir free block
header that require more context than can be provided to read verifiers,
we must call xfs_buf_corruption_error when it finds a problem.

Switching the calls has a secondary effect that we no longer corrupt the
buffer state by setting b_error and leaving XBF_DONE set.  When /that/
happens, we'll trip over various state assertions (most commonly the
b_error check in xfs_buf_reverify) on a subsequent attempt to read the
buffer.

Fixes: bc1a09b8e334bf5f ("xfs: refactor verifier callers to print address of failing check")
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 fs/xfs/libxfs/xfs_dir2_node.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Comments

Dave Chinner March 11, 2020, 5:39 a.m. UTC | #1
On Tue, Mar 10, 2020 at 05:47:33PM -0700, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
> 
> xfs_verifier_error is supposed to be called on a corrupt metadata buffer
> from within a buffer verifier function, whereas xfs_buf_corruption_error

xfs_buf_mark_corrupt()?

> is the function to be called when a piece of code has read a buffer and
> catches something that a read verifier cannot.  The first function sets
> b_error anticipating that the low level buffer handling code will see
> the nonzero b_error and clear XBF_DONE on the buffer, whereas the second
> function does not.
> 
> Since xfs_dir3_free_header_check examines fields in the dir free block
> header that require more context than can be provided to read verifiers,
> we must call xfs_buf_corruption_error when it finds a problem.

And again?

> 
> Switching the calls has a secondary effect that we no longer corrupt the
> buffer state by setting b_error and leaving XBF_DONE set.  When /that/
> happens, we'll trip over various state assertions (most commonly the
> b_error check in xfs_buf_reverify) on a subsequent attempt to read the
> buffer.
> 
> Fixes: bc1a09b8e334bf5f ("xfs: refactor verifier callers to print address of failing check")
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> ---
>  fs/xfs/libxfs/xfs_dir2_node.c |    2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> 
> diff --git a/fs/xfs/libxfs/xfs_dir2_node.c b/fs/xfs/libxfs/xfs_dir2_node.c
> index dbd1e901da92..af4f22dc3891 100644
> --- a/fs/xfs/libxfs/xfs_dir2_node.c
> +++ b/fs/xfs/libxfs/xfs_dir2_node.c
> @@ -226,7 +226,7 @@ __xfs_dir3_free_read(
>  	/* Check things that we can't do in the verifier. */
>  	fa = xfs_dir3_free_header_check(dp, fbno, *bpp);
>  	if (fa) {
> -		xfs_verifier_error(*bpp, -EFSCORRUPTED, fa);
> +		__xfs_buf_mark_corrupt(*bpp, fa);
>  		xfs_trans_brelse(tp, *bpp);
>  		return -EFSCORRUPTED;
>  	}

Code looks fine. WIth the commit description fixes,

Reviewed-by: Dave Chinner <dchinner@redhat.com>
diff mbox series

Patch

diff --git a/fs/xfs/libxfs/xfs_dir2_node.c b/fs/xfs/libxfs/xfs_dir2_node.c
index dbd1e901da92..af4f22dc3891 100644
--- a/fs/xfs/libxfs/xfs_dir2_node.c
+++ b/fs/xfs/libxfs/xfs_dir2_node.c
@@ -226,7 +226,7 @@  __xfs_dir3_free_read(
 	/* Check things that we can't do in the verifier. */
 	fa = xfs_dir3_free_header_check(dp, fbno, *bpp);
 	if (fa) {
-		xfs_verifier_error(*bpp, -EFSCORRUPTED, fa);
+		__xfs_buf_mark_corrupt(*bpp, fa);
 		xfs_trans_brelse(tp, *bpp);
 		return -EFSCORRUPTED;
 	}