Re: [PATCH 01/11] xfs: refactor messy xfs_inode_free_quota_* functions

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

 



On Mon, Jan 25, 2021 at 01:13:31PM -0500, Brian Foster wrote:
> On Sat, Jan 23, 2021 at 10:52:05AM -0800, Darrick J. Wong wrote:
> > From: Darrick J. Wong <djwong@xxxxxxxxxx>
> > 
> > The functions to run an eof/cowblocks scan to try to reduce quota usage
> > are kind of a mess -- the logic repeatedly initializes an eofb structure
> > and there are logic bugs in the code that result in the cowblocks scan
> > never actually happening.
> > 
> > Replace all three functions with a single function that fills out an
> > eofb if we're low on quota and runs both eof and cowblocks scans.
> > 
> 
> It would be nice to be a bit more explicit about the scanning bug(s)
> being fixed here. It looks like a couple potential issues are the first
> scan clearing the low free space state on the associated quotas, and
> also only falling back to the cowblocks scan if the eofblocks scan
> doesn't do anything. If that's the gist of this patch, I'd suggest to
> change the patch subject as well since "refactor messy functions"
> doesn't really convey that we're fixing some logic issues. Perhaps
> something like "xfs: trigger all block scans on low quota space" would
> be more accurate?

Yes, that sounds good.  I'll change the commit message to:

xfs: trigger all block gc scans when low on quota space

The functions to run an eof/cowblocks scan to try to reduce quota usage
are kind of a mess -- the logic repeatedly initializes an eofb structure
and there are logic bugs in the code that result in the cowblocks scan
never actually happening.

Replace all three functions with a single function that fills out an
eofb and runs both eof and cowblocks scans.

--D

> Otherwise for the code changes:
> 
> Reviewed-by: Brian Foster <bfoster@xxxxxxxxxx>
> 
> > Signed-off-by: Darrick J. Wong <djwong@xxxxxxxxxx>
> > Reviewed-by: Christoph Hellwig <hch@xxxxxx>
> > ---
> >  fs/xfs/xfs_file.c   |   15 ++++++---------
> >  fs/xfs/xfs_icache.c |   46 ++++++++++++++++------------------------------
> >  fs/xfs/xfs_icache.h |    4 ++--
> >  3 files changed, 24 insertions(+), 41 deletions(-)
> > 
> > 
> > diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
> > index 5d4a66c72c78..69879237533b 100644
> > --- a/fs/xfs/xfs_file.c
> > +++ b/fs/xfs/xfs_file.c
> > @@ -713,7 +713,7 @@ xfs_file_buffered_write(
> >  	struct inode		*inode = mapping->host;
> >  	struct xfs_inode	*ip = XFS_I(inode);
> >  	ssize_t			ret;
> > -	int			enospc = 0;
> > +	bool			cleared_space = false;
> >  	int			iolock;
> >  
> >  	if (iocb->ki_flags & IOCB_NOWAIT)
> > @@ -745,19 +745,16 @@ xfs_file_buffered_write(
> >  	 * also behaves as a filter to prevent too many eofblocks scans from
> >  	 * running at the same time.
> >  	 */
> > -	if (ret == -EDQUOT && !enospc) {
> > +	if (ret == -EDQUOT && !cleared_space) {
> >  		xfs_iunlock(ip, iolock);
> > -		enospc = xfs_inode_free_quota_eofblocks(ip);
> > -		if (enospc)
> > -			goto write_retry;
> > -		enospc = xfs_inode_free_quota_cowblocks(ip);
> > -		if (enospc)
> > +		cleared_space = xfs_inode_free_quota_blocks(ip);
> > +		if (cleared_space)
> >  			goto write_retry;
> >  		iolock = 0;
> > -	} else if (ret == -ENOSPC && !enospc) {
> > +	} else if (ret == -ENOSPC && !cleared_space) {
> >  		struct xfs_eofblocks eofb = {0};
> >  
> > -		enospc = 1;
> > +		cleared_space = true;
> >  		xfs_flush_inodes(ip->i_mount);
> >  
> >  		xfs_iunlock(ip, iolock);
> > diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
> > index deb99300d171..c71eb15e3835 100644
> > --- a/fs/xfs/xfs_icache.c
> > +++ b/fs/xfs/xfs_icache.c
> > @@ -1397,33 +1397,31 @@ xfs_icache_free_eofblocks(
> >  }
> >  
> >  /*
> > - * Run eofblocks scans on the quotas applicable to the inode. For inodes with
> > - * multiple quotas, we don't know exactly which quota caused an allocation
> > + * Run cow/eofblocks scans on the quotas applicable to the inode. For inodes
> > + * with multiple quotas, we don't know exactly which quota caused an allocation
> >   * failure. We make a best effort by including each quota under low free space
> >   * conditions (less than 1% free space) in the scan.
> >   */
> > -static int
> > -__xfs_inode_free_quota_eofblocks(
> > -	struct xfs_inode	*ip,
> > -	int			(*execute)(struct xfs_mount *mp,
> > -					   struct xfs_eofblocks	*eofb))
> > +bool
> > +xfs_inode_free_quota_blocks(
> > +	struct xfs_inode	*ip)
> >  {
> > -	int scan = 0;
> > -	struct xfs_eofblocks eofb = {0};
> > -	struct xfs_dquot *dq;
> > +	struct xfs_eofblocks	eofb = {0};
> > +	struct xfs_dquot	*dq;
> > +	bool			do_work = false;
> >  
> >  	/*
> >  	 * Run a sync scan to increase effectiveness and use the union filter to
> >  	 * cover all applicable quotas in a single scan.
> >  	 */
> > -	eofb.eof_flags = XFS_EOF_FLAGS_UNION|XFS_EOF_FLAGS_SYNC;
> > +	eofb.eof_flags = XFS_EOF_FLAGS_UNION | XFS_EOF_FLAGS_SYNC;
> >  
> >  	if (XFS_IS_UQUOTA_ENFORCED(ip->i_mount)) {
> >  		dq = xfs_inode_dquot(ip, XFS_DQTYPE_USER);
> >  		if (dq && xfs_dquot_lowsp(dq)) {
> >  			eofb.eof_uid = VFS_I(ip)->i_uid;
> >  			eofb.eof_flags |= XFS_EOF_FLAGS_UID;
> > -			scan = 1;
> > +			do_work = true;
> >  		}
> >  	}
> >  
> > @@ -1432,21 +1430,16 @@ __xfs_inode_free_quota_eofblocks(
> >  		if (dq && xfs_dquot_lowsp(dq)) {
> >  			eofb.eof_gid = VFS_I(ip)->i_gid;
> >  			eofb.eof_flags |= XFS_EOF_FLAGS_GID;
> > -			scan = 1;
> > +			do_work = true;
> >  		}
> >  	}
> >  
> > -	if (scan)
> > -		execute(ip->i_mount, &eofb);
> > +	if (!do_work)
> > +		return false;
> >  
> > -	return scan;
> > -}
> > -
> > -int
> > -xfs_inode_free_quota_eofblocks(
> > -	struct xfs_inode *ip)
> > -{
> > -	return __xfs_inode_free_quota_eofblocks(ip, xfs_icache_free_eofblocks);
> > +	xfs_icache_free_eofblocks(ip->i_mount, &eofb);
> > +	xfs_icache_free_cowblocks(ip->i_mount, &eofb);
> > +	return true;
> >  }
> >  
> >  static inline unsigned long
> > @@ -1646,13 +1639,6 @@ xfs_icache_free_cowblocks(
> >  			XFS_ICI_COWBLOCKS_TAG);
> >  }
> >  
> > -int
> > -xfs_inode_free_quota_cowblocks(
> > -	struct xfs_inode *ip)
> > -{
> > -	return __xfs_inode_free_quota_eofblocks(ip, xfs_icache_free_cowblocks);
> > -}
> > -
> >  void
> >  xfs_inode_set_cowblocks_tag(
> >  	xfs_inode_t	*ip)
> > diff --git a/fs/xfs/xfs_icache.h b/fs/xfs/xfs_icache.h
> > index 3a4c8b382cd0..3f7ddbca8638 100644
> > --- a/fs/xfs/xfs_icache.h
> > +++ b/fs/xfs/xfs_icache.h
> > @@ -54,17 +54,17 @@ long xfs_reclaim_inodes_nr(struct xfs_mount *mp, int nr_to_scan);
> >  
> >  void xfs_inode_set_reclaim_tag(struct xfs_inode *ip);
> >  
> > +bool xfs_inode_free_quota_blocks(struct xfs_inode *ip);
> > +
> >  void xfs_inode_set_eofblocks_tag(struct xfs_inode *ip);
> >  void xfs_inode_clear_eofblocks_tag(struct xfs_inode *ip);
> >  int xfs_icache_free_eofblocks(struct xfs_mount *, struct xfs_eofblocks *);
> > -int xfs_inode_free_quota_eofblocks(struct xfs_inode *ip);
> >  void xfs_eofblocks_worker(struct work_struct *);
> >  void xfs_queue_eofblocks(struct xfs_mount *);
> >  
> >  void xfs_inode_set_cowblocks_tag(struct xfs_inode *ip);
> >  void xfs_inode_clear_cowblocks_tag(struct xfs_inode *ip);
> >  int xfs_icache_free_cowblocks(struct xfs_mount *, struct xfs_eofblocks *);
> > -int xfs_inode_free_quota_cowblocks(struct xfs_inode *ip);
> >  void xfs_cowblocks_worker(struct work_struct *);
> >  void xfs_queue_cowblocks(struct xfs_mount *);
> >  
> > 
> 



[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