Commit bd27c7bc authored by Darrick J. Wong's avatar Darrick J. Wong
Browse files

xfs: return a 64-bit block count from xfs_btree_count_blocks



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: df9ad5cc ("xfs: Introduce macros to represent new maximum extent counts for data/attr forks")
Signed-off-by: default avatar"Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
parent e1d8602b
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -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,
+1 −1
Original line number Diff line number Diff line
@@ -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);
+3 −1
Original line number Diff line number Diff line
@@ -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;
}
+3 −3
Original line number Diff line number Diff line
@@ -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))
+3 −3
Original line number Diff line number Diff line
@@ -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);
Loading