aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2016-06-20 21:53:28 -0400
committerDave Chinner <david@fromorbit.com>2016-06-20 21:53:28 -0400
commit19b54ee66c4c5de8f8db74d5914d9a97161460bf (patch)
tree3ef3b0221a531fd418d3b41b7c250ded1b9638ed
parente66a4c678e64932eb4befd95a348b9632603d27c (diff)
xfs: refactor btree maxlevels computation
Create a common function to calculate the maximum height of a per-AG btree. This will eventually be used by the rmapbt and refcountbt code to calculate appropriate maxlevels values for each. This is important because the verifiers and the transaction block reservations depend on accurate estimates of how many blocks are needed to satisfy a btree split. We were mistakenly using the max bnobt height for all the btrees, which creates a dangerous situation since the larger records and keys in an rmapbt make it very possible that the rmapbt will be taller than the bnobt and so we can run out of transaction block reservation. Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> Reviewed-by: Brian Foster <bfoster@redhat.com> Signed-off-by: Dave Chinner <david@fromorbit.com>
-rw-r--r--fs/xfs/libxfs/xfs_alloc.c15
-rw-r--r--fs/xfs/libxfs/xfs_btree.c19
-rw-r--r--fs/xfs/libxfs/xfs_btree.h2
-rw-r--r--fs/xfs/libxfs/xfs_ialloc.c19
4 files changed, 28 insertions, 27 deletions
diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c
index 638657a91335..e56991d1a970 100644
--- a/fs/xfs/libxfs/xfs_alloc.c
+++ b/fs/xfs/libxfs/xfs_alloc.c
@@ -1839,19 +1839,8 @@ void
1839xfs_alloc_compute_maxlevels( 1839xfs_alloc_compute_maxlevels(
1840 xfs_mount_t *mp) /* file system mount structure */ 1840 xfs_mount_t *mp) /* file system mount structure */
1841{ 1841{
1842 int level; 1842 mp->m_ag_maxlevels = xfs_btree_compute_maxlevels(mp, mp->m_alloc_mnr,
1843 uint maxblocks; 1843 (mp->m_sb.sb_agblocks + 1) / 2);
1844 uint maxleafents;
1845 int minleafrecs;
1846 int minnoderecs;
1847
1848 maxleafents = (mp->m_sb.sb_agblocks + 1) / 2;
1849 minleafrecs = mp->m_alloc_mnr[0];
1850 minnoderecs = mp->m_alloc_mnr[1];
1851 maxblocks = (maxleafents + minleafrecs - 1) / minleafrecs;
1852 for (level = 1; maxblocks > 1; level++)
1853 maxblocks = (maxblocks + minnoderecs - 1) / minnoderecs;
1854 mp->m_ag_maxlevels = level;
1855} 1844}
1856 1845
1857/* 1846/*
diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c
index 1f88e1ce770f..a6779b3e873c 100644
--- a/fs/xfs/libxfs/xfs_btree.c
+++ b/fs/xfs/libxfs/xfs_btree.c
@@ -4152,3 +4152,22 @@ xfs_btree_sblock_verify(
4152 4152
4153 return true; 4153 return true;
4154} 4154}
4155
4156/*
4157 * Calculate the number of btree levels needed to store a given number of
4158 * records in a short-format btree.
4159 */
4160uint
4161xfs_btree_compute_maxlevels(
4162 struct xfs_mount *mp,
4163 uint *limits,
4164 unsigned long len)
4165{
4166 uint level;
4167 unsigned long maxblocks;
4168
4169 maxblocks = (len + limits[0] - 1) / limits[0];
4170 for (level = 1; maxblocks > 1; level++)
4171 maxblocks = (maxblocks + limits[1] - 1) / limits[1];
4172 return level;
4173}
diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h
index 2e874be70209..785a99682159 100644
--- a/fs/xfs/libxfs/xfs_btree.h
+++ b/fs/xfs/libxfs/xfs_btree.h
@@ -474,5 +474,7 @@ static inline int xfs_btree_get_level(struct xfs_btree_block *block)
474 474
475bool xfs_btree_sblock_v5hdr_verify(struct xfs_buf *bp); 475bool xfs_btree_sblock_v5hdr_verify(struct xfs_buf *bp);
476bool xfs_btree_sblock_verify(struct xfs_buf *bp, unsigned int max_recs); 476bool xfs_btree_sblock_verify(struct xfs_buf *bp, unsigned int max_recs);
477uint xfs_btree_compute_maxlevels(struct xfs_mount *mp, uint *limits,
478 unsigned long len);
477 479
478#endif /* __XFS_BTREE_H__ */ 480#endif /* __XFS_BTREE_H__ */
diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c
index e3c0af73cf94..4b1e408169a8 100644
--- a/fs/xfs/libxfs/xfs_ialloc.c
+++ b/fs/xfs/libxfs/xfs_ialloc.c
@@ -2394,20 +2394,11 @@ void
2394xfs_ialloc_compute_maxlevels( 2394xfs_ialloc_compute_maxlevels(
2395 xfs_mount_t *mp) /* file system mount structure */ 2395 xfs_mount_t *mp) /* file system mount structure */
2396{ 2396{
2397 int level; 2397 uint inodes;
2398 uint maxblocks; 2398
2399 uint maxleafents; 2399 inodes = (1LL << XFS_INO_AGINO_BITS(mp)) >> XFS_INODES_PER_CHUNK_LOG;
2400 int minleafrecs; 2400 mp->m_in_maxlevels = xfs_btree_compute_maxlevels(mp, mp->m_inobt_mnr,
2401 int minnoderecs; 2401 inodes);
2402
2403 maxleafents = (1LL << XFS_INO_AGINO_BITS(mp)) >>
2404 XFS_INODES_PER_CHUNK_LOG;
2405 minleafrecs = mp->m_inobt_mnr[0];
2406 minnoderecs = mp->m_inobt_mnr[1];
2407 maxblocks = (maxleafents + minleafrecs - 1) / minleafrecs;
2408 for (level = 1; maxblocks > 1; level++)
2409 maxblocks = (maxblocks + minnoderecs - 1) / minnoderecs;
2410 mp->m_in_maxlevels = level;
2411} 2402}
2412 2403
2413/* 2404/*