diff mbox

[011/119] xfs: refactor btree maxlevels computation

Message ID 146612634260.12839.10495592169777117935.stgit@birch.djwong.org (mailing list archive)
State New, archived
Headers show

Commit Message

Darrick J. Wong June 17, 2016, 1:19 a.m. UTC
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 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>
---
 fs/xfs/libxfs/xfs_alloc.c  |   15 ++-------------
 fs/xfs/libxfs/xfs_btree.c  |   19 +++++++++++++++++++
 fs/xfs/libxfs/xfs_btree.h  |    2 ++
 fs/xfs/libxfs/xfs_ialloc.c |   19 +++++--------------
 4 files changed, 28 insertions(+), 27 deletions(-)



--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Comments

Brian Foster June 20, 2016, 2:31 p.m. UTC | #1
On Thu, Jun 16, 2016 at 06:19:02PM -0700, Darrick J. Wong wrote:
> 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 many blocks are needed to satisfy a btree split.

			how many

> 
> 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>

>  fs/xfs/libxfs/xfs_alloc.c  |   15 ++-------------
>  fs/xfs/libxfs/xfs_btree.c  |   19 +++++++++++++++++++
>  fs/xfs/libxfs/xfs_btree.h  |    2 ++
>  fs/xfs/libxfs/xfs_ialloc.c |   19 +++++--------------
>  4 files changed, 28 insertions(+), 27 deletions(-)
> 
> 
> diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c
> index 1c76a0e..c366889 100644
> --- a/fs/xfs/libxfs/xfs_alloc.c
> +++ b/fs/xfs/libxfs/xfs_alloc.c
> @@ -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);
>  }
>  
>  /*
> diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c
> index 5eb4e40..046fbcf 100644
> --- a/fs/xfs/libxfs/xfs_btree.c
> +++ b/fs/xfs/libxfs/xfs_btree.c
> @@ -4158,6 +4158,25 @@ xfs_btree_sblock_verify(
>  }
>  
>  /*
> + * 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;
> +}
> +
> +/*
>   * Calculate the number of blocks needed to store a given number of records
>   * in a short-format (per-AG metadata) btree.
>   */
> diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h
> index b330f19..b955e5d 100644
> --- a/fs/xfs/libxfs/xfs_btree.h
> +++ b/fs/xfs/libxfs/xfs_btree.h
> @@ -477,5 +477,7 @@ bool xfs_btree_sblock_verify(struct xfs_buf *bp, unsigned int max_recs);
>  
>  xfs_extlen_t xfs_btree_calc_size(struct xfs_mount *mp, uint *limits,
>  		unsigned long long len);
> +uint xfs_btree_compute_maxlevels(struct xfs_mount *mp, uint *limits,
> +		unsigned long len);
>  
>  #endif	/* __XFS_BTREE_H__ */
> diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c
> index 9d0003c..cda7269 100644
> --- a/fs/xfs/libxfs/xfs_ialloc.c
> +++ b/fs/xfs/libxfs/xfs_ialloc.c
> @@ -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;
> -
> -	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;
> +	uint		inodes;
> +
> +	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);
>  }
>  
>  /*
> 
> _______________________________________________
> xfs mailing list
> xfs@oss.sgi.com
> http://oss.sgi.com/mailman/listinfo/xfs
--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Darrick J. Wong June 20, 2016, 6:23 p.m. UTC | #2
On Mon, Jun 20, 2016 at 10:31:59AM -0400, Brian Foster wrote:
> On Thu, Jun 16, 2016 at 06:19:02PM -0700, Darrick J. Wong wrote:
> > 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 many blocks are needed to satisfy a btree split.
> 
> 			how many

Got it, will change for the next posting.

--D

> 
> > 
> > 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>
> 
> >  fs/xfs/libxfs/xfs_alloc.c  |   15 ++-------------
> >  fs/xfs/libxfs/xfs_btree.c  |   19 +++++++++++++++++++
> >  fs/xfs/libxfs/xfs_btree.h  |    2 ++
> >  fs/xfs/libxfs/xfs_ialloc.c |   19 +++++--------------
> >  4 files changed, 28 insertions(+), 27 deletions(-)
> > 
> > 
> > diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c
> > index 1c76a0e..c366889 100644
> > --- a/fs/xfs/libxfs/xfs_alloc.c
> > +++ b/fs/xfs/libxfs/xfs_alloc.c
> > @@ -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);
> >  }
> >  
> >  /*
> > diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c
> > index 5eb4e40..046fbcf 100644
> > --- a/fs/xfs/libxfs/xfs_btree.c
> > +++ b/fs/xfs/libxfs/xfs_btree.c
> > @@ -4158,6 +4158,25 @@ xfs_btree_sblock_verify(
> >  }
> >  
> >  /*
> > + * 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;
> > +}
> > +
> > +/*
> >   * Calculate the number of blocks needed to store a given number of records
> >   * in a short-format (per-AG metadata) btree.
> >   */
> > diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h
> > index b330f19..b955e5d 100644
> > --- a/fs/xfs/libxfs/xfs_btree.h
> > +++ b/fs/xfs/libxfs/xfs_btree.h
> > @@ -477,5 +477,7 @@ bool xfs_btree_sblock_verify(struct xfs_buf *bp, unsigned int max_recs);
> >  
> >  xfs_extlen_t xfs_btree_calc_size(struct xfs_mount *mp, uint *limits,
> >  		unsigned long long len);
> > +uint xfs_btree_compute_maxlevels(struct xfs_mount *mp, uint *limits,
> > +		unsigned long len);
> >  
> >  #endif	/* __XFS_BTREE_H__ */
> > diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c
> > index 9d0003c..cda7269 100644
> > --- a/fs/xfs/libxfs/xfs_ialloc.c
> > +++ b/fs/xfs/libxfs/xfs_ialloc.c
> > @@ -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;
> > -
> > -	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;
> > +	uint		inodes;
> > +
> > +	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);
> >  }
> >  
> >  /*
> > 
> > _______________________________________________
> > xfs mailing list
> > xfs@oss.sgi.com
> > http://oss.sgi.com/mailman/listinfo/xfs
--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c
index 1c76a0e..c366889 100644
--- a/fs/xfs/libxfs/xfs_alloc.c
+++ b/fs/xfs/libxfs/xfs_alloc.c
@@ -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);
 }
 
 /*
diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c
index 5eb4e40..046fbcf 100644
--- a/fs/xfs/libxfs/xfs_btree.c
+++ b/fs/xfs/libxfs/xfs_btree.c
@@ -4158,6 +4158,25 @@  xfs_btree_sblock_verify(
 }
 
 /*
+ * 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;
+}
+
+/*
  * Calculate the number of blocks needed to store a given number of records
  * in a short-format (per-AG metadata) btree.
  */
diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h
index b330f19..b955e5d 100644
--- a/fs/xfs/libxfs/xfs_btree.h
+++ b/fs/xfs/libxfs/xfs_btree.h
@@ -477,5 +477,7 @@  bool xfs_btree_sblock_verify(struct xfs_buf *bp, unsigned int max_recs);
 
 xfs_extlen_t xfs_btree_calc_size(struct xfs_mount *mp, uint *limits,
 		unsigned long long len);
+uint xfs_btree_compute_maxlevels(struct xfs_mount *mp, uint *limits,
+		unsigned long len);
 
 #endif	/* __XFS_BTREE_H__ */
diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c
index 9d0003c..cda7269 100644
--- a/fs/xfs/libxfs/xfs_ialloc.c
+++ b/fs/xfs/libxfs/xfs_ialloc.c
@@ -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;
-
-	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;
+	uint		inodes;
+
+	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);
 }
 
 /*