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

Chandan Babu R
2020-06-06T08:28:30Z

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);
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;
--
2.20.1