diff mbox series

[4/7] xfs: Add "Use Dir BMBT height" argument to XFS_BM_MAXLEVELS()

Message ID 20200606082745.15174-5-chandanrlinux@gmail.com (mailing list archive)
State New, archived
Headers show
Series xfs: Extend per-inode extent counters. | expand

Commit Message

Chandan Babu R June 6, 2020, 8:27 a.m. UTC
XFS_BM_MAXLEVELS() returns the maximum possible height of BMBT tree for
either data or attribute fork. For data forks, this commit adds a new
argument to XFS_BM_MAXLEVELS() to let the users choose between the
maximum heights of dir and non-dir BMBTs.

As of this commit, both dir and non-dir BMBTs have the same maximum
height. A future commit in this series will use 2^27 extent count as the
input to compute the maximum height of a directory BMBT which will in
turn cause the maximum heights of dir and non-dir BMBTs to differ.

Signed-off-by: Chandan Babu R <chandanrlinux@gmail.com>
---
 fs/xfs/libxfs/xfs_attr.c        |  5 ++--
 fs/xfs/libxfs/xfs_bmap.c        |  5 ++--
 fs/xfs/libxfs/xfs_bmap_btree.h  |  4 +++-
 fs/xfs/libxfs/xfs_trans_resv.c  | 25 +++++++++++---------
 fs/xfs/libxfs/xfs_trans_resv.h  |  4 ++--
 fs/xfs/libxfs/xfs_trans_space.h | 41 +++++++++++++++++----------------
 fs/xfs/xfs_bmap_item.c          |  3 ++-
 fs/xfs/xfs_reflink.c            |  4 ++--
 8 files changed, 50 insertions(+), 41 deletions(-)

Comments

Darrick J. Wong June 8, 2020, 5:50 p.m. UTC | #1
On Sat, Jun 06, 2020 at 01:57:42PM +0530, Chandan Babu R wrote:
> XFS_BM_MAXLEVELS() returns the maximum possible height of BMBT tree for
> either data or attribute fork. For data forks, this commit adds a new
> argument to XFS_BM_MAXLEVELS() to let the users choose between the
> maximum heights of dir and non-dir BMBTs.
> 
> As of this commit, both dir and non-dir BMBTs have the same maximum
> height. A future commit in this series will use 2^27 extent count as the
> input to compute the maximum height of a directory BMBT which will in
> turn cause the maximum heights of dir and non-dir BMBTs to differ.
> 
> Signed-off-by: Chandan Babu R <chandanrlinux@gmail.com>
> ---
>  fs/xfs/libxfs/xfs_attr.c        |  5 ++--
>  fs/xfs/libxfs/xfs_bmap.c        |  5 ++--
>  fs/xfs/libxfs/xfs_bmap_btree.h  |  4 +++-
>  fs/xfs/libxfs/xfs_trans_resv.c  | 25 +++++++++++---------
>  fs/xfs/libxfs/xfs_trans_resv.h  |  4 ++--
>  fs/xfs/libxfs/xfs_trans_space.h | 41 +++++++++++++++++----------------
>  fs/xfs/xfs_bmap_item.c          |  3 ++-
>  fs/xfs/xfs_reflink.c            |  4 ++--
>  8 files changed, 50 insertions(+), 41 deletions(-)
> 
> diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c
> index a4b23edf887e..357e29a5a167 100644
> --- a/fs/xfs/libxfs/xfs_attr.c
> +++ b/fs/xfs/libxfs/xfs_attr.c
> @@ -150,7 +150,7 @@ xfs_attr_calc_size(
>  	 * "local" or "remote" (note: local != inline).
>  	 */
>  	size = xfs_attr_leaf_newentsize(args, local);
> -	nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK);
> +	nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK, 0);

When would we have a DAENTER space reservation for the data fork on
something that isn't a directory?

Shouldn't you be able to compute the correct 'dbmbt' parameter value
from whichfork?

Can you modify these macros to take the xfs_inode so that we can gate
the logic on i_mode instead of passing magic values 0 and 1 around?
Though... thinking about this more, 1 means "use the slightly smaller
directory bmbt maxlevels", and 0 means "either this is a non directory
or we want worst case calculations", doesn't it...

Zooming out, why do we even care?  While it's true that we might gain
the ability to shave a few blocks off the block reservation when we know
we're dealing with a directory, this adds quite a bit of clutter to get
it.

>  	if (*local) {
>  		if (size > (args->geo->blksize / 2)) {
>  			/* Double split possible */
> @@ -163,7 +163,8 @@ xfs_attr_calc_size(
>  		 */
>  		uint	dblocks = xfs_attr3_rmt_blocks(mp, args->valuelen);
>  		nblks += dblocks;
> -		nblks += XFS_NEXTENTADD_SPACE_RES(mp, dblocks, XFS_ATTR_FORK);
> +		nblks += XFS_NEXTENTADD_SPACE_RES(mp, dblocks,
> +				XFS_ATTR_FORK, 0);
>  	}
>  
>  	return nblks;
> diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
> index 01e2b543b139..8b0029b3cecf 100644
> --- a/fs/xfs/libxfs/xfs_bmap.c
> +++ b/fs/xfs/libxfs/xfs_bmap.c
> @@ -182,13 +182,14 @@ xfs_bmap_worst_indlen(
>  	mp = ip->i_mount;
>  	maxrecs = mp->m_bmap_dmxr[0];
>  	for (level = 0, rval = 0;
> -	     level < XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK);
> +	     level < XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK, 0);
>  	     level++) {
>  		len += maxrecs - 1;
>  		do_div(len, maxrecs);
>  		rval += len;
>  		if (len == 1)
> -			return rval + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) -
> +			return rval +
> +				XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK, 0) -
>  				level - 1;
>  		if (level == 0)
>  			maxrecs = mp->m_bmap_dmxr[1];
> diff --git a/fs/xfs/libxfs/xfs_bmap_btree.h b/fs/xfs/libxfs/xfs_bmap_btree.h
> index 72bf74c79fb9..a047be5883d1 100644
> --- a/fs/xfs/libxfs/xfs_bmap_btree.h
> +++ b/fs/xfs/libxfs/xfs_bmap_btree.h
> @@ -79,7 +79,9 @@ struct xfs_trans;
>  /*
>   * Maximum number of bmap btree levels.
>   */
> -#define XFS_BM_MAXLEVELS(mp,w)		((mp)->m_bm_maxlevels[(w)])
> +#define XFS_BM_MAXLEVELS(mp,w,use_dir_bmbt) \
> +	((!(use_dir_bmbt)) ? \
> +		(mp)->m_bm_maxlevels[(w)] : (mp)->m_bm_dir_maxlevel)

Also, if you /are/ going to mess with these macros, can you please turn
them into static inline functions?  Typechecking would be nice.

--D

>  /*
>   * Prototypes for xfs_bmap.c to call.
> diff --git a/fs/xfs/libxfs/xfs_trans_resv.c b/fs/xfs/libxfs/xfs_trans_resv.c
> index b44b521c605c..39cfca1b71b6 100644
> --- a/fs/xfs/libxfs/xfs_trans_resv.c
> +++ b/fs/xfs/libxfs/xfs_trans_resv.c
> @@ -265,14 +265,14 @@ xfs_calc_write_reservation(
>  	unsigned int		blksz = XFS_FSB_TO_B(mp, 1);
>  
>  	t1 = xfs_calc_inode_res(mp, 1) +
> -	     xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK), blksz) +
> +	     xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK, 0), blksz) +
>  	     xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) +
>  	     xfs_calc_buf_res(xfs_allocfree_log_count(mp, 2), blksz);
>  
>  	if (xfs_sb_version_hasrealtime(&mp->m_sb)) {
>  		t2 = xfs_calc_inode_res(mp, 1) +
> -		     xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK),
> -				     blksz) +
> +		     xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK, 0),
> +			blksz) +
>  		     xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) +
>  		     xfs_calc_buf_res(xfs_rtalloc_log_count(mp, 1), blksz) +
>  		     xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1), blksz);
> @@ -313,7 +313,8 @@ xfs_calc_itruncate_reservation(
>  	unsigned int		blksz = XFS_FSB_TO_B(mp, 1);
>  
>  	t1 = xfs_calc_inode_res(mp, 1) +
> -	     xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) + 1, blksz);
> +	     xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK, 0) + 1,
> +			     blksz);
>  
>  	t2 = xfs_calc_buf_res(9, mp->m_sb.sb_sectsize) +
>  	     xfs_calc_buf_res(xfs_allocfree_log_count(mp, 4), blksz);
> @@ -592,7 +593,7 @@ xfs_calc_growrtalloc_reservation(
>  	struct xfs_mount	*mp)
>  {
>  	return xfs_calc_buf_res(2, mp->m_sb.sb_sectsize) +
> -		xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK),
> +		xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK, 0),
>  				 XFS_FSB_TO_B(mp, 1)) +
>  		xfs_calc_inode_res(mp, 1) +
>  		xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1),
> @@ -669,7 +670,7 @@ xfs_calc_addafork_reservation(
>  		xfs_calc_inode_res(mp, 1) +
>  		xfs_calc_buf_res(2, mp->m_sb.sb_sectsize) +
>  		xfs_calc_buf_res(1, mp->m_dir_geo->blksize) +
> -		xfs_calc_buf_res(XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1,
> +		xfs_calc_buf_res(XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK, 0) + 1,
>  				 XFS_FSB_TO_B(mp, 1)) +
>  		xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1),
>  				 XFS_FSB_TO_B(mp, 1));
> @@ -691,7 +692,7 @@ xfs_calc_attrinval_reservation(
>  	struct xfs_mount	*mp)
>  {
>  	return max((xfs_calc_inode_res(mp, 1) +
> -		    xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK),
> +		    xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK, 0),
>  				     XFS_FSB_TO_B(mp, 1))),
>  		   (xfs_calc_buf_res(9, mp->m_sb.sb_sectsize) +
>  		    xfs_calc_buf_res(xfs_allocfree_log_count(mp, 4),
> @@ -717,10 +718,11 @@ xfs_calc_attrset_reservation(
>  	int			bmbt_blks;
>  
>  	da_blks = XFS_DAENTER_BLOCKS(mp, XFS_ATTR_FORK);
> -	bmbt_blks = XFS_DAENTER_BMAPS(mp, XFS_ATTR_FORK);
> +	bmbt_blks = XFS_DAENTER_BMAPS(mp, XFS_ATTR_FORK, 0);
>  
>  	max_rmt_blks = xfs_attr3_rmt_blocks(mp, XATTR_SIZE_MAX);
> -	bmbt_blks += XFS_NEXTENTADD_SPACE_RES(mp, max_rmt_blks, XFS_ATTR_FORK);
> +	bmbt_blks += XFS_NEXTENTADD_SPACE_RES(mp, max_rmt_blks,
> +			XFS_ATTR_FORK, 0);
>  
>  	return XFS_DQUOT_LOGRES(mp) +
>  		xfs_calc_inode_res(mp, 1) +
> @@ -752,8 +754,9 @@ xfs_calc_attrrm_reservation(
>  		     xfs_calc_buf_res(XFS_DA_NODE_MAXDEPTH,
>  				      XFS_FSB_TO_B(mp, 1)) +
>  		     (uint)XFS_FSB_TO_B(mp,
> -					XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK)) +
> -		     xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK), 0)),
> +				XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK, 0)) +
> +		     xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK, 0),
> +				     0)),
>  		    (xfs_calc_buf_res(5, mp->m_sb.sb_sectsize) +
>  		     xfs_calc_buf_res(xfs_allocfree_log_count(mp, 2),
>  				      XFS_FSB_TO_B(mp, 1))));
> diff --git a/fs/xfs/libxfs/xfs_trans_resv.h b/fs/xfs/libxfs/xfs_trans_resv.h
> index f50996ae18e6..d64989eeebd7 100644
> --- a/fs/xfs/libxfs/xfs_trans_resv.h
> +++ b/fs/xfs/libxfs/xfs_trans_resv.h
> @@ -61,10 +61,10 @@ struct xfs_trans_resv {
>   */
>  #define	XFS_DIROP_LOG_RES(mp)	\
>  	(XFS_FSB_TO_B(mp, XFS_DAENTER_BLOCKS(mp, XFS_DATA_FORK)) + \
> -	 (XFS_FSB_TO_B(mp, XFS_DAENTER_BMAPS(mp, XFS_DATA_FORK) + 1)))
> +	 (XFS_FSB_TO_B(mp, XFS_DAENTER_BMAPS(mp, XFS_DATA_FORK, 1) + 1)))
>  #define	XFS_DIROP_LOG_COUNT(mp)	\
>  	(XFS_DAENTER_BLOCKS(mp, XFS_DATA_FORK) + \
> -	 XFS_DAENTER_BMAPS(mp, XFS_DATA_FORK) + 1)
> +	 XFS_DAENTER_BMAPS(mp, XFS_DATA_FORK, 1) + 1)
>  
>  /*
>   * Various log count values.
> diff --git a/fs/xfs/libxfs/xfs_trans_space.h b/fs/xfs/libxfs/xfs_trans_space.h
> index b559af70cf51..c51d809a16b1 100644
> --- a/fs/xfs/libxfs/xfs_trans_space.h
> +++ b/fs/xfs/libxfs/xfs_trans_space.h
> @@ -25,15 +25,16 @@
>  
>  #define XFS_MAX_CONTIG_EXTENTS_PER_BLOCK(mp)    \
>  		(((mp)->m_alloc_mxr[0]) - ((mp)->m_alloc_mnr[0]))
> -#define	XFS_EXTENTADD_SPACE_RES(mp,w)	(XFS_BM_MAXLEVELS(mp,w) - 1)
> -#define XFS_NEXTENTADD_SPACE_RES(mp,b,w)\
> +#define	XFS_EXTENTADD_SPACE_RES(mp,w,dbmbt)	\
> +	(XFS_BM_MAXLEVELS(mp,w,dbmbt) - 1)
> +#define XFS_NEXTENTADD_SPACE_RES(mp,b,w,dbmbt)		   \
>  	(((b + XFS_MAX_CONTIG_EXTENTS_PER_BLOCK(mp) - 1) / \
>  	  XFS_MAX_CONTIG_EXTENTS_PER_BLOCK(mp)) * \
> -	  XFS_EXTENTADD_SPACE_RES(mp,w))
> +		XFS_EXTENTADD_SPACE_RES(mp,w,dbmbt))
>  
>  /* Blocks we might need to add "b" mappings & rmappings to a file. */
> -#define XFS_SWAP_RMAP_SPACE_RES(mp,b,w)\
> -	(XFS_NEXTENTADD_SPACE_RES((mp), (b), (w)) + \
> +#define XFS_SWAP_RMAP_SPACE_RES(mp,b,w)	    \
> +	(XFS_NEXTENTADD_SPACE_RES((mp), (b), (w), 0) +	\
>  	 XFS_NRMAPADD_SPACE_RES((mp), (b)))
>  
>  #define	XFS_DAENTER_1B(mp,w)	\
> @@ -47,19 +48,19 @@
>  	(XFS_DA_NODE_MAXDEPTH + (((w) == XFS_DATA_FORK) ? 2 : 1))
>  #define	XFS_DAENTER_BLOCKS(mp,w)	\
>  	(XFS_DAENTER_1B(mp,w) * XFS_DAENTER_DBS(mp,w))
> -#define	XFS_DAENTER_BMAP1B(mp,w)	\
> -	XFS_NEXTENTADD_SPACE_RES(mp, XFS_DAENTER_1B(mp, w), w)
> -#define	XFS_DAENTER_BMAPS(mp,w)		\
> -	(XFS_DAENTER_DBS(mp,w) * XFS_DAENTER_BMAP1B(mp,w))
> -#define	XFS_DAENTER_SPACE_RES(mp,w)	\
> -	(XFS_DAENTER_BLOCKS(mp,w) + XFS_DAENTER_BMAPS(mp,w))
> -#define	XFS_DAREMOVE_SPACE_RES(mp,w)	XFS_DAENTER_BMAPS(mp,w)
> +#define	XFS_DAENTER_BMAP1B(mp,w,dbmbt)	\
> +	XFS_NEXTENTADD_SPACE_RES(mp, XFS_DAENTER_1B(mp, w), w, dbmbt)
> +#define	XFS_DAENTER_BMAPS(mp,w,dbmbt)	\
> +	(XFS_DAENTER_DBS(mp,w) * XFS_DAENTER_BMAP1B(mp,w,dbmbt))
> +#define	XFS_DAENTER_SPACE_RES(mp,w,dbmbt)	\
> +	(XFS_DAENTER_BLOCKS(mp,w) + XFS_DAENTER_BMAPS(mp,w,dbmbt))
> +#define	XFS_DAREMOVE_SPACE_RES(mp,w,dbmbt)	XFS_DAENTER_BMAPS(mp,w,dbmbt)
>  #define	XFS_DIRENTER_MAX_SPLIT(mp,nl)	1
>  #define	XFS_DIRENTER_SPACE_RES(mp,nl)	\
> -	(XFS_DAENTER_SPACE_RES(mp, XFS_DATA_FORK) * \
> +	(XFS_DAENTER_SPACE_RES(mp, XFS_DATA_FORK, 1) *	\
>  	 XFS_DIRENTER_MAX_SPLIT(mp,nl))
>  #define	XFS_DIRREMOVE_SPACE_RES(mp)	\
> -	XFS_DAREMOVE_SPACE_RES(mp, XFS_DATA_FORK)
> +	XFS_DAREMOVE_SPACE_RES(mp, XFS_DATA_FORK, 1)
>  #define	XFS_IALLOC_SPACE_RES(mp)	\
>  	(M_IGEO(mp)->ialloc_blks + \
>  	 (xfs_sb_version_hasfinobt(&mp->m_sb) ? 2 : 1 * \
> @@ -69,26 +70,26 @@
>   * Space reservation values for various transactions.
>   */
>  #define	XFS_ADDAFORK_SPACE_RES(mp)	\
> -	((mp)->m_dir_geo->fsbcount + XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK))
> +	((mp)->m_dir_geo->fsbcount + XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK, 0))
>  #define	XFS_ATTRRM_SPACE_RES(mp)	\
> -	XFS_DAREMOVE_SPACE_RES(mp, XFS_ATTR_FORK)
> +	XFS_DAREMOVE_SPACE_RES(mp, XFS_ATTR_FORK, 0)
>  /* This macro is not used - see inline code in xfs_attr_set */
>  #define	XFS_ATTRSET_SPACE_RES(mp, v)	\
> -	(XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK) + XFS_B_TO_FSB(mp, v))
> +	(XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK, 0) + XFS_B_TO_FSB(mp, v))
>  #define	XFS_CREATE_SPACE_RES(mp,nl)	\
>  	(XFS_IALLOC_SPACE_RES(mp) + XFS_DIRENTER_SPACE_RES(mp,nl))
>  #define	XFS_DIOSTRAT_SPACE_RES(mp, v)	\
> -	(XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK) + (v))
> +	(XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK, 0) + (v))
>  #define	XFS_GROWFS_SPACE_RES(mp)	\
>  	(2 * (mp)->m_ag_maxlevels)
>  #define	XFS_GROWFSRT_SPACE_RES(mp,b)	\
> -	((b) + XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK))
> +	((b) + XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK, 0))
>  #define	XFS_LINK_SPACE_RES(mp,nl)	\
>  	XFS_DIRENTER_SPACE_RES(mp,nl)
>  #define	XFS_MKDIR_SPACE_RES(mp,nl)	\
>  	(XFS_IALLOC_SPACE_RES(mp) + XFS_DIRENTER_SPACE_RES(mp,nl))
>  #define	XFS_QM_DQALLOC_SPACE_RES(mp)	\
> -	(XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK) + \
> +	(XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK, 0) + \
>  	 XFS_DQUOT_CLUSTER_SIZE_FSB)
>  #define	XFS_QM_QINOCREATE_SPACE_RES(mp)	\
>  	XFS_IALLOC_SPACE_RES(mp)
> diff --git a/fs/xfs/xfs_bmap_item.c b/fs/xfs/xfs_bmap_item.c
> index 6736c5ab188f..0a8a8377a150 100644
> --- a/fs/xfs/xfs_bmap_item.c
> +++ b/fs/xfs/xfs_bmap_item.c
> @@ -482,7 +482,8 @@ xfs_bui_item_recover(
>  	}
>  
>  	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate,
> -			XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK), 0, 0, &tp);
> +			XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK, 0), 0,
> +			0, &tp);
>  	if (error)
>  		return error;
>  	/*
> diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c
> index 107bf2a2f344..fd35a0bf2c47 100644
> --- a/fs/xfs/xfs_reflink.c
> +++ b/fs/xfs/xfs_reflink.c
> @@ -614,7 +614,7 @@ xfs_reflink_end_cow_extent(
>  		return 0;
>  	}
>  
> -	resblks = XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK);
> +	resblks = XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK, 0);
>  	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0,
>  			XFS_TRANS_RESERVE, &tp);
>  	if (error)
> @@ -1017,7 +1017,7 @@ xfs_reflink_remap_extent(
>  	}
>  
>  	/* Start a rolling transaction to switch the mappings */
> -	resblks = XFS_EXTENTADD_SPACE_RES(ip->i_mount, XFS_DATA_FORK);
> +	resblks = XFS_EXTENTADD_SPACE_RES(ip->i_mount, XFS_DATA_FORK, 0);
>  	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0, 0, &tp);
>  	if (error)
>  		goto out;
> -- 
> 2.20.1
>
Chandan Babu R June 9, 2020, 2:23 p.m. UTC | #2
On Monday 8 June 2020 11:20:08 PM IST Darrick J. Wong wrote:
> On Sat, Jun 06, 2020 at 01:57:42PM +0530, Chandan Babu R wrote:
> > XFS_BM_MAXLEVELS() returns the maximum possible height of BMBT tree for
> > either data or attribute fork. For data forks, this commit adds a new
> > argument to XFS_BM_MAXLEVELS() to let the users choose between the
> > maximum heights of dir and non-dir BMBTs.
> > 
> > As of this commit, both dir and non-dir BMBTs have the same maximum
> > height. A future commit in this series will use 2^27 extent count as the
> > input to compute the maximum height of a directory BMBT which will in
> > turn cause the maximum heights of dir and non-dir BMBTs to differ.
> > 
> > Signed-off-by: Chandan Babu R <chandanrlinux@gmail.com>
> > ---
> >  fs/xfs/libxfs/xfs_attr.c        |  5 ++--
> >  fs/xfs/libxfs/xfs_bmap.c        |  5 ++--
> >  fs/xfs/libxfs/xfs_bmap_btree.h  |  4 +++-
> >  fs/xfs/libxfs/xfs_trans_resv.c  | 25 +++++++++++---------
> >  fs/xfs/libxfs/xfs_trans_resv.h  |  4 ++--
> >  fs/xfs/libxfs/xfs_trans_space.h | 41 +++++++++++++++++----------------
> >  fs/xfs/xfs_bmap_item.c          |  3 ++-
> >  fs/xfs/xfs_reflink.c            |  4 ++--
> >  8 files changed, 50 insertions(+), 41 deletions(-)
> > 
> > diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c
> > index a4b23edf887e..357e29a5a167 100644
> > --- a/fs/xfs/libxfs/xfs_attr.c
> > +++ b/fs/xfs/libxfs/xfs_attr.c
> > @@ -150,7 +150,7 @@ xfs_attr_calc_size(
> >  	 * "local" or "remote" (note: local != inline).
> >  	 */
> >  	size = xfs_attr_leaf_newentsize(args, local);
> > -	nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK);
> > +	nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK, 0);
> 
> When would we have a DAENTER space reservation for the data fork on
> something that isn't a directory?
> 
> Shouldn't you be able to compute the correct 'dbmbt' parameter value
> from whichfork?
>

You are right. I could pass the "use dir bmbt" argument to XFS_DAENTER_BMAPS()
from within the definition of XFS_DAENTER_SPACE_RES() if the fork passed in is
a data fork. This argument could be passed to XFS_BM_MAXLEVELS() via
XFS_NEXTENTADD_SPACE_RES() => XFS_EXTENTADD_SPACE_RES() => XFS_BM_MAXLEVELS().
But modifications made to invocations of these three macros else where in the
code have to be retained so that a correct value is passed for the newly
introduced argument.

> Can you modify these macros to take the xfs_inode so that we can gate
> the logic on i_mode instead of passing magic values 0 and 1 around?

I did try to do that. But many of these macros are invoked from functions that
don't have access to xfs_inode. For example, functions in xfs_trans_resv.c
which pre-calculate log reservations don't have an xfs_inode handy.

> Though... thinking about this more, 1 means "use the slightly smaller
> directory bmbt maxlevels", and 0 means "either this is a non directory
> or we want worst case calculations", doesn't it...

Yes, that was the intention of introducing this argument.

> 
> Zooming out, why do we even care?  While it's true that we might gain
> the ability to shave a few blocks off the block reservation when we know
> we're dealing with a directory, this adds quite a bit of clutter to get
> it.

Using a separate maximum extent count for directory data fork was required to
reduce the increased log reservations. To be precise, rename
operation invokes XFS_DIR_OP_LOG_COUNT() which indirectly uses
mp->m_bm_maxlevels[XFS_DATA_FORK] for its calculations. Using a modified
kernel which had 2^47 as the value for MAXEXTNUM resulted in a taller data
fork BMBT tree. Hence log reservation space for rename operation became larger.

The idea of special handling of "maximum extents for directory data fork" came
up later when trying to find a way to reduce the log reservation for the
rename operation.

> 
> >  	if (*local) {
> >  		if (size > (args->geo->blksize / 2)) {
> >  			/* Double split possible */
> > @@ -163,7 +163,8 @@ xfs_attr_calc_size(
> >  		 */
> >  		uint	dblocks = xfs_attr3_rmt_blocks(mp, args->valuelen);
> >  		nblks += dblocks;
> > -		nblks += XFS_NEXTENTADD_SPACE_RES(mp, dblocks, XFS_ATTR_FORK);
> > +		nblks += XFS_NEXTENTADD_SPACE_RES(mp, dblocks,
> > +				XFS_ATTR_FORK, 0);
> >  	}
> >  
> >  	return nblks;
> > diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
> > index 01e2b543b139..8b0029b3cecf 100644
> > --- a/fs/xfs/libxfs/xfs_bmap.c
> > +++ b/fs/xfs/libxfs/xfs_bmap.c
> > @@ -182,13 +182,14 @@ xfs_bmap_worst_indlen(
> >  	mp = ip->i_mount;
> >  	maxrecs = mp->m_bmap_dmxr[0];
> >  	for (level = 0, rval = 0;
> > -	     level < XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK);
> > +	     level < XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK, 0);
> >  	     level++) {
> >  		len += maxrecs - 1;
> >  		do_div(len, maxrecs);
> >  		rval += len;
> >  		if (len == 1)
> > -			return rval + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) -
> > +			return rval +
> > +				XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK, 0) -
> >  				level - 1;
> >  		if (level == 0)
> >  			maxrecs = mp->m_bmap_dmxr[1];
> > diff --git a/fs/xfs/libxfs/xfs_bmap_btree.h b/fs/xfs/libxfs/xfs_bmap_btree.h
> > index 72bf74c79fb9..a047be5883d1 100644
> > --- a/fs/xfs/libxfs/xfs_bmap_btree.h
> > +++ b/fs/xfs/libxfs/xfs_bmap_btree.h
> > @@ -79,7 +79,9 @@ struct xfs_trans;
> >  /*
> >   * Maximum number of bmap btree levels.
> >   */
> > -#define XFS_BM_MAXLEVELS(mp,w)		((mp)->m_bm_maxlevels[(w)])
> > +#define XFS_BM_MAXLEVELS(mp,w,use_dir_bmbt) \
> > +	((!(use_dir_bmbt)) ? \
> > +		(mp)->m_bm_maxlevels[(w)] : (mp)->m_bm_dir_maxlevel)
> 
> Also, if you /are/ going to mess with these macros, can you please turn
> them into static inline functions?  Typechecking would be nice.

Sure, I will do that.

> 
> --D
> 
> >  /*
> >   * Prototypes for xfs_bmap.c to call.
> > diff --git a/fs/xfs/libxfs/xfs_trans_resv.c b/fs/xfs/libxfs/xfs_trans_resv.c
> > index b44b521c605c..39cfca1b71b6 100644
> > --- a/fs/xfs/libxfs/xfs_trans_resv.c
> > +++ b/fs/xfs/libxfs/xfs_trans_resv.c
> > @@ -265,14 +265,14 @@ xfs_calc_write_reservation(
> >  	unsigned int		blksz = XFS_FSB_TO_B(mp, 1);
> >  
> >  	t1 = xfs_calc_inode_res(mp, 1) +
> > -	     xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK), blksz) +
> > +	     xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK, 0), blksz) +
> >  	     xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) +
> >  	     xfs_calc_buf_res(xfs_allocfree_log_count(mp, 2), blksz);
> >  
> >  	if (xfs_sb_version_hasrealtime(&mp->m_sb)) {
> >  		t2 = xfs_calc_inode_res(mp, 1) +
> > -		     xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK),
> > -				     blksz) +
> > +		     xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK, 0),
> > +			blksz) +
> >  		     xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) +
> >  		     xfs_calc_buf_res(xfs_rtalloc_log_count(mp, 1), blksz) +
> >  		     xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1), blksz);
> > @@ -313,7 +313,8 @@ xfs_calc_itruncate_reservation(
> >  	unsigned int		blksz = XFS_FSB_TO_B(mp, 1);
> >  
> >  	t1 = xfs_calc_inode_res(mp, 1) +
> > -	     xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) + 1, blksz);
> > +	     xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK, 0) + 1,
> > +			     blksz);
> >  
> >  	t2 = xfs_calc_buf_res(9, mp->m_sb.sb_sectsize) +
> >  	     xfs_calc_buf_res(xfs_allocfree_log_count(mp, 4), blksz);
> > @@ -592,7 +593,7 @@ xfs_calc_growrtalloc_reservation(
> >  	struct xfs_mount	*mp)
> >  {
> >  	return xfs_calc_buf_res(2, mp->m_sb.sb_sectsize) +
> > -		xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK),
> > +		xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK, 0),
> >  				 XFS_FSB_TO_B(mp, 1)) +
> >  		xfs_calc_inode_res(mp, 1) +
> >  		xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1),
> > @@ -669,7 +670,7 @@ xfs_calc_addafork_reservation(
> >  		xfs_calc_inode_res(mp, 1) +
> >  		xfs_calc_buf_res(2, mp->m_sb.sb_sectsize) +
> >  		xfs_calc_buf_res(1, mp->m_dir_geo->blksize) +
> > -		xfs_calc_buf_res(XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1,
> > +		xfs_calc_buf_res(XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK, 0) + 1,
> >  				 XFS_FSB_TO_B(mp, 1)) +
> >  		xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1),
> >  				 XFS_FSB_TO_B(mp, 1));
> > @@ -691,7 +692,7 @@ xfs_calc_attrinval_reservation(
> >  	struct xfs_mount	*mp)
> >  {
> >  	return max((xfs_calc_inode_res(mp, 1) +
> > -		    xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK),
> > +		    xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK, 0),
> >  				     XFS_FSB_TO_B(mp, 1))),
> >  		   (xfs_calc_buf_res(9, mp->m_sb.sb_sectsize) +
> >  		    xfs_calc_buf_res(xfs_allocfree_log_count(mp, 4),
> > @@ -717,10 +718,11 @@ xfs_calc_attrset_reservation(
> >  	int			bmbt_blks;
> >  
> >  	da_blks = XFS_DAENTER_BLOCKS(mp, XFS_ATTR_FORK);
> > -	bmbt_blks = XFS_DAENTER_BMAPS(mp, XFS_ATTR_FORK);
> > +	bmbt_blks = XFS_DAENTER_BMAPS(mp, XFS_ATTR_FORK, 0);
> >  
> >  	max_rmt_blks = xfs_attr3_rmt_blocks(mp, XATTR_SIZE_MAX);
> > -	bmbt_blks += XFS_NEXTENTADD_SPACE_RES(mp, max_rmt_blks, XFS_ATTR_FORK);
> > +	bmbt_blks += XFS_NEXTENTADD_SPACE_RES(mp, max_rmt_blks,
> > +			XFS_ATTR_FORK, 0);
> >  
> >  	return XFS_DQUOT_LOGRES(mp) +
> >  		xfs_calc_inode_res(mp, 1) +
> > @@ -752,8 +754,9 @@ xfs_calc_attrrm_reservation(
> >  		     xfs_calc_buf_res(XFS_DA_NODE_MAXDEPTH,
> >  				      XFS_FSB_TO_B(mp, 1)) +
> >  		     (uint)XFS_FSB_TO_B(mp,
> > -					XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK)) +
> > -		     xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK), 0)),
> > +				XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK, 0)) +
> > +		     xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK, 0),
> > +				     0)),
> >  		    (xfs_calc_buf_res(5, mp->m_sb.sb_sectsize) +
> >  		     xfs_calc_buf_res(xfs_allocfree_log_count(mp, 2),
> >  				      XFS_FSB_TO_B(mp, 1))));
> > diff --git a/fs/xfs/libxfs/xfs_trans_resv.h b/fs/xfs/libxfs/xfs_trans_resv.h
> > index f50996ae18e6..d64989eeebd7 100644
> > --- a/fs/xfs/libxfs/xfs_trans_resv.h
> > +++ b/fs/xfs/libxfs/xfs_trans_resv.h
> > @@ -61,10 +61,10 @@ struct xfs_trans_resv {
> >   */
> >  #define	XFS_DIROP_LOG_RES(mp)	\
> >  	(XFS_FSB_TO_B(mp, XFS_DAENTER_BLOCKS(mp, XFS_DATA_FORK)) + \
> > -	 (XFS_FSB_TO_B(mp, XFS_DAENTER_BMAPS(mp, XFS_DATA_FORK) + 1)))
> > +	 (XFS_FSB_TO_B(mp, XFS_DAENTER_BMAPS(mp, XFS_DATA_FORK, 1) + 1)))
> >  #define	XFS_DIROP_LOG_COUNT(mp)	\
> >  	(XFS_DAENTER_BLOCKS(mp, XFS_DATA_FORK) + \
> > -	 XFS_DAENTER_BMAPS(mp, XFS_DATA_FORK) + 1)
> > +	 XFS_DAENTER_BMAPS(mp, XFS_DATA_FORK, 1) + 1)
> >  
> >  /*
> >   * Various log count values.
> > diff --git a/fs/xfs/libxfs/xfs_trans_space.h b/fs/xfs/libxfs/xfs_trans_space.h
> > index b559af70cf51..c51d809a16b1 100644
> > --- a/fs/xfs/libxfs/xfs_trans_space.h
> > +++ b/fs/xfs/libxfs/xfs_trans_space.h
> > @@ -25,15 +25,16 @@
> >  
> >  #define XFS_MAX_CONTIG_EXTENTS_PER_BLOCK(mp)    \
> >  		(((mp)->m_alloc_mxr[0]) - ((mp)->m_alloc_mnr[0]))
> > -#define	XFS_EXTENTADD_SPACE_RES(mp,w)	(XFS_BM_MAXLEVELS(mp,w) - 1)
> > -#define XFS_NEXTENTADD_SPACE_RES(mp,b,w)\
> > +#define	XFS_EXTENTADD_SPACE_RES(mp,w,dbmbt)	\
> > +	(XFS_BM_MAXLEVELS(mp,w,dbmbt) - 1)
> > +#define XFS_NEXTENTADD_SPACE_RES(mp,b,w,dbmbt)		   \
> >  	(((b + XFS_MAX_CONTIG_EXTENTS_PER_BLOCK(mp) - 1) / \
> >  	  XFS_MAX_CONTIG_EXTENTS_PER_BLOCK(mp)) * \
> > -	  XFS_EXTENTADD_SPACE_RES(mp,w))
> > +		XFS_EXTENTADD_SPACE_RES(mp,w,dbmbt))
> >  
> >  /* Blocks we might need to add "b" mappings & rmappings to a file. */
> > -#define XFS_SWAP_RMAP_SPACE_RES(mp,b,w)\
> > -	(XFS_NEXTENTADD_SPACE_RES((mp), (b), (w)) + \
> > +#define XFS_SWAP_RMAP_SPACE_RES(mp,b,w)	    \
> > +	(XFS_NEXTENTADD_SPACE_RES((mp), (b), (w), 0) +	\
> >  	 XFS_NRMAPADD_SPACE_RES((mp), (b)))
> >  
> >  #define	XFS_DAENTER_1B(mp,w)	\
> > @@ -47,19 +48,19 @@
> >  	(XFS_DA_NODE_MAXDEPTH + (((w) == XFS_DATA_FORK) ? 2 : 1))
> >  #define	XFS_DAENTER_BLOCKS(mp,w)	\
> >  	(XFS_DAENTER_1B(mp,w) * XFS_DAENTER_DBS(mp,w))
> > -#define	XFS_DAENTER_BMAP1B(mp,w)	\
> > -	XFS_NEXTENTADD_SPACE_RES(mp, XFS_DAENTER_1B(mp, w), w)
> > -#define	XFS_DAENTER_BMAPS(mp,w)		\
> > -	(XFS_DAENTER_DBS(mp,w) * XFS_DAENTER_BMAP1B(mp,w))
> > -#define	XFS_DAENTER_SPACE_RES(mp,w)	\
> > -	(XFS_DAENTER_BLOCKS(mp,w) + XFS_DAENTER_BMAPS(mp,w))
> > -#define	XFS_DAREMOVE_SPACE_RES(mp,w)	XFS_DAENTER_BMAPS(mp,w)
> > +#define	XFS_DAENTER_BMAP1B(mp,w,dbmbt)	\
> > +	XFS_NEXTENTADD_SPACE_RES(mp, XFS_DAENTER_1B(mp, w), w, dbmbt)
> > +#define	XFS_DAENTER_BMAPS(mp,w,dbmbt)	\
> > +	(XFS_DAENTER_DBS(mp,w) * XFS_DAENTER_BMAP1B(mp,w,dbmbt))
> > +#define	XFS_DAENTER_SPACE_RES(mp,w,dbmbt)	\
> > +	(XFS_DAENTER_BLOCKS(mp,w) + XFS_DAENTER_BMAPS(mp,w,dbmbt))
> > +#define	XFS_DAREMOVE_SPACE_RES(mp,w,dbmbt)	XFS_DAENTER_BMAPS(mp,w,dbmbt)
> >  #define	XFS_DIRENTER_MAX_SPLIT(mp,nl)	1
> >  #define	XFS_DIRENTER_SPACE_RES(mp,nl)	\
> > -	(XFS_DAENTER_SPACE_RES(mp, XFS_DATA_FORK) * \
> > +	(XFS_DAENTER_SPACE_RES(mp, XFS_DATA_FORK, 1) *	\
> >  	 XFS_DIRENTER_MAX_SPLIT(mp,nl))
> >  #define	XFS_DIRREMOVE_SPACE_RES(mp)	\
> > -	XFS_DAREMOVE_SPACE_RES(mp, XFS_DATA_FORK)
> > +	XFS_DAREMOVE_SPACE_RES(mp, XFS_DATA_FORK, 1)
> >  #define	XFS_IALLOC_SPACE_RES(mp)	\
> >  	(M_IGEO(mp)->ialloc_blks + \
> >  	 (xfs_sb_version_hasfinobt(&mp->m_sb) ? 2 : 1 * \
> > @@ -69,26 +70,26 @@
> >   * Space reservation values for various transactions.
> >   */
> >  #define	XFS_ADDAFORK_SPACE_RES(mp)	\
> > -	((mp)->m_dir_geo->fsbcount + XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK))
> > +	((mp)->m_dir_geo->fsbcount + XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK, 0))
> >  #define	XFS_ATTRRM_SPACE_RES(mp)	\
> > -	XFS_DAREMOVE_SPACE_RES(mp, XFS_ATTR_FORK)
> > +	XFS_DAREMOVE_SPACE_RES(mp, XFS_ATTR_FORK, 0)
> >  /* This macro is not used - see inline code in xfs_attr_set */
> >  #define	XFS_ATTRSET_SPACE_RES(mp, v)	\
> > -	(XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK) + XFS_B_TO_FSB(mp, v))
> > +	(XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK, 0) + XFS_B_TO_FSB(mp, v))
> >  #define	XFS_CREATE_SPACE_RES(mp,nl)	\
> >  	(XFS_IALLOC_SPACE_RES(mp) + XFS_DIRENTER_SPACE_RES(mp,nl))
> >  #define	XFS_DIOSTRAT_SPACE_RES(mp, v)	\
> > -	(XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK) + (v))
> > +	(XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK, 0) + (v))
> >  #define	XFS_GROWFS_SPACE_RES(mp)	\
> >  	(2 * (mp)->m_ag_maxlevels)
> >  #define	XFS_GROWFSRT_SPACE_RES(mp,b)	\
> > -	((b) + XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK))
> > +	((b) + XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK, 0))
> >  #define	XFS_LINK_SPACE_RES(mp,nl)	\
> >  	XFS_DIRENTER_SPACE_RES(mp,nl)
> >  #define	XFS_MKDIR_SPACE_RES(mp,nl)	\
> >  	(XFS_IALLOC_SPACE_RES(mp) + XFS_DIRENTER_SPACE_RES(mp,nl))
> >  #define	XFS_QM_DQALLOC_SPACE_RES(mp)	\
> > -	(XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK) + \
> > +	(XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK, 0) + \
> >  	 XFS_DQUOT_CLUSTER_SIZE_FSB)
> >  #define	XFS_QM_QINOCREATE_SPACE_RES(mp)	\
> >  	XFS_IALLOC_SPACE_RES(mp)
> > diff --git a/fs/xfs/xfs_bmap_item.c b/fs/xfs/xfs_bmap_item.c
> > index 6736c5ab188f..0a8a8377a150 100644
> > --- a/fs/xfs/xfs_bmap_item.c
> > +++ b/fs/xfs/xfs_bmap_item.c
> > @@ -482,7 +482,8 @@ xfs_bui_item_recover(
> >  	}
> >  
> >  	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate,
> > -			XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK), 0, 0, &tp);
> > +			XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK, 0), 0,
> > +			0, &tp);
> >  	if (error)
> >  		return error;
> >  	/*
> > diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c
> > index 107bf2a2f344..fd35a0bf2c47 100644
> > --- a/fs/xfs/xfs_reflink.c
> > +++ b/fs/xfs/xfs_reflink.c
> > @@ -614,7 +614,7 @@ xfs_reflink_end_cow_extent(
> >  		return 0;
> >  	}
> >  
> > -	resblks = XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK);
> > +	resblks = XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK, 0);
> >  	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0,
> >  			XFS_TRANS_RESERVE, &tp);
> >  	if (error)
> > @@ -1017,7 +1017,7 @@ xfs_reflink_remap_extent(
> >  	}
> >  
> >  	/* Start a rolling transaction to switch the mappings */
> > -	resblks = XFS_EXTENTADD_SPACE_RES(ip->i_mount, XFS_DATA_FORK);
> > +	resblks = XFS_EXTENTADD_SPACE_RES(ip->i_mount, XFS_DATA_FORK, 0);
> >  	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0, 0, &tp);
> >  	if (error)
> >  		goto out;
>
diff mbox series

Patch

diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c
index a4b23edf887e..357e29a5a167 100644
--- a/fs/xfs/libxfs/xfs_attr.c
+++ b/fs/xfs/libxfs/xfs_attr.c
@@ -150,7 +150,7 @@  xfs_attr_calc_size(
 	 * "local" or "remote" (note: local != inline).
 	 */
 	size = xfs_attr_leaf_newentsize(args, local);
-	nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK);
+	nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK, 0);
 	if (*local) {
 		if (size > (args->geo->blksize / 2)) {
 			/* Double split possible */
@@ -163,7 +163,8 @@  xfs_attr_calc_size(
 		 */
 		uint	dblocks = xfs_attr3_rmt_blocks(mp, args->valuelen);
 		nblks += dblocks;
-		nblks += XFS_NEXTENTADD_SPACE_RES(mp, dblocks, XFS_ATTR_FORK);
+		nblks += XFS_NEXTENTADD_SPACE_RES(mp, dblocks,
+				XFS_ATTR_FORK, 0);
 	}
 
 	return nblks;
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
index 01e2b543b139..8b0029b3cecf 100644
--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -182,13 +182,14 @@  xfs_bmap_worst_indlen(
 	mp = ip->i_mount;
 	maxrecs = mp->m_bmap_dmxr[0];
 	for (level = 0, rval = 0;
-	     level < XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK);
+	     level < XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK, 0);
 	     level++) {
 		len += maxrecs - 1;
 		do_div(len, maxrecs);
 		rval += len;
 		if (len == 1)
-			return rval + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) -
+			return rval +
+				XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK, 0) -
 				level - 1;
 		if (level == 0)
 			maxrecs = mp->m_bmap_dmxr[1];
diff --git a/fs/xfs/libxfs/xfs_bmap_btree.h b/fs/xfs/libxfs/xfs_bmap_btree.h
index 72bf74c79fb9..a047be5883d1 100644
--- a/fs/xfs/libxfs/xfs_bmap_btree.h
+++ b/fs/xfs/libxfs/xfs_bmap_btree.h
@@ -79,7 +79,9 @@  struct xfs_trans;
 /*
  * Maximum number of bmap btree levels.
  */
-#define XFS_BM_MAXLEVELS(mp,w)		((mp)->m_bm_maxlevels[(w)])
+#define XFS_BM_MAXLEVELS(mp,w,use_dir_bmbt) \
+	((!(use_dir_bmbt)) ? \
+		(mp)->m_bm_maxlevels[(w)] : (mp)->m_bm_dir_maxlevel)
 
 /*
  * Prototypes for xfs_bmap.c to call.
diff --git a/fs/xfs/libxfs/xfs_trans_resv.c b/fs/xfs/libxfs/xfs_trans_resv.c
index b44b521c605c..39cfca1b71b6 100644
--- a/fs/xfs/libxfs/xfs_trans_resv.c
+++ b/fs/xfs/libxfs/xfs_trans_resv.c
@@ -265,14 +265,14 @@  xfs_calc_write_reservation(
 	unsigned int		blksz = XFS_FSB_TO_B(mp, 1);
 
 	t1 = xfs_calc_inode_res(mp, 1) +
-	     xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK), blksz) +
+	     xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK, 0), blksz) +
 	     xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) +
 	     xfs_calc_buf_res(xfs_allocfree_log_count(mp, 2), blksz);
 
 	if (xfs_sb_version_hasrealtime(&mp->m_sb)) {
 		t2 = xfs_calc_inode_res(mp, 1) +
-		     xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK),
-				     blksz) +
+		     xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK, 0),
+			blksz) +
 		     xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) +
 		     xfs_calc_buf_res(xfs_rtalloc_log_count(mp, 1), blksz) +
 		     xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1), blksz);
@@ -313,7 +313,8 @@  xfs_calc_itruncate_reservation(
 	unsigned int		blksz = XFS_FSB_TO_B(mp, 1);
 
 	t1 = xfs_calc_inode_res(mp, 1) +
-	     xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) + 1, blksz);
+	     xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK, 0) + 1,
+			     blksz);
 
 	t2 = xfs_calc_buf_res(9, mp->m_sb.sb_sectsize) +
 	     xfs_calc_buf_res(xfs_allocfree_log_count(mp, 4), blksz);
@@ -592,7 +593,7 @@  xfs_calc_growrtalloc_reservation(
 	struct xfs_mount	*mp)
 {
 	return xfs_calc_buf_res(2, mp->m_sb.sb_sectsize) +
-		xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK),
+		xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK, 0),
 				 XFS_FSB_TO_B(mp, 1)) +
 		xfs_calc_inode_res(mp, 1) +
 		xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1),
@@ -669,7 +670,7 @@  xfs_calc_addafork_reservation(
 		xfs_calc_inode_res(mp, 1) +
 		xfs_calc_buf_res(2, mp->m_sb.sb_sectsize) +
 		xfs_calc_buf_res(1, mp->m_dir_geo->blksize) +
-		xfs_calc_buf_res(XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1,
+		xfs_calc_buf_res(XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK, 0) + 1,
 				 XFS_FSB_TO_B(mp, 1)) +
 		xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1),
 				 XFS_FSB_TO_B(mp, 1));
@@ -691,7 +692,7 @@  xfs_calc_attrinval_reservation(
 	struct xfs_mount	*mp)
 {
 	return max((xfs_calc_inode_res(mp, 1) +
-		    xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK),
+		    xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK, 0),
 				     XFS_FSB_TO_B(mp, 1))),
 		   (xfs_calc_buf_res(9, mp->m_sb.sb_sectsize) +
 		    xfs_calc_buf_res(xfs_allocfree_log_count(mp, 4),
@@ -717,10 +718,11 @@  xfs_calc_attrset_reservation(
 	int			bmbt_blks;
 
 	da_blks = XFS_DAENTER_BLOCKS(mp, XFS_ATTR_FORK);
-	bmbt_blks = XFS_DAENTER_BMAPS(mp, XFS_ATTR_FORK);
+	bmbt_blks = XFS_DAENTER_BMAPS(mp, XFS_ATTR_FORK, 0);
 
 	max_rmt_blks = xfs_attr3_rmt_blocks(mp, XATTR_SIZE_MAX);
-	bmbt_blks += XFS_NEXTENTADD_SPACE_RES(mp, max_rmt_blks, XFS_ATTR_FORK);
+	bmbt_blks += XFS_NEXTENTADD_SPACE_RES(mp, max_rmt_blks,
+			XFS_ATTR_FORK, 0);
 
 	return XFS_DQUOT_LOGRES(mp) +
 		xfs_calc_inode_res(mp, 1) +
@@ -752,8 +754,9 @@  xfs_calc_attrrm_reservation(
 		     xfs_calc_buf_res(XFS_DA_NODE_MAXDEPTH,
 				      XFS_FSB_TO_B(mp, 1)) +
 		     (uint)XFS_FSB_TO_B(mp,
-					XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK)) +
-		     xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK), 0)),
+				XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK, 0)) +
+		     xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK, 0),
+				     0)),
 		    (xfs_calc_buf_res(5, mp->m_sb.sb_sectsize) +
 		     xfs_calc_buf_res(xfs_allocfree_log_count(mp, 2),
 				      XFS_FSB_TO_B(mp, 1))));
diff --git a/fs/xfs/libxfs/xfs_trans_resv.h b/fs/xfs/libxfs/xfs_trans_resv.h
index f50996ae18e6..d64989eeebd7 100644
--- a/fs/xfs/libxfs/xfs_trans_resv.h
+++ b/fs/xfs/libxfs/xfs_trans_resv.h
@@ -61,10 +61,10 @@  struct xfs_trans_resv {
  */
 #define	XFS_DIROP_LOG_RES(mp)	\
 	(XFS_FSB_TO_B(mp, XFS_DAENTER_BLOCKS(mp, XFS_DATA_FORK)) + \
-	 (XFS_FSB_TO_B(mp, XFS_DAENTER_BMAPS(mp, XFS_DATA_FORK) + 1)))
+	 (XFS_FSB_TO_B(mp, XFS_DAENTER_BMAPS(mp, XFS_DATA_FORK, 1) + 1)))
 #define	XFS_DIROP_LOG_COUNT(mp)	\
 	(XFS_DAENTER_BLOCKS(mp, XFS_DATA_FORK) + \
-	 XFS_DAENTER_BMAPS(mp, XFS_DATA_FORK) + 1)
+	 XFS_DAENTER_BMAPS(mp, XFS_DATA_FORK, 1) + 1)
 
 /*
  * Various log count values.
diff --git a/fs/xfs/libxfs/xfs_trans_space.h b/fs/xfs/libxfs/xfs_trans_space.h
index b559af70cf51..c51d809a16b1 100644
--- a/fs/xfs/libxfs/xfs_trans_space.h
+++ b/fs/xfs/libxfs/xfs_trans_space.h
@@ -25,15 +25,16 @@ 
 
 #define XFS_MAX_CONTIG_EXTENTS_PER_BLOCK(mp)    \
 		(((mp)->m_alloc_mxr[0]) - ((mp)->m_alloc_mnr[0]))
-#define	XFS_EXTENTADD_SPACE_RES(mp,w)	(XFS_BM_MAXLEVELS(mp,w) - 1)
-#define XFS_NEXTENTADD_SPACE_RES(mp,b,w)\
+#define	XFS_EXTENTADD_SPACE_RES(mp,w,dbmbt)	\
+	(XFS_BM_MAXLEVELS(mp,w,dbmbt) - 1)
+#define XFS_NEXTENTADD_SPACE_RES(mp,b,w,dbmbt)		   \
 	(((b + XFS_MAX_CONTIG_EXTENTS_PER_BLOCK(mp) - 1) / \
 	  XFS_MAX_CONTIG_EXTENTS_PER_BLOCK(mp)) * \
-	  XFS_EXTENTADD_SPACE_RES(mp,w))
+		XFS_EXTENTADD_SPACE_RES(mp,w,dbmbt))
 
 /* Blocks we might need to add "b" mappings & rmappings to a file. */
-#define XFS_SWAP_RMAP_SPACE_RES(mp,b,w)\
-	(XFS_NEXTENTADD_SPACE_RES((mp), (b), (w)) + \
+#define XFS_SWAP_RMAP_SPACE_RES(mp,b,w)	    \
+	(XFS_NEXTENTADD_SPACE_RES((mp), (b), (w), 0) +	\
 	 XFS_NRMAPADD_SPACE_RES((mp), (b)))
 
 #define	XFS_DAENTER_1B(mp,w)	\
@@ -47,19 +48,19 @@ 
 	(XFS_DA_NODE_MAXDEPTH + (((w) == XFS_DATA_FORK) ? 2 : 1))
 #define	XFS_DAENTER_BLOCKS(mp,w)	\
 	(XFS_DAENTER_1B(mp,w) * XFS_DAENTER_DBS(mp,w))
-#define	XFS_DAENTER_BMAP1B(mp,w)	\
-	XFS_NEXTENTADD_SPACE_RES(mp, XFS_DAENTER_1B(mp, w), w)
-#define	XFS_DAENTER_BMAPS(mp,w)		\
-	(XFS_DAENTER_DBS(mp,w) * XFS_DAENTER_BMAP1B(mp,w))
-#define	XFS_DAENTER_SPACE_RES(mp,w)	\
-	(XFS_DAENTER_BLOCKS(mp,w) + XFS_DAENTER_BMAPS(mp,w))
-#define	XFS_DAREMOVE_SPACE_RES(mp,w)	XFS_DAENTER_BMAPS(mp,w)
+#define	XFS_DAENTER_BMAP1B(mp,w,dbmbt)	\
+	XFS_NEXTENTADD_SPACE_RES(mp, XFS_DAENTER_1B(mp, w), w, dbmbt)
+#define	XFS_DAENTER_BMAPS(mp,w,dbmbt)	\
+	(XFS_DAENTER_DBS(mp,w) * XFS_DAENTER_BMAP1B(mp,w,dbmbt))
+#define	XFS_DAENTER_SPACE_RES(mp,w,dbmbt)	\
+	(XFS_DAENTER_BLOCKS(mp,w) + XFS_DAENTER_BMAPS(mp,w,dbmbt))
+#define	XFS_DAREMOVE_SPACE_RES(mp,w,dbmbt)	XFS_DAENTER_BMAPS(mp,w,dbmbt)
 #define	XFS_DIRENTER_MAX_SPLIT(mp,nl)	1
 #define	XFS_DIRENTER_SPACE_RES(mp,nl)	\
-	(XFS_DAENTER_SPACE_RES(mp, XFS_DATA_FORK) * \
+	(XFS_DAENTER_SPACE_RES(mp, XFS_DATA_FORK, 1) *	\
 	 XFS_DIRENTER_MAX_SPLIT(mp,nl))
 #define	XFS_DIRREMOVE_SPACE_RES(mp)	\
-	XFS_DAREMOVE_SPACE_RES(mp, XFS_DATA_FORK)
+	XFS_DAREMOVE_SPACE_RES(mp, XFS_DATA_FORK, 1)
 #define	XFS_IALLOC_SPACE_RES(mp)	\
 	(M_IGEO(mp)->ialloc_blks + \
 	 (xfs_sb_version_hasfinobt(&mp->m_sb) ? 2 : 1 * \
@@ -69,26 +70,26 @@ 
  * Space reservation values for various transactions.
  */
 #define	XFS_ADDAFORK_SPACE_RES(mp)	\
-	((mp)->m_dir_geo->fsbcount + XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK))
+	((mp)->m_dir_geo->fsbcount + XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK, 0))
 #define	XFS_ATTRRM_SPACE_RES(mp)	\
-	XFS_DAREMOVE_SPACE_RES(mp, XFS_ATTR_FORK)
+	XFS_DAREMOVE_SPACE_RES(mp, XFS_ATTR_FORK, 0)
 /* This macro is not used - see inline code in xfs_attr_set */
 #define	XFS_ATTRSET_SPACE_RES(mp, v)	\
-	(XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK) + XFS_B_TO_FSB(mp, v))
+	(XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK, 0) + XFS_B_TO_FSB(mp, v))
 #define	XFS_CREATE_SPACE_RES(mp,nl)	\
 	(XFS_IALLOC_SPACE_RES(mp) + XFS_DIRENTER_SPACE_RES(mp,nl))
 #define	XFS_DIOSTRAT_SPACE_RES(mp, v)	\
-	(XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK) + (v))
+	(XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK, 0) + (v))
 #define	XFS_GROWFS_SPACE_RES(mp)	\
 	(2 * (mp)->m_ag_maxlevels)
 #define	XFS_GROWFSRT_SPACE_RES(mp,b)	\
-	((b) + XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK))
+	((b) + XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK, 0))
 #define	XFS_LINK_SPACE_RES(mp,nl)	\
 	XFS_DIRENTER_SPACE_RES(mp,nl)
 #define	XFS_MKDIR_SPACE_RES(mp,nl)	\
 	(XFS_IALLOC_SPACE_RES(mp) + XFS_DIRENTER_SPACE_RES(mp,nl))
 #define	XFS_QM_DQALLOC_SPACE_RES(mp)	\
-	(XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK) + \
+	(XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK, 0) + \
 	 XFS_DQUOT_CLUSTER_SIZE_FSB)
 #define	XFS_QM_QINOCREATE_SPACE_RES(mp)	\
 	XFS_IALLOC_SPACE_RES(mp)
diff --git a/fs/xfs/xfs_bmap_item.c b/fs/xfs/xfs_bmap_item.c
index 6736c5ab188f..0a8a8377a150 100644
--- a/fs/xfs/xfs_bmap_item.c
+++ b/fs/xfs/xfs_bmap_item.c
@@ -482,7 +482,8 @@  xfs_bui_item_recover(
 	}
 
 	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate,
-			XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK), 0, 0, &tp);
+			XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK, 0), 0,
+			0, &tp);
 	if (error)
 		return error;
 	/*
diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c
index 107bf2a2f344..fd35a0bf2c47 100644
--- a/fs/xfs/xfs_reflink.c
+++ b/fs/xfs/xfs_reflink.c
@@ -614,7 +614,7 @@  xfs_reflink_end_cow_extent(
 		return 0;
 	}
 
-	resblks = XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK);
+	resblks = XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK, 0);
 	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0,
 			XFS_TRANS_RESERVE, &tp);
 	if (error)
@@ -1017,7 +1017,7 @@  xfs_reflink_remap_extent(
 	}
 
 	/* Start a rolling transaction to switch the mappings */
-	resblks = XFS_EXTENTADD_SPACE_RES(ip->i_mount, XFS_DATA_FORK);
+	resblks = XFS_EXTENTADD_SPACE_RES(ip->i_mount, XFS_DATA_FORK, 0);
 	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0, 0, &tp);
 	if (error)
 		goto out;