From: Darrick J. Wong <djwong@xxxxxxxxxx> When running generic/525 with rtinherit=1 and rextsize=28k, generic/525 trips over the following block mapping: data offset 2251799813685247 startblock 7 (0/7) count 1 flag 0 data offset 2251799813685248 startblock 8 (0/8) count 6 flag 1 with this error: inode 155 - extent exceeds max offset - start 2251799813685248, count 6, physical block 8 This is due to an incorrect check in xfs_repair, which tries to validate that a block mapping cannot exceed what it thinks is the maximum file offset. Unfortunately, the check is wrong, because only br_startoff is subject to the 2^52-1 limit -- not br_startoff + br_blockcount. Nowadays libxfs provides a symbol XFS_MAX_FILEOFF for the maximum allowable file block offset that can be mapped into a file. Use this instead of the open-coded logic in versions.c and correct all the other checks. Note that this problem only surfaced when rtgroups were enabled because hch changed xfs_repair to use the same tree-based block state data structure that we use for AGs when rtgroups are enabled. Signed-off-by: "Darrick J. Wong" <djwong@xxxxxxxxxx> --- repair/dinode.c | 2 +- repair/globals.c | 1 - repair/globals.h | 1 - repair/prefetch.c | 2 +- repair/versions.c | 7 +------ 5 files changed, 3 insertions(+), 10 deletions(-) diff --git a/repair/dinode.c b/repair/dinode.c index 9fea0cedd71cfe..2185214ac41bdf 100644 --- a/repair/dinode.c +++ b/repair/dinode.c @@ -501,7 +501,7 @@ _("inode %" PRIu64 " - bad extent overflows - start %" PRIu64 ", " } /* Ensure this extent does not extend beyond the max offset */ if (irec.br_startoff + irec.br_blockcount - 1 > - fs_max_file_offset) { + XFS_MAX_FILEOFF) { do_warn( _("inode %" PRIu64 " - extent exceeds max offset - start %" PRIu64 ", " "count %" PRIu64 ", physical block %" PRIu64 "\n"), diff --git a/repair/globals.c b/repair/globals.c index 07f7526a73a0b1..b63931be9fdb70 100644 --- a/repair/globals.c +++ b/repair/globals.c @@ -86,7 +86,6 @@ int inodes_per_block; unsigned int glob_agcount; int chunks_pblock; /* # of 64-ino chunks per allocation */ int max_symlink_blocks; -int64_t fs_max_file_offset; /* realtime info */ diff --git a/repair/globals.h b/repair/globals.h index 7db710a266b3c7..1dc85ce7f8114c 100644 --- a/repair/globals.h +++ b/repair/globals.h @@ -127,7 +127,6 @@ extern int inodes_per_block; extern unsigned int glob_agcount; extern int chunks_pblock; /* # of 64-ino chunks per allocation */ extern int max_symlink_blocks; -extern int64_t fs_max_file_offset; /* realtime info */ diff --git a/repair/prefetch.c b/repair/prefetch.c index 0772ecef9d73eb..5ecf19ae9cb111 100644 --- a/repair/prefetch.c +++ b/repair/prefetch.c @@ -185,7 +185,7 @@ pf_read_bmbt_reclist( if (((i > 0) && (op + cp > irec.br_startoff)) || (irec.br_blockcount == 0) || - (irec.br_startoff >= fs_max_file_offset)) + (irec.br_startoff + irec.br_blockcount - 1 >= XFS_MAX_FILEOFF)) goto out_free; if (!libxfs_verify_fsbno(mp, irec.br_startblock) || diff --git a/repair/versions.c b/repair/versions.c index b24965b263a183..7dc91b4597eece 100644 --- a/repair/versions.c +++ b/repair/versions.c @@ -180,10 +180,5 @@ _("WARNING: you have a V1 inode filesystem. It would be converted to a\n" fs_ino_alignment = mp->m_sb.sb_inoalignmt; } - /* - * calculate maximum file offset for this geometry - */ - fs_max_file_offset = 0x7fffffffffffffffLL >> mp->m_sb.sb_blocklog; - - return(0); + return 0; }