diff mbox series

repair: btree blocks are never on the RT subvolume

Message ID 20240715170915.776487-1-hch@lst.de (mailing list archive)
State Superseded
Headers show
Series repair: btree blocks are never on the RT subvolume | expand

Commit Message

Christoph Hellwig July 15, 2024, 5:09 p.m. UTC
scan_bmapbt tries to track btree blocks in the RT duplicate extent
AVL tree if the inode has the realtime flag set.  Given that the
RT subvolume is only ever used for file data this is incorrect.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 repair/scan.c | 21 +++++----------------
 1 file changed, 5 insertions(+), 16 deletions(-)

Comments

Darrick J. Wong July 15, 2024, 5:32 p.m. UTC | #1
On Mon, Jul 15, 2024 at 07:09:15PM +0200, Christoph Hellwig wrote:
> scan_bmapbt tries to track btree blocks in the RT duplicate extent
> AVL tree if the inode has the realtime flag set.  Given that the
> RT subvolume is only ever used for file data this is incorrect.
> 
> Signed-off-by: Christoph Hellwig <hch@lst.de>

Did you actually hit this, or did you find it through code inspection?
AFAICT for attr forks, the (whichfork != XFS_DATA_FORK) check should
have been saving us this whole time?  And the (type != XR_INO_RTDATA)
check did the job for the data fork?

IOWs, is this merely cleaning out a logic bomb, or is it resolving some
false positive/customer complaint?

Reviewed-by: Darrick J. Wong <djwong@kernel.org>

--D

> ---
>  repair/scan.c | 21 +++++----------------
>  1 file changed, 5 insertions(+), 16 deletions(-)
> 
> diff --git a/repair/scan.c b/repair/scan.c
> index 338308ef8..8352b3ccf 100644
> --- a/repair/scan.c
> +++ b/repair/scan.c
> @@ -390,22 +390,11 @@ _("bad state %d, inode %" PRIu64 " bmap block 0x%" PRIx64 "\n"),
>  			break;
>  		}
>  		pthread_mutex_unlock(&ag_locks[agno].lock);
> -	} else  {
> -		/*
> -		 * attribute fork for realtime files is in the regular
> -		 * filesystem
> -		 */
> -		if (type != XR_INO_RTDATA || whichfork != XFS_DATA_FORK)  {
> -			if (search_dup_extent(XFS_FSB_TO_AGNO(mp, bno),
> -					XFS_FSB_TO_AGBNO(mp, bno),
> -					XFS_FSB_TO_AGBNO(mp, bno) + 1))
> -				return(1);
> -		} else  {
> -			xfs_rtxnum_t	ext = xfs_rtb_to_rtx(mp, bno);
> -
> -			if (search_rt_dup_extent(mp, ext))
> -				return 1;
> -		}
> +	} else {
> +		if (search_dup_extent(XFS_FSB_TO_AGNO(mp, bno),
> +				XFS_FSB_TO_AGBNO(mp, bno),
> +				XFS_FSB_TO_AGBNO(mp, bno) + 1))
> +			return 1;
>  	}
>  	(*tot)++;
>  	numrecs = be16_to_cpu(block->bb_numrecs);
> -- 
> 2.43.0
> 
>
Christoph Hellwig July 15, 2024, 5:43 p.m. UTC | #2
On Mon, Jul 15, 2024 at 10:32:04AM -0700, Darrick J. Wong wrote:
> Did you actually hit this, or did you find it through code inspection?

I hit this, but only with the per-rtg rt bitmap, with which this caused
an out of bounds access in the new, non-upstream array of RT AVL trees.

> AFAICT for attr forks, the (whichfork != XFS_DATA_FORK) check should
> have been saving us this whole time?  And the (type != XR_INO_RTDATA)
> check did the job for the data fork?
> 
> IOWs, is this merely cleaning out a logic bomb, or is it resolving some
> false positive/customer complaint?

As far as I can tell this is a real bug upstream.  If you have a bmap
btree block number that when interpreted as a RT extent is also otherwise
used you'll get repair finding an incorrect duplicate block.  It just
seems hard enough to trigger so that no one found it despite being there
since day 1 of public xfsprogs releases.
diff mbox series

Patch

diff --git a/repair/scan.c b/repair/scan.c
index 338308ef8..8352b3ccf 100644
--- a/repair/scan.c
+++ b/repair/scan.c
@@ -390,22 +390,11 @@  _("bad state %d, inode %" PRIu64 " bmap block 0x%" PRIx64 "\n"),
 			break;
 		}
 		pthread_mutex_unlock(&ag_locks[agno].lock);
-	} else  {
-		/*
-		 * attribute fork for realtime files is in the regular
-		 * filesystem
-		 */
-		if (type != XR_INO_RTDATA || whichfork != XFS_DATA_FORK)  {
-			if (search_dup_extent(XFS_FSB_TO_AGNO(mp, bno),
-					XFS_FSB_TO_AGBNO(mp, bno),
-					XFS_FSB_TO_AGBNO(mp, bno) + 1))
-				return(1);
-		} else  {
-			xfs_rtxnum_t	ext = xfs_rtb_to_rtx(mp, bno);
-
-			if (search_rt_dup_extent(mp, ext))
-				return 1;
-		}
+	} else {
+		if (search_dup_extent(XFS_FSB_TO_AGNO(mp, bno),
+				XFS_FSB_TO_AGBNO(mp, bno),
+				XFS_FSB_TO_AGBNO(mp, bno) + 1))
+			return 1;
 	}
 	(*tot)++;
 	numrecs = be16_to_cpu(block->bb_numrecs);