diff options
Diffstat (limited to 'fs/xfs/libxfs/xfs_ialloc_btree.c')
| -rw-r--r-- | fs/xfs/libxfs/xfs_ialloc_btree.c | 90 | 
1 files changed, 87 insertions, 3 deletions
| diff --git a/fs/xfs/libxfs/xfs_ialloc_btree.c b/fs/xfs/libxfs/xfs_ialloc_btree.c index 0fd086d03d41..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, @@ -480,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; +} |