]> git.ipfire.org Git - thirdparty/kernel/stable.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)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 19 Dec 2024 17:13:08 +0000 (18:13 +0100)
commit bd27c7bcdca25ce8067ebb94ded6ac1bd7b47317 upstream.

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>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
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 b1c46dc82c96f1f86fb4f6be7042ba715737cb46..134d87b3489aa497aed3e309321e4bb6068dfd76 100644 (file)
@@ -5173,7 +5173,7 @@ xfs_btree_count_blocks_helper(
        int                     level,
        void                    *data)
 {
-       xfs_extlen_t            *blocks = data;
+       xfs_filblks_t           *blocks = data;
        (*blocks)++;
 
        return 0;
@@ -5183,7 +5183,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 10b7ddc3b2b34e438589b0d9670e1b210024defb..91e0b6dac31ec61353a1b8adf7871ef2fa029d8c 100644 (file)
@@ -485,7 +485,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 401b42d52af6861237270d3397770a6550ad29d5..6aa43f3fc68e03c08ffd49256e01f740dc7992db 100644 (file)
@@ -743,6 +743,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);
@@ -750,9 +751,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 f8e5b67128d25a190a4b49a7bca355defe603f74..da30f926cbe66df1392021d05ac332496adde0a6 100644 (file)
@@ -434,7 +434,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;
 
@@ -483,7 +483,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)
@@ -816,7 +816,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 2f98d90d7fd66d099c9f8f78725e77700c540a78..69b003259784fefbad309d66630ca985e38b68a9 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 1d3e98346933e1100d951af3ce77618b1d00aa0f..454f17595c9c9e1c00787889d943dd4550d315d0 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 750d7b0cd25a78c3d6ac0f8630c56cc4e6012a8b..a59c44e5903a452a65ca0ce0d0728109c4c84c7a 100644 (file)
@@ -652,8 +652,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 d0c7d4a29c0feb86ce60ee889fa270e26af06dfb..cccf39d917a09c9527d57b63c1010f7ca8f3d1e9 100644 (file)
@@ -490,7 +490,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 edaf193dbd5ccc62097a620cc95ee9255091471c..95f8a09f96ae20160132e349af0905ed4bc21a1b 100644 (file)
@@ -111,7 +111,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;