Re: [PATCH 1/2] xfs: Fix log reservation calculation for xattr insert operation

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tuesday, April 7, 2020 6:19 AM Dave Chinner wrote: 
> [chopped bits out of the diff to get the whole reservation in one
>  obvious piece of code.]
> 
> On Sat, Apr 04, 2020 at 02:22:02PM +0530, Chandan Rajendra wrote:
> > @@ -698,42 +699,36 @@ xfs_calc_attrinval_reservation(
> >  }
> >  
> >  /*
> > + * Setting an attribute.
> >   *	the inode getting the attribute
> >   *	the superblock for allocations
> > + *	the agf extents are allocated from
> >   *	the attribute btree * max depth
> > + *	the bmbt entries for da btree blocks
> > + *	the bmbt entries for remote blocks (if any)
> > + *	the allocation btrees.
> >   */
> >  STATIC uint
> > -xfs_calc_attrsetm_reservation(
> > +xfs_calc_attrset_reservation(
> >  	struct xfs_mount	*mp)
> >  {
> > +	int			max_rmt_blks;
> > +	int			da_blks;
> > +	int			bmbt_blks;
> > +
> > +	da_blks = XFS_DAENTER_BLOCKS(mp, XFS_ATTR_FORK);
> 
> #define XFS_DAENTER_BLOCKS(mp,w)        \
>         (XFS_DAENTER_1B(mp,w) * XFS_DAENTER_DBS(mp,w))
> #define XFS_DAENTER_1B(mp,w)    \
>         ((w) == XFS_DATA_FORK ? (mp)->m_dir_geo->fsbcount : 1)
> #define XFS_DAENTER_DBS(mp,w)   \
> 	(XFS_DA_NODE_MAXDEPTH + (((w) == XFS_DATA_FORK) ? 2 : 0))
> 
> So, da_blks contains the full da btree split depth * 1 block. i.e.
> 
> 	da_blks = XFS_DA_NODE_MAXDEPTH;
> 
> > +	bmbt_blks = XFS_DAENTER_BMAPS(mp, XFS_ATTR_FORK);
> 
> #define XFS_DAENTER_BMAPS(mp,w)         \
>         (XFS_DAENTER_DBS(mp,w) * XFS_DAENTER_BMAP1B(mp,w))
> 
> #define XFS_DAENTER_BMAP1B(mp,w)        \
>         XFS_NEXTENTADD_SPACE_RES(mp, XFS_DAENTER_1B(mp, w), w)
> 
> So, bmbt_blks contains the full da btree split depth * the BMBT
> overhead for a single block allocation:
> 
> #define XFS_EXTENTADD_SPACE_RES(mp,w)   (XFS_BM_MAXLEVELS(mp,w) - 1)
> #define XFS_NEXTENTADD_SPACE_RES(mp,b,w)\
>         (((b + XFS_MAX_CONTIG_EXTENTS_PER_BLOCK(mp) - 1) / \
> 	          XFS_MAX_CONTIG_EXTENTS_PER_BLOCK(mp)) * \
> 		            XFS_EXTENTADD_SPACE_RES(mp,w))
> 
> XFS_NEXTENTADD_SPACE_RES(1) = ((1 + N - 1) / N) * (XFS_BM_MAXLEVELS - 1)
> 		= (XFS_BM_MAXLEVELS - 1)
> 
> So, bmbt_blks = XFS_DA_NODE_MAXDEPTH * (XFS_BM_MAXLEVELS - 1)
> 
> IOWs, this bmbt reservation is assuming a full height BMBT
> modification on *every* dabtree node allocation. IOWs, we're
> reserving multiple times the log space for potential bmbt
> modifications than we are for the entire dabtree modification.
> That's why the individual dabtree reservations are so big....
> 
> > +	max_rmt_blks = xfs_attr3_rmt_blocks(mp, XATTR_SIZE_MAX);
> > +	bmbt_blks += XFS_NEXTENTADD_SPACE_RES(mp, max_rmt_blks, XFS_ATTR_FORK);
> 
> And this assumes we are going to log at least another full bmbt
> modification.
> 
> IT seems to me that the worst case here is one full split and then
> every other allocation inserts at the start of an existing block and
> so updates pointers all the way up to the root. The impact is
> limited, though, because XFS_DA_NODE_MAXDEPTH = 5 and so the attr
> fork BMBT tree is not likely to reach anywhere near it's max depth
> on large filesystems.....
> 
> >  	return XFS_DQUOT_LOGRES(mp) +
> >  		xfs_calc_inode_res(mp, 1) +
> >  		xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) +
> > +		xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) +
> > +		xfs_calc_buf_res(da_blks, XFS_FSB_TO_B(mp, 1)) +
> > +		xfs_calc_buf_res(bmbt_blks, XFS_FSB_TO_B(mp, 1)) +
> > +		xfs_calc_buf_res(xfs_allocfree_log_count(mp, da_blks),
> >  				 XFS_FSB_TO_B(mp, 1));
> 
> Given the above, this looks OK. Worst case BMBT usage looks
> excessive, but there is a chance it could be required...
> 
> > diff --git a/fs/xfs/libxfs/xfs_trans_space.h b/fs/xfs/libxfs/xfs_trans_space.h
> > index 88221c7a04ccf..6a22ad11b3825 100644
> > --- a/fs/xfs/libxfs/xfs_trans_space.h
> > +++ b/fs/xfs/libxfs/xfs_trans_space.h
> > @@ -38,8 +38,14 @@
> >  
> >  #define	XFS_DAENTER_1B(mp,w)	\
> >  	((w) == XFS_DATA_FORK ? (mp)->m_dir_geo->fsbcount : 1)
> > +/*
> > + * xattr set operation can cause the da btree to split twice in the
> > + * worst case. The double split is actually an extra leaf node rather
> > + * than a complete split of blocks in the path from root to a
> > + * leaf. The '1' in the macro below accounts for the extra leaf node.
> 
> It's not a double tree split, so don't describe it that way and then
> have to explain that it's not a double tree split!
> 
> /*
>  * When inserting a large local record into the dabtree leaf, we may
>  * need to split the leaf twice to make room to fit the new record
>  * into the new leaf. This double leaf split still only requires a
>  * single datree path update as the inserted leaves are at adjacent
>  * indexes. Hence we only need to account for an the extra leaf
>  * block in the attribute fork here.
>  */

Sure. I will change the comment. Thanks for the review.

-- 
chandan






[Index of Archives]     [XFS Filesystem Development (older mail)]     [Linux Filesystem Development]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux RAID]     [Linux SCSI]


  Powered by Linux