]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs_repair: fix maximum file offset comparison
authorDarrick J. Wong <djwong@kernel.org>
Thu, 21 Nov 2024 00:24:22 +0000 (16:24 -0800)
committerDarrick J. Wong <djwong@kernel.org>
Tue, 24 Dec 2024 02:01:22 +0000 (18:01 -0800)
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@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
repair/dinode.c
repair/globals.c
repair/globals.h
repair/prefetch.c
repair/versions.c

index ac81c487a20b8a0b36aec4285ee970b7fd966074..2c9d9acfa10be5e6c398fc88700227a493964696 100644 (file)
@@ -491,7 +491,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"),
index c0c45df51d562aba4cfe6b42af19f9f0bdf05dac..7388090a7d39f3ba8c355bfacf8c14860efe68cb 100644 (file)
@@ -83,7 +83,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 */
 
index 1eadfdbf9ae4f25b355f522267abb2c009de18ee..fa53502f98bbcd43035be2dab507eddd11ce5aa1 100644 (file)
@@ -124,7 +124,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 */
 
index 0772ecef9d73ebf2e814a08c7b0a5ef9453f8fdd..5ecf19ae9cb111d39edac1246c7feb512f02068d 100644 (file)
@@ -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) ||
index b24965b263a1836d645b54e2ff69bafc92a477ae..7dc91b4597eece4f045d8171297bdc3a66c28169 100644 (file)
@@ -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;
 }