]> www.infradead.org Git - users/hch/misc.git/commitdiff
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 2b5fc5fd16435d01b3474b74b8ad7f598945bac6..c748866ef92368c8876447f6e2ed33249a0666c8 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 3b739459ebb0f4c51630533c152e24b9d64699f0..c5bff273cae255d94ef5715aeec64121187d0a68 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 9b34896dd1a32f29ee9f75922e6f46e0a27d82b9..6f270d8f4270cb18ba954e89c7810e30b7f92ccc 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 61f80a6410c7387e2bf96f916dc9b356636a8012..1d41b85478da9d5680a2594ac51e9dab8a5b3f76 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 0fad0baaba2f69cbefd69dc6194ce9fdc8fada2b..b45d2b32051a63f98655885a045052dbfdc8f2a6 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 4a50f8e0004092e51320ef8e8e258cf7fd55c9dc..ca23cf4db6c5ef727ce046c25cb5d0e8b3444359 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 abad54c3621d4455782a1acb2da59a5566128ff4..4dc7c83dc08a4060be4b8e9e3109a4f7fd144030 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 2b6be75e94241515f573e6caf77e3ef88bebd88a..1c5e45cc64190c8be35ac3e4e3286f7ec8783638 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 a59bbe767a7dc42018adcec61e83836dfe03a4e9..0836fea2d6d8144e4cb8bea929f6824f9f334a81 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;