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>
This commit is contained in:
parent
e66a4c678e
commit
19b54ee66c
|
@ -1839,19 +1839,8 @@ void
|
|||
xfs_alloc_compute_maxlevels(
|
||||
xfs_mount_t *mp) /* file system mount structure */
|
||||
{
|
||||
int level;
|
||||
uint maxblocks;
|
||||
uint maxleafents;
|
||||
int minleafrecs;
|
||||
int minnoderecs;
|
||||
|
||||
maxleafents = (mp->m_sb.sb_agblocks + 1) / 2;
|
||||
minleafrecs = mp->m_alloc_mnr[0];
|
||||
minnoderecs = mp->m_alloc_mnr[1];
|
||||
maxblocks = (maxleafents + minleafrecs - 1) / minleafrecs;
|
||||
for (level = 1; maxblocks > 1; level++)
|
||||
maxblocks = (maxblocks + minnoderecs - 1) / minnoderecs;
|
||||
mp->m_ag_maxlevels = level;
|
||||
mp->m_ag_maxlevels = xfs_btree_compute_maxlevels(mp, mp->m_alloc_mnr,
|
||||
(mp->m_sb.sb_agblocks + 1) / 2);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -4152,3 +4152,22 @@ xfs_btree_sblock_verify(
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the number of btree levels needed to store a given number of
|
||||
* records in a short-format btree.
|
||||
*/
|
||||
uint
|
||||
xfs_btree_compute_maxlevels(
|
||||
struct xfs_mount *mp,
|
||||
uint *limits,
|
||||
unsigned long len)
|
||||
{
|
||||
uint level;
|
||||
unsigned long maxblocks;
|
||||
|
||||
maxblocks = (len + limits[0] - 1) / limits[0];
|
||||
for (level = 1; maxblocks > 1; level++)
|
||||
maxblocks = (maxblocks + limits[1] - 1) / limits[1];
|
||||
return level;
|
||||
}
|
||||
|
|
|
@ -474,5 +474,7 @@ static inline int xfs_btree_get_level(struct xfs_btree_block *block)
|
|||
|
||||
bool xfs_btree_sblock_v5hdr_verify(struct xfs_buf *bp);
|
||||
bool xfs_btree_sblock_verify(struct xfs_buf *bp, unsigned int max_recs);
|
||||
uint xfs_btree_compute_maxlevels(struct xfs_mount *mp, uint *limits,
|
||||
unsigned long len);
|
||||
|
||||
#endif /* __XFS_BTREE_H__ */
|
||||
|
|
|
@ -2394,20 +2394,11 @@ void
|
|||
xfs_ialloc_compute_maxlevels(
|
||||
xfs_mount_t *mp) /* file system mount structure */
|
||||
{
|
||||
int level;
|
||||
uint maxblocks;
|
||||
uint maxleafents;
|
||||
int minleafrecs;
|
||||
int minnoderecs;
|
||||
uint inodes;
|
||||
|
||||
maxleafents = (1LL << XFS_INO_AGINO_BITS(mp)) >>
|
||||
XFS_INODES_PER_CHUNK_LOG;
|
||||
minleafrecs = mp->m_inobt_mnr[0];
|
||||
minnoderecs = mp->m_inobt_mnr[1];
|
||||
maxblocks = (maxleafents + minleafrecs - 1) / minleafrecs;
|
||||
for (level = 1; maxblocks > 1; level++)
|
||||
maxblocks = (maxblocks + minnoderecs - 1) / minnoderecs;
|
||||
mp->m_in_maxlevels = level;
|
||||
inodes = (1LL << XFS_INO_AGINO_BITS(mp)) >> XFS_INODES_PER_CHUNK_LOG;
|
||||
mp->m_in_maxlevels = xfs_btree_compute_maxlevels(mp, mp->m_inobt_mnr,
|
||||
inodes);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue