Commit e45ea364 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Darrick J. Wong
Browse files

xfs: split the agf_roots and agf_levels arrays



Using arrays of largely unrelated fields that use the btree number
as index is not very robust.  Split the arrays into three separate
fields instead.

Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarDarrick J. Wong <djwong@kernel.org>
Signed-off-by: default avatarDarrick J. Wong <djwong@kernel.org>
parent 02f7ebf5
Loading
Loading
Loading
Loading
+6 −7
Original line number Diff line number Diff line
@@ -669,14 +669,13 @@ xfs_agfblock_init(
	agf->agf_versionnum = cpu_to_be32(XFS_AGF_VERSION);
	agf->agf_seqno = cpu_to_be32(id->agno);
	agf->agf_length = cpu_to_be32(id->agsize);
	agf->agf_roots[XFS_BTNUM_BNOi] = cpu_to_be32(XFS_BNO_BLOCK(mp));
	agf->agf_roots[XFS_BTNUM_CNTi] = cpu_to_be32(XFS_CNT_BLOCK(mp));
	agf->agf_levels[XFS_BTNUM_BNOi] = cpu_to_be32(1);
	agf->agf_levels[XFS_BTNUM_CNTi] = cpu_to_be32(1);
	agf->agf_bno_root = cpu_to_be32(XFS_BNO_BLOCK(mp));
	agf->agf_cnt_root = cpu_to_be32(XFS_CNT_BLOCK(mp));
	agf->agf_bno_level = cpu_to_be32(1);
	agf->agf_cnt_level = cpu_to_be32(1);
	if (xfs_has_rmapbt(mp)) {
		agf->agf_roots[XFS_BTNUM_RMAPi] =
					cpu_to_be32(XFS_RMAP_BLOCK(mp));
		agf->agf_levels[XFS_BTNUM_RMAPi] = cpu_to_be32(1);
		agf->agf_rmap_root = cpu_to_be32(XFS_RMAP_BLOCK(mp));
		agf->agf_rmap_level = cpu_to_be32(1);
		agf->agf_rmap_blocks = cpu_to_be32(1);
	}

+5 −3
Original line number Diff line number Diff line
@@ -36,8 +36,9 @@ struct xfs_perag {
	atomic_t	pag_active_ref;	/* active reference count */
	wait_queue_head_t pag_active_wq;/* woken active_ref falls to zero */
	unsigned long	pag_opstate;
	uint8_t		pagf_levels[XFS_BTNUM_AGF];
					/* # of levels in bno & cnt btree */
	uint8_t		pagf_bno_level;	/* # of levels in bno btree */
	uint8_t		pagf_cnt_level;	/* # of levels in cnt btree */
	uint8_t		pagf_rmap_level;/* # of levels in rmap btree */
	uint32_t	pagf_flcount;	/* count of blocks in freelist */
	xfs_extlen_t	pagf_freeblks;	/* total free blocks */
	xfs_extlen_t	pagf_longest;	/* longest free space */
@@ -86,7 +87,8 @@ struct xfs_perag {
	 * Alternate btree heights so that online repair won't trip the write
	 * verifiers while rebuilding the AG btrees.
	 */
	uint8_t		pagf_repair_levels[XFS_BTNUM_AGF];
	uint8_t		pagf_repair_bno_level;
	uint8_t		pagf_repair_cnt_level;
	uint8_t		pagf_repair_refcount_level;
#endif

+19 −30
Original line number Diff line number Diff line
@@ -2335,8 +2335,9 @@ xfs_alloc_min_freelist(
	struct xfs_perag	*pag)
{
	/* AG btrees have at least 1 level. */
	static const uint8_t	fake_levels[XFS_BTNUM_AGF] = {1, 1, 1};
	const uint8_t		*levels = pag ? pag->pagf_levels : fake_levels;
	const unsigned int	bno_level = pag ? pag->pagf_bno_level : 1;
	const unsigned int	cnt_level = pag ? pag->pagf_cnt_level : 1;
	const unsigned int	rmap_level = pag ? pag->pagf_rmap_level : 1;
	unsigned int		min_free;

	ASSERT(mp->m_alloc_maxlevels > 0);
@@ -2363,16 +2364,12 @@ xfs_alloc_min_freelist(
	 */

	/* space needed by-bno freespace btree */
	min_free = min_t(unsigned int, levels[XFS_BTNUM_BNOi] + 1,
				       mp->m_alloc_maxlevels) * 2 - 2;
	min_free = min(bno_level + 1, mp->m_alloc_maxlevels) * 2 - 2;
	/* space needed by-size freespace btree */
	min_free += min_t(unsigned int, levels[XFS_BTNUM_CNTi] + 1,
				       mp->m_alloc_maxlevels) * 2 - 2;
	min_free += min(cnt_level + 1, mp->m_alloc_maxlevels) * 2 - 2;
	/* space needed reverse mapping used space btree */
	if (xfs_has_rmapbt(mp))
		min_free += min_t(unsigned int, levels[XFS_BTNUM_RMAPi] + 1,
						mp->m_rmap_maxlevels) * 2 - 2;

		min_free += min(rmap_level + 1, mp->m_rmap_maxlevels) * 2 - 2;
	return min_free;
}

@@ -3056,8 +3053,8 @@ xfs_alloc_log_agf(
		offsetof(xfs_agf_t, agf_versionnum),
		offsetof(xfs_agf_t, agf_seqno),
		offsetof(xfs_agf_t, agf_length),
		offsetof(xfs_agf_t, agf_roots[0]),
		offsetof(xfs_agf_t, agf_levels[0]),
		offsetof(xfs_agf_t, agf_bno_root),   /* also cnt/rmap root */
		offsetof(xfs_agf_t, agf_bno_level),  /* also cnt/rmap levels */
		offsetof(xfs_agf_t, agf_flfirst),
		offsetof(xfs_agf_t, agf_fllast),
		offsetof(xfs_agf_t, agf_flcount),
@@ -3236,12 +3233,10 @@ xfs_agf_verify(
	    be32_to_cpu(agf->agf_freeblks) > agf_length)
		return __this_address;

	if (be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNO]) < 1 ||
	    be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]) < 1 ||
	    be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNO]) >
						mp->m_alloc_maxlevels ||
	    be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]) >
						mp->m_alloc_maxlevels)
	if (be32_to_cpu(agf->agf_bno_level) < 1 ||
	    be32_to_cpu(agf->agf_cnt_level) < 1 ||
	    be32_to_cpu(agf->agf_bno_level) > mp->m_alloc_maxlevels ||
	    be32_to_cpu(agf->agf_cnt_level) > mp->m_alloc_maxlevels)
		return __this_address;

	if (xfs_has_lazysbcount(mp) &&
@@ -3252,9 +3247,8 @@ xfs_agf_verify(
		if (be32_to_cpu(agf->agf_rmap_blocks) > agf_length)
			return __this_address;

		if (be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]) < 1 ||
		    be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]) >
							mp->m_rmap_maxlevels)
		if (be32_to_cpu(agf->agf_rmap_level) < 1 ||
		    be32_to_cpu(agf->agf_rmap_level) > mp->m_rmap_maxlevels)
			return __this_address;
	}

@@ -3380,12 +3374,9 @@ xfs_alloc_read_agf(
		pag->pagf_btreeblks = be32_to_cpu(agf->agf_btreeblks);
		pag->pagf_flcount = be32_to_cpu(agf->agf_flcount);
		pag->pagf_longest = be32_to_cpu(agf->agf_longest);
		pag->pagf_levels[XFS_BTNUM_BNOi] =
			be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNOi]);
		pag->pagf_levels[XFS_BTNUM_CNTi] =
			be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNTi]);
		pag->pagf_levels[XFS_BTNUM_RMAPi] =
			be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAPi]);
		pag->pagf_bno_level = be32_to_cpu(agf->agf_bno_level);
		pag->pagf_cnt_level = be32_to_cpu(agf->agf_cnt_level);
		pag->pagf_rmap_level = be32_to_cpu(agf->agf_rmap_level);
		pag->pagf_refcount_level = be32_to_cpu(agf->agf_refcount_level);
		if (xfs_agfl_needs_reset(pag->pag_mount, agf))
			set_bit(XFS_AGSTATE_AGFL_NEEDS_RESET, &pag->pag_opstate);
@@ -3414,10 +3405,8 @@ xfs_alloc_read_agf(
		ASSERT(pag->pagf_btreeblks == be32_to_cpu(agf->agf_btreeblks));
		ASSERT(pag->pagf_flcount == be32_to_cpu(agf->agf_flcount));
		ASSERT(pag->pagf_longest == be32_to_cpu(agf->agf_longest));
		ASSERT(pag->pagf_levels[XFS_BTNUM_BNOi] ==
		       be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNOi]));
		ASSERT(pag->pagf_levels[XFS_BTNUM_CNTi] ==
		       be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNTi]));
		ASSERT(pag->pagf_bno_level == be32_to_cpu(agf->agf_bno_level));
		ASSERT(pag->pagf_cnt_level == be32_to_cpu(agf->agf_cnt_level));
	}
#endif
	if (agfbpp)
+35 −17
Original line number Diff line number Diff line
@@ -38,13 +38,18 @@ xfs_allocbt_set_root(
{
	struct xfs_buf		*agbp = cur->bc_ag.agbp;
	struct xfs_agf		*agf = agbp->b_addr;
	int			btnum = cur->bc_btnum;

	ASSERT(ptr->s != 0);

	agf->agf_roots[btnum] = ptr->s;
	be32_add_cpu(&agf->agf_levels[btnum], inc);
	cur->bc_ag.pag->pagf_levels[btnum] += inc;
	if (cur->bc_btnum == XFS_BTNUM_BNO) {
		agf->agf_bno_root = ptr->s;
		be32_add_cpu(&agf->agf_bno_level, inc);
		cur->bc_ag.pag->pagf_bno_level += inc;
	} else {
		agf->agf_cnt_root = ptr->s;
		be32_add_cpu(&agf->agf_cnt_level, inc);
		cur->bc_ag.pag->pagf_cnt_level += inc;
	}

	xfs_alloc_log_agf(cur->bc_tp, agbp, XFS_AGF_ROOTS | XFS_AGF_LEVELS);
}
@@ -226,7 +231,10 @@ xfs_allocbt_init_ptr_from_cur(

	ASSERT(cur->bc_ag.pag->pag_agno == be32_to_cpu(agf->agf_seqno));

	ptr->s = agf->agf_roots[cur->bc_btnum];
	if (cur->bc_btnum == XFS_BTNUM_BNO)
		ptr->s = agf->agf_bno_root;
	else
		ptr->s = agf->agf_cnt_root;
}

STATIC int64_t
@@ -299,7 +307,6 @@ xfs_allocbt_verify(
	struct xfs_perag	*pag = bp->b_pag;
	xfs_failaddr_t		fa;
	unsigned int		level;
	xfs_btnum_t		btnum = XFS_BTNUM_BNOi;

	if (!xfs_verify_magic(bp, block->bb_magic))
		return __this_address;
@@ -320,21 +327,27 @@ xfs_allocbt_verify(
	 * against.
	 */
	level = be16_to_cpu(block->bb_level);
	if (bp->b_ops->magic[0] == cpu_to_be32(XFS_ABTC_MAGIC))
		btnum = XFS_BTNUM_CNTi;
	if (pag && xfs_perag_initialised_agf(pag)) {
		unsigned int	maxlevel = pag->pagf_levels[btnum];
		unsigned int	maxlevel, repair_maxlevel = 0;

#ifdef CONFIG_XFS_ONLINE_REPAIR
		/*
		 * Online repair could be rewriting the free space btrees, so
		 * we'll validate against the larger of either tree while this
		 * is going on.
		 */
		maxlevel = max_t(unsigned int, maxlevel,
				 pag->pagf_repair_levels[btnum]);
		if (bp->b_ops->magic[0] == cpu_to_be32(XFS_ABTC_MAGIC)) {
			maxlevel = pag->pagf_cnt_level;
#ifdef CONFIG_XFS_ONLINE_REPAIR
			repair_maxlevel = pag->pagf_repair_cnt_level;
#endif
		if (level >= maxlevel)
		} else {
			maxlevel = pag->pagf_bno_level;
#ifdef CONFIG_XFS_ONLINE_REPAIR
			repair_maxlevel = pag->pagf_repair_bno_level;
#endif
		}

		if (level >= max(maxlevel, repair_maxlevel))
			return __this_address;
	} else if (level >= mp->m_alloc_maxlevels)
		return __this_address;
@@ -542,8 +555,8 @@ xfs_allocbt_init_cursor(
		struct xfs_agf		*agf = agbp->b_addr;

		cur->bc_nlevels = (btnum == XFS_BTNUM_BNO) ?
			be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNO]) :
			be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]);
			be32_to_cpu(agf->agf_bno_level) :
			be32_to_cpu(agf->agf_cnt_level);
	}
	return cur;
}
@@ -563,8 +576,13 @@ xfs_allocbt_commit_staged_btree(

	ASSERT(cur->bc_flags & XFS_BTREE_STAGING);

	agf->agf_roots[cur->bc_btnum] = cpu_to_be32(afake->af_root);
	agf->agf_levels[cur->bc_btnum] = cpu_to_be32(afake->af_levels);
	if (cur->bc_btnum == XFS_BTNUM_BNO) {
		agf->agf_bno_root = cpu_to_be32(afake->af_root);
		agf->agf_bno_level = cpu_to_be32(afake->af_levels);
	} else {
		agf->agf_cnt_root = cpu_to_be32(afake->af_root);
		agf->agf_cnt_level = cpu_to_be32(afake->af_levels);
	}
	xfs_alloc_log_agf(tp, agbp, XFS_AGF_ROOTS | XFS_AGF_LEVELS);

	xfs_btree_commit_afakeroot(cur, tp, agbp);
+10 −11
Original line number Diff line number Diff line
@@ -477,15 +477,9 @@ xfs_is_quota_inode(struct xfs_sb *sbp, xfs_ino_t ino)
#define	XFS_AGI_GOOD_VERSION(v)	((v) == XFS_AGI_VERSION)

/*
 * Btree number 0 is bno, 1 is cnt, 2 is rmap. This value gives the size of the
 * arrays below.
 */
#define	XFS_BTNUM_AGF	((int)XFS_BTNUM_RMAPi + 1)

/*
 * The second word of agf_levels in the first a.g. overlaps the EFS
 * superblock's magic number.  Since the magic numbers valid for EFS
 * are > 64k, our value cannot be confused for an EFS superblock's.
 * agf_cnt_level in the first AGF overlaps the EFS superblock's magic number.
 * Since the magic numbers valid for EFS are > 64k, our value cannot be confused
 * for an EFS superblock.
 */

typedef struct xfs_agf {
@@ -499,8 +493,13 @@ typedef struct xfs_agf {
	/*
	 * Freespace and rmap information
	 */
	__be32		agf_roots[XFS_BTNUM_AGF];	/* root blocks */
	__be32		agf_levels[XFS_BTNUM_AGF];	/* btree levels */
	__be32		agf_bno_root;	/* bnobt root block */
	__be32		agf_cnt_root;	/* cntbt root block */
	__be32		agf_rmap_root;	/* rmapbt root block */

	__be32		agf_bno_level;	/* bnobt btree levels */
	__be32		agf_cnt_level;	/* cntbt btree levels */
	__be32		agf_rmap_level;	/* rmapbt btree levels */

	__be32		agf_flfirst;	/* first freelist block's index */
	__be32		agf_fllast;	/* last freelist block's index */
Loading