diff options
Diffstat (limited to 'fs/xfs/libxfs/xfs_ialloc_btree.c')
| -rw-r--r-- | fs/xfs/libxfs/xfs_ialloc_btree.c | 94 | 
1 files changed, 90 insertions, 4 deletions
diff --git a/fs/xfs/libxfs/xfs_ialloc_btree.c b/fs/xfs/libxfs/xfs_ialloc_btree.c index eab68ae2e011..7c471881c9a6 100644 --- a/fs/xfs/libxfs/xfs_ialloc_btree.c +++ b/fs/xfs/libxfs/xfs_ialloc_btree.c @@ -82,11 +82,12 @@ xfs_finobt_set_root(  }  STATIC int -xfs_inobt_alloc_block( +__xfs_inobt_alloc_block(  	struct xfs_btree_cur	*cur,  	union xfs_btree_ptr	*start,  	union xfs_btree_ptr	*new, -	int			*stat) +	int			*stat, +	enum xfs_ag_resv_type	resv)  {  	xfs_alloc_arg_t		args;		/* block allocation args */  	int			error;		/* error return value */ @@ -103,6 +104,7 @@ xfs_inobt_alloc_block(  	args.maxlen = 1;  	args.prod = 1;  	args.type = XFS_ALLOCTYPE_NEAR_BNO; +	args.resv = resv;  	error = xfs_alloc_vextent(&args);  	if (error) { @@ -123,6 +125,27 @@ xfs_inobt_alloc_block(  }  STATIC int +xfs_inobt_alloc_block( +	struct xfs_btree_cur	*cur, +	union xfs_btree_ptr	*start, +	union xfs_btree_ptr	*new, +	int			*stat) +{ +	return __xfs_inobt_alloc_block(cur, start, new, stat, XFS_AG_RESV_NONE); +} + +STATIC int +xfs_finobt_alloc_block( +	struct xfs_btree_cur	*cur, +	union xfs_btree_ptr	*start, +	union xfs_btree_ptr	*new, +	int			*stat) +{ +	return __xfs_inobt_alloc_block(cur, start, new, stat, +			XFS_AG_RESV_METADATA); +} + +STATIC int  xfs_inobt_free_block(  	struct xfs_btree_cur	*cur,  	struct xfs_buf		*bp) @@ -328,7 +351,7 @@ static const struct xfs_btree_ops xfs_finobt_ops = {  	.dup_cursor		= xfs_inobt_dup_cursor,  	.set_root		= xfs_finobt_set_root, -	.alloc_block		= xfs_inobt_alloc_block, +	.alloc_block		= xfs_finobt_alloc_block,  	.free_block		= xfs_inobt_free_block,  	.get_minrecs		= xfs_inobt_get_minrecs,  	.get_maxrecs		= xfs_inobt_get_maxrecs, @@ -357,7 +380,7 @@ xfs_inobt_init_cursor(  	struct xfs_agi		*agi = XFS_BUF_TO_AGI(agbp);  	struct xfs_btree_cur	*cur; -	cur = kmem_zone_zalloc(xfs_btree_cur_zone, KM_SLEEP); +	cur = kmem_zone_zalloc(xfs_btree_cur_zone, KM_NOFS);  	cur->bc_tp = tp;  	cur->bc_mp = mp; @@ -365,9 +388,11 @@ xfs_inobt_init_cursor(  	if (btnum == XFS_BTNUM_INO) {  		cur->bc_nlevels = be32_to_cpu(agi->agi_level);  		cur->bc_ops = &xfs_inobt_ops; +		cur->bc_statoff = XFS_STATS_CALC_INDEX(xs_ibt_2);  	} else {  		cur->bc_nlevels = be32_to_cpu(agi->agi_free_level);  		cur->bc_ops = &xfs_finobt_ops; +		cur->bc_statoff = XFS_STATS_CALC_INDEX(xs_fibt_2);  	}  	cur->bc_blocklog = mp->m_sb.sb_blocklog; @@ -478,3 +503,64 @@ xfs_inobt_rec_check_count(  	return 0;  }  #endif	/* DEBUG */ + +static xfs_extlen_t +xfs_inobt_max_size( +	struct xfs_mount	*mp) +{ +	/* Bail out if we're uninitialized, which can happen in mkfs. */ +	if (mp->m_inobt_mxr[0] == 0) +		return 0; + +	return xfs_btree_calc_size(mp, mp->m_inobt_mnr, +		(uint64_t)mp->m_sb.sb_agblocks * mp->m_sb.sb_inopblock / +				XFS_INODES_PER_CHUNK); +} + +static int +xfs_inobt_count_blocks( +	struct xfs_mount	*mp, +	xfs_agnumber_t		agno, +	xfs_btnum_t		btnum, +	xfs_extlen_t		*tree_blocks) +{ +	struct xfs_buf		*agbp; +	struct xfs_btree_cur	*cur; +	int			error; + +	error = xfs_ialloc_read_agi(mp, NULL, agno, &agbp); +	if (error) +		return error; + +	cur = xfs_inobt_init_cursor(mp, NULL, agbp, agno, btnum); +	error = xfs_btree_count_blocks(cur, tree_blocks); +	xfs_btree_del_cursor(cur, error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR); +	xfs_buf_relse(agbp); + +	return error; +} + +/* + * Figure out how many blocks to reserve and how many are used by this btree. + */ +int +xfs_finobt_calc_reserves( +	struct xfs_mount	*mp, +	xfs_agnumber_t		agno, +	xfs_extlen_t		*ask, +	xfs_extlen_t		*used) +{ +	xfs_extlen_t		tree_len = 0; +	int			error; + +	if (!xfs_sb_version_hasfinobt(&mp->m_sb)) +		return 0; + +	error = xfs_inobt_count_blocks(mp, agno, XFS_BTNUM_FINO, &tree_len); +	if (error) +		return error; + +	*ask += xfs_inobt_max_size(mp); +	*used += tree_len; +	return 0; +}  |