xfs: return a 64-bit block count from xfs_btree_count_blocks
authorDarrick J. Wong <djwong@kernel.org>
Mon, 2 Dec 2024 18:57:26 +0000 (10:57 -0800)
committerDarrick J. Wong <djwong@kernel.org>
Fri, 13 Dec 2024 01:45:09 +0000 (17:45 -0800)
With the nrext64 feature enabled, it's possible for a data fork to have
2^48 extent mappings.  Even with a 64k fsblock size, that maps out to
a bmbt containing more than 2^32 blocks.  Therefore, this predicate must
return a u64 count to avoid an integer wraparound that will cause scrub
to do the wrong thing.

It's unlikely that any such filesystem currently exists, because the
incore bmbt would consume more than 64GB of kernel memory on its own,
and so far nobody except me has driven a filesystem that far, judging
from the lack of complaints.

Cc: <stable@vger.kernel.org> # v5.19
Fixes: df9ad5cc7a5240 ("xfs: Introduce macros to represent new maximum extent counts for data/attr forks")
Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
fs/xfs/libxfs/xfs_btree.c
fs/xfs/libxfs/xfs_btree.h
fs/xfs/libxfs/xfs_ialloc_btree.c
fs/xfs/scrub/agheader.c
fs/xfs/scrub/agheader_repair.c
fs/xfs/scrub/fscounters.c
fs/xfs/scrub/ialloc.c
fs/xfs/scrub/refcount.c
fs/xfs/xfs_bmap_util.c

index 2b5fc5f..c748866 100644 (file)
@@ -5144,7 +5144,7 @@ xfs_btree_count_blocks_helper(
        int                     level,
        void                    *data)
 {
-       xfs_extlen_t            *blocks = data;
+       xfs_filblks_t           *blocks = data;
        (*blocks)++;
 
        return 0;
@@ -5154,7 +5154,7 @@ xfs_btree_count_blocks_helper(
 int
 xfs_btree_count_blocks(
        struct xfs_btree_cur    *cur,
-       xfs_extlen_t            *blocks)
+       xfs_filblks_t           *blocks)
 {
        *blocks = 0;
        return xfs_btree_visit_blocks(cur, xfs_btree_count_blocks_helper,
index 3b73945..c5bff27 100644 (file)
@@ -484,7 +484,7 @@ typedef int (*xfs_btree_visit_blocks_fn)(struct xfs_btree_cur *cur, int level,
 int xfs_btree_visit_blocks(struct xfs_btree_cur *cur,
                xfs_btree_visit_blocks_fn fn, unsigned int flags, void *data);
 
-int xfs_btree_count_blocks(struct xfs_btree_cur *cur, xfs_extlen_t *blocks);
+int xfs_btree_count_blocks(struct xfs_btree_cur *cur, xfs_filblks_t *blocks);
 
 union xfs_btree_rec *xfs_btree_rec_addr(struct xfs_btree_cur *cur, int n,
                struct xfs_btree_block *block);
index 9b34896..6f270d8 100644 (file)
@@ -744,6 +744,7 @@ xfs_finobt_count_blocks(
 {
        struct xfs_buf          *agbp = NULL;
        struct xfs_btree_cur    *cur;
+       xfs_filblks_t           blocks;
        int                     error;
 
        error = xfs_ialloc_read_agi(pag, tp, 0, &agbp);
@@ -751,9 +752,10 @@ xfs_finobt_count_blocks(
                return error;
 
        cur = xfs_finobt_init_cursor(pag, tp, agbp);
-       error = xfs_btree_count_blocks(cur, tree_blocks);
+       error = xfs_btree_count_blocks(cur, &blocks);
        xfs_btree_del_cursor(cur, error);
        xfs_trans_brelse(tp, agbp);
+       *tree_blocks = blocks;
 
        return error;
 }
index 61f80a6..1d41b85 100644 (file)
@@ -458,7 +458,7 @@ xchk_agf_xref_btreeblks(
 {
        struct xfs_agf          *agf = sc->sa.agf_bp->b_addr;
        struct xfs_mount        *mp = sc->mp;
-       xfs_agblock_t           blocks;
+       xfs_filblks_t           blocks;
        xfs_agblock_t           btreeblks;
        int                     error;
 
@@ -507,7 +507,7 @@ xchk_agf_xref_refcblks(
        struct xfs_scrub        *sc)
 {
        struct xfs_agf          *agf = sc->sa.agf_bp->b_addr;
-       xfs_agblock_t           blocks;
+       xfs_filblks_t           blocks;
        int                     error;
 
        if (!sc->sa.refc_cur)
@@ -840,7 +840,7 @@ xchk_agi_xref_fiblocks(
        struct xfs_scrub        *sc)
 {
        struct xfs_agi          *agi = sc->sa.agi_bp->b_addr;
-       xfs_agblock_t           blocks;
+       xfs_filblks_t           blocks;
        int                     error = 0;
 
        if (!xfs_has_inobtcounts(sc->mp))
index 0fad0ba..b45d2b3 100644 (file)
@@ -256,7 +256,7 @@ xrep_agf_calc_from_btrees(
        struct xfs_agf          *agf = agf_bp->b_addr;
        struct xfs_mount        *mp = sc->mp;
        xfs_agblock_t           btreeblks;
-       xfs_agblock_t           blocks;
+       xfs_filblks_t           blocks;
        int                     error;
 
        /* Update the AGF counters from the bnobt. */
@@ -946,7 +946,7 @@ xrep_agi_calc_from_btrees(
        if (error)
                goto err;
        if (xfs_has_inobtcounts(mp)) {
-               xfs_agblock_t   blocks;
+               xfs_filblks_t   blocks;
 
                error = xfs_btree_count_blocks(cur, &blocks);
                if (error)
@@ -959,7 +959,7 @@ xrep_agi_calc_from_btrees(
        agi->agi_freecount = cpu_to_be32(freecount);
 
        if (xfs_has_finobt(mp) && xfs_has_inobtcounts(mp)) {
-               xfs_agblock_t   blocks;
+               xfs_filblks_t   blocks;
 
                cur = xfs_finobt_init_cursor(sc->sa.pag, sc->tp, agi_bp);
                error = xfs_btree_count_blocks(cur, &blocks);
index 4a50f8e..ca23cf4 100644 (file)
@@ -261,7 +261,7 @@ xchk_fscount_btreeblks(
        struct xchk_fscounters  *fsc,
        xfs_agnumber_t          agno)
 {
-       xfs_extlen_t            blocks;
+       xfs_filblks_t           blocks;
        int                     error;
 
        error = xchk_ag_init_existing(sc, agno, &sc->sa);
index abad54c..4dc7c83 100644 (file)
@@ -650,8 +650,8 @@ xchk_iallocbt_xref_rmap_btreeblks(
        struct xfs_scrub        *sc)
 {
        xfs_filblks_t           blocks;
-       xfs_extlen_t            inobt_blocks = 0;
-       xfs_extlen_t            finobt_blocks = 0;
+       xfs_filblks_t           inobt_blocks = 0;
+       xfs_filblks_t           finobt_blocks = 0;
        int                     error;
 
        if (!sc->sa.ino_cur || !sc->sa.rmap_cur ||
index 2b6be75..1c5e45c 100644 (file)
@@ -491,7 +491,7 @@ xchk_refcount_xref_rmap(
        struct xfs_scrub        *sc,
        xfs_filblks_t           cow_blocks)
 {
-       xfs_extlen_t            refcbt_blocks = 0;
+       xfs_filblks_t           refcbt_blocks = 0;
        xfs_filblks_t           blocks;
        int                     error;
 
index a59bbe7..0836fea 100644 (file)
@@ -103,7 +103,7 @@ xfs_bmap_count_blocks(
        struct xfs_mount        *mp = ip->i_mount;
        struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
        struct xfs_btree_cur    *cur;
-       xfs_extlen_t            btblocks = 0;
+       xfs_filblks_t           btblocks = 0;
        int                     error;
 
        *nextents = 0;