diff options
| author | Christoph Hellwig <hch@infradead.org> | 2008-10-30 16:56:32 +1100 | 
|---|---|---|
| committer | Lachlan McIlroy <lachlan@sgi.com> | 2008-10-30 16:56:32 +1100 | 
| commit | 278d0ca14e889c3932a05d1a68675252a12b3466 (patch) | |
| tree | a228d171d4aded60b27639e30eca1bf58ed7daa6 /fs/xfs/xfs_alloc_btree.c | |
| parent | 38bb74237d2d94c1aced2ec626d7d0f317e360da (diff) | |
| download | olio-linux-3.10-278d0ca14e889c3932a05d1a68675252a12b3466.tar.xz olio-linux-3.10-278d0ca14e889c3932a05d1a68675252a12b3466.zip  | |
[XFS] implement generic xfs_btree_update
From: Dave Chinner <dgc@sgi.com>
The most complicated part here is the lastrec tracking for the alloc
btree. Most logic is in the update_lastrec method which has to do some
hopefully good enough dirty magic to maintain it.
[hch: split out from bigger patch and a rework of the lastrec
logic]
SGI-PV: 985583
SGI-Modid: xfs-linux-melb:xfs-kern:32194a
Signed-off-by: Christoph Hellwig <hch@infradead.org>
Signed-off-by: Lachlan McIlroy <lachlan@sgi.com>
Signed-off-by: Bill O'Donnell <billodo@sgi.com>
Signed-off-by: David Chinner <david@fromorbit.com>
Diffstat (limited to 'fs/xfs/xfs_alloc_btree.c')
| -rw-r--r-- | fs/xfs/xfs_alloc_btree.c | 106 | 
1 files changed, 38 insertions, 68 deletions
diff --git a/fs/xfs/xfs_alloc_btree.c b/fs/xfs/xfs_alloc_btree.c index 28c6a698f56..c5c32999b81 100644 --- a/fs/xfs/xfs_alloc_btree.c +++ b/fs/xfs/xfs_alloc_btree.c @@ -1661,83 +1661,50 @@ xfs_alloc_insert(  	return 0;  } +STATIC struct xfs_btree_cur * +xfs_allocbt_dup_cursor( +	struct xfs_btree_cur	*cur) +{ +	return xfs_allocbt_init_cursor(cur->bc_mp, cur->bc_tp, +			cur->bc_private.a.agbp, cur->bc_private.a.agno, +			cur->bc_btnum); +} +  /* - * Update the record referred to by cur, to the value given by [bno, len]. - * This either works (return 0) or gets an EFSCORRUPTED error. + * Update the longest extent in the AGF   */ -int					/* error */ -xfs_alloc_update( -	xfs_btree_cur_t		*cur,	/* btree cursor */ -	xfs_agblock_t		bno,	/* starting block of extent */ -	xfs_extlen_t		len)	/* length of extent */ +STATIC void +xfs_allocbt_update_lastrec( +	struct xfs_btree_cur	*cur, +	struct xfs_btree_block	*block, +	union xfs_btree_rec	*rec, +	int			ptr, +	int			reason)  { -	xfs_alloc_block_t	*block;	/* btree block to update */ -	int			error;	/* error return value */ -	int			ptr;	/* current record number (updating) */ +	struct xfs_agf		*agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp); +	xfs_agnumber_t		seqno = be32_to_cpu(agf->agf_seqno); +	__be32			len; -	ASSERT(len > 0); -	/* -	 * Pick up the a.g. freelist struct and the current block. -	 */ -	block = XFS_BUF_TO_ALLOC_BLOCK(cur->bc_bufs[0]); -#ifdef DEBUG -	if ((error = xfs_btree_check_sblock(cur, block, 0, cur->bc_bufs[0]))) -		return error; -#endif -	/* -	 * Get the address of the rec to be updated. -	 */ -	ptr = cur->bc_ptrs[0]; -	{ -		xfs_alloc_rec_t		*rp;	/* pointer to updated record */ +	ASSERT(cur->bc_btnum == XFS_BTNUM_CNT); -		rp = XFS_ALLOC_REC_ADDR(block, ptr, cur); +	switch (reason) { +	case LASTREC_UPDATE:  		/* -		 * Fill in the new contents and log them. +		 * If this is the last leaf block and it's the last record, +		 * then update the size of the longest extent in the AG.  		 */ -		rp->ar_startblock = cpu_to_be32(bno); -		rp->ar_blockcount = cpu_to_be32(len); -		xfs_alloc_log_recs(cur, cur->bc_bufs[0], ptr, ptr); -	} -	/* -	 * If it's the by-size btree and it's the last leaf block and -	 * it's the last record... then update the size of the longest -	 * extent in the a.g., which we cache in the a.g. freelist header. -	 */ -	if (cur->bc_btnum == XFS_BTNUM_CNT && -	    be32_to_cpu(block->bb_rightsib) == NULLAGBLOCK && -	    ptr == be16_to_cpu(block->bb_numrecs)) { -		xfs_agf_t	*agf;	/* a.g. freespace header */ -		xfs_agnumber_t	seqno; - -		agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp); -		seqno = be32_to_cpu(agf->agf_seqno); -		cur->bc_mp->m_perag[seqno].pagf_longest = len; -		agf->agf_longest = cpu_to_be32(len); -		xfs_alloc_log_agf(cur->bc_tp, cur->bc_private.a.agbp, -			XFS_AGF_LONGEST); -	} -	/* -	 * Updating first record in leaf. Pass new key value up to our parent. -	 */ -	if (ptr == 1) { -		xfs_alloc_key_t	key;	/* key containing [bno, len] */ - -		key.ar_startblock = cpu_to_be32(bno); -		key.ar_blockcount = cpu_to_be32(len); -		if ((error = xfs_btree_updkey(cur, (union xfs_btree_key *)&key, 1))) -			return error; +		if (ptr != xfs_btree_get_numrecs(block)) +			return; +		len = rec->alloc.ar_blockcount; +		break; +	default: +		ASSERT(0); +		return;  	} -	return 0; -} -STATIC struct xfs_btree_cur * -xfs_allocbt_dup_cursor( -	struct xfs_btree_cur	*cur) -{ -	return xfs_allocbt_init_cursor(cur->bc_mp, cur->bc_tp, -			cur->bc_private.a.agbp, cur->bc_private.a.agno, -			cur->bc_btnum); +	agf->agf_longest = len; +	cur->bc_mp->m_perag[seqno].pagf_longest = be32_to_cpu(len); +	xfs_alloc_log_agf(cur->bc_tp, cur->bc_private.a.agbp, XFS_AGF_LONGEST);  }  STATIC int @@ -1864,6 +1831,7 @@ static const struct xfs_btree_ops xfs_allocbt_ops = {  	.key_len		= sizeof(xfs_alloc_key_t),  	.dup_cursor		= xfs_allocbt_dup_cursor, +	.update_lastrec		= xfs_allocbt_update_lastrec,  	.get_maxrecs		= xfs_allocbt_get_maxrecs,  	.init_key_from_rec	= xfs_allocbt_init_key_from_rec,  	.init_ptr_from_cur	= xfs_allocbt_init_ptr_from_cur, @@ -1902,6 +1870,8 @@ xfs_allocbt_init_cursor(  	cur->bc_blocklog = mp->m_sb.sb_blocklog;  	cur->bc_ops = &xfs_allocbt_ops; +	if (btnum == XFS_BTNUM_CNT) +		cur->bc_flags = XFS_BTREE_LASTREC_UPDATE;  	cur->bc_private.a.agbp = agbp;  	cur->bc_private.a.agno = agno;  |