diff options
Diffstat (limited to 'fs/xfs/xfs_alloc_btree.c')
| -rw-r--r-- | fs/xfs/xfs_alloc_btree.c | 179 | 
1 files changed, 22 insertions, 157 deletions
diff --git a/fs/xfs/xfs_alloc_btree.c b/fs/xfs/xfs_alloc_btree.c index 8a8d1aeec52..f21a3e9cc3d 100644 --- a/fs/xfs/xfs_alloc_btree.c +++ b/fs/xfs/xfs_alloc_btree.c @@ -48,7 +48,6 @@ STATIC void xfs_alloc_log_block(xfs_trans_t *, xfs_buf_t *, int);  STATIC void xfs_alloc_log_keys(xfs_btree_cur_t *, xfs_buf_t *, int, int);  STATIC void xfs_alloc_log_ptrs(xfs_btree_cur_t *, xfs_buf_t *, int, int);  STATIC void xfs_alloc_log_recs(xfs_btree_cur_t *, xfs_buf_t *, int, int); -STATIC int xfs_alloc_newroot(xfs_btree_cur_t *, int *);  /*   * Internal functions. @@ -628,7 +627,7 @@ xfs_alloc_insrec(  	 */  	if (level >= cur->bc_nlevels) {  		XFS_STATS_INC(xs_abt_insrec); -		if ((error = xfs_alloc_newroot(cur, &i))) +		if ((error = xfs_btree_new_root(cur, &i)))  			return error;  		*bnop = NULLAGBLOCK;  		*stat = i; @@ -936,161 +935,6 @@ xfs_alloc_log_recs(  	xfs_trans_log_buf(cur->bc_tp, bp, first, last);  } -/* - * Allocate a new root block, fill it in. - */ -STATIC int				/* error */ -xfs_alloc_newroot( -	xfs_btree_cur_t		*cur,	/* btree cursor */ -	int			*stat)	/* success/failure */ -{ -	int			error;	/* error return value */ -	xfs_agblock_t		lbno;	/* left block number */ -	xfs_buf_t		*lbp;	/* left btree buffer */ -	xfs_alloc_block_t	*left;	/* left btree block */ -	xfs_mount_t		*mp;	/* mount structure */ -	xfs_agblock_t		nbno;	/* new block number */ -	xfs_buf_t		*nbp;	/* new (root) buffer */ -	xfs_alloc_block_t	*new;	/* new (root) btree block */ -	int			nptr;	/* new value for key index, 1 or 2 */ -	xfs_agblock_t		rbno;	/* right block number */ -	xfs_buf_t		*rbp;	/* right btree buffer */ -	xfs_alloc_block_t	*right;	/* right btree block */ - -	mp = cur->bc_mp; - -	ASSERT(cur->bc_nlevels < XFS_AG_MAXLEVELS(mp)); -	/* -	 * Get a buffer from the freelist blocks, for the new root. -	 */ -	error = xfs_alloc_get_freelist(cur->bc_tp, -					cur->bc_private.a.agbp, &nbno, 1); -	if (error) -		return error; -	/* -	 * None available, we fail. -	 */ -	if (nbno == NULLAGBLOCK) { -		*stat = 0; -		return 0; -	} -	xfs_trans_agbtree_delta(cur->bc_tp, 1); -	nbp = xfs_btree_get_bufs(mp, cur->bc_tp, cur->bc_private.a.agno, nbno, -		0); -	new = XFS_BUF_TO_ALLOC_BLOCK(nbp); -	/* -	 * Set the root data in the a.g. freespace structure. -	 */ -	{ -		xfs_agf_t	*agf;	/* a.g. freespace header */ -		xfs_agnumber_t	seqno; - -		agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp); -		agf->agf_roots[cur->bc_btnum] = cpu_to_be32(nbno); -		be32_add_cpu(&agf->agf_levels[cur->bc_btnum], 1); -		seqno = be32_to_cpu(agf->agf_seqno); -		mp->m_perag[seqno].pagf_levels[cur->bc_btnum]++; -		xfs_alloc_log_agf(cur->bc_tp, cur->bc_private.a.agbp, -			XFS_AGF_ROOTS | XFS_AGF_LEVELS); -	} -	/* -	 * At the previous root level there are now two blocks: the old -	 * root, and the new block generated when it was split. -	 * We don't know which one the cursor is pointing at, so we -	 * set up variables "left" and "right" for each case. -	 */ -	lbp = cur->bc_bufs[cur->bc_nlevels - 1]; -	left = XFS_BUF_TO_ALLOC_BLOCK(lbp); -#ifdef DEBUG -	if ((error = xfs_btree_check_sblock(cur, left, cur->bc_nlevels - 1, lbp))) -		return error; -#endif -	if (be32_to_cpu(left->bb_rightsib) != NULLAGBLOCK) { -		/* -		 * Our block is left, pick up the right block. -		 */ -		lbno = XFS_DADDR_TO_AGBNO(mp, XFS_BUF_ADDR(lbp)); -		rbno = be32_to_cpu(left->bb_rightsib); -		if ((error = xfs_btree_read_bufs(mp, cur->bc_tp, -				cur->bc_private.a.agno, rbno, 0, &rbp, -				XFS_ALLOC_BTREE_REF))) -			return error; -		right = XFS_BUF_TO_ALLOC_BLOCK(rbp); -		if ((error = xfs_btree_check_sblock(cur, right, -				cur->bc_nlevels - 1, rbp))) -			return error; -		nptr = 1; -	} else { -		/* -		 * Our block is right, pick up the left block. -		 */ -		rbp = lbp; -		right = left; -		rbno = XFS_DADDR_TO_AGBNO(mp, XFS_BUF_ADDR(rbp)); -		lbno = be32_to_cpu(right->bb_leftsib); -		if ((error = xfs_btree_read_bufs(mp, cur->bc_tp, -				cur->bc_private.a.agno, lbno, 0, &lbp, -				XFS_ALLOC_BTREE_REF))) -			return error; -		left = XFS_BUF_TO_ALLOC_BLOCK(lbp); -		if ((error = xfs_btree_check_sblock(cur, left, -				cur->bc_nlevels - 1, lbp))) -			return error; -		nptr = 2; -	} -	/* -	 * Fill in the new block's btree header and log it. -	 */ -	new->bb_magic = cpu_to_be32(xfs_magics[cur->bc_btnum]); -	new->bb_level = cpu_to_be16(cur->bc_nlevels); -	new->bb_numrecs = cpu_to_be16(2); -	new->bb_leftsib = cpu_to_be32(NULLAGBLOCK); -	new->bb_rightsib = cpu_to_be32(NULLAGBLOCK); -	xfs_alloc_log_block(cur->bc_tp, nbp, XFS_BB_ALL_BITS); -	ASSERT(lbno != NULLAGBLOCK && rbno != NULLAGBLOCK); -	/* -	 * Fill in the key data in the new root. -	 */ -	{ -		xfs_alloc_key_t		*kp;	/* btree key pointer */ - -		kp = XFS_ALLOC_KEY_ADDR(new, 1, cur); -		if (be16_to_cpu(left->bb_level) > 0) { -			kp[0] = *XFS_ALLOC_KEY_ADDR(left, 1, cur); -			kp[1] = *XFS_ALLOC_KEY_ADDR(right, 1, cur); -		} else { -			xfs_alloc_rec_t	*rp;	/* btree record pointer */ - -			rp = XFS_ALLOC_REC_ADDR(left, 1, cur); -			kp[0].ar_startblock = rp->ar_startblock; -			kp[0].ar_blockcount = rp->ar_blockcount; -			rp = XFS_ALLOC_REC_ADDR(right, 1, cur); -			kp[1].ar_startblock = rp->ar_startblock; -			kp[1].ar_blockcount = rp->ar_blockcount; -		} -	} -	xfs_alloc_log_keys(cur, nbp, 1, 2); -	/* -	 * Fill in the pointer data in the new root. -	 */ -	{ -		xfs_alloc_ptr_t		*pp;	/* btree address pointer */ - -		pp = XFS_ALLOC_PTR_ADDR(new, 1, cur); -		pp[0] = cpu_to_be32(lbno); -		pp[1] = cpu_to_be32(rbno); -	} -	xfs_alloc_log_ptrs(cur, nbp, 1, 2); -	/* -	 * Fix up the cursor. -	 */ -	xfs_btree_setbuf(cur, cur->bc_nlevels, nbp); -	cur->bc_ptrs[cur->bc_nlevels] = nptr; -	cur->bc_nlevels++; -	*stat = 1; -	return 0; -} -  /*   * Externally visible routines. @@ -1244,6 +1088,26 @@ xfs_allocbt_dup_cursor(  			cur->bc_btnum);  } +STATIC void +xfs_allocbt_set_root( +	struct xfs_btree_cur	*cur, +	union xfs_btree_ptr	*ptr, +	int			inc) +{ +	struct xfs_buf		*agbp = cur->bc_private.a.agbp; +	struct xfs_agf		*agf = XFS_BUF_TO_AGF(agbp); +	xfs_agnumber_t		seqno = be32_to_cpu(agf->agf_seqno); +	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_mp->m_perag[seqno].pagf_levels[btnum] += inc; + +	xfs_alloc_log_agf(cur->bc_tp, agbp, XFS_AGF_ROOTS | XFS_AGF_LEVELS); +} +  STATIC int  xfs_allocbt_alloc_block(  	struct xfs_btree_cur	*cur, @@ -1440,6 +1304,7 @@ static const struct xfs_btree_ops xfs_allocbt_ops = {  	.key_len		= sizeof(xfs_alloc_key_t),  	.dup_cursor		= xfs_allocbt_dup_cursor, +	.set_root		= xfs_allocbt_set_root,  	.alloc_block		= xfs_allocbt_alloc_block,  	.update_lastrec		= xfs_allocbt_update_lastrec,  	.get_maxrecs		= xfs_allocbt_get_maxrecs,  |