All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Darrick J. Wong" <djwong@kernel.org>
To: Brian Foster <bfoster@redhat.com>
Cc: linux-xfs@vger.kernel.org, hch@infradead.org, david@fromorbit.com
Subject: Re: [PATCH 07/12] xfs: flush eof/cowblocks if we can't reserve quota for file blocks
Date: Fri, 29 Jan 2021 09:47:16 -0800	[thread overview]
Message-ID: <20210129174716.GI7695@magnolia> (raw)
In-Reply-To: <20210129160944.GE2665284@bfoster>

On Fri, Jan 29, 2021 at 11:09:44AM -0500, Brian Foster wrote:
> On Thu, Jan 28, 2021 at 06:18:26PM -0800, Darrick J. Wong wrote:
> > From: Darrick J. Wong <djwong@kernel.org>
> > 
> > If a fs modification (data write, reflink, xattr set, fallocate, etc.)
> > is unable to reserve enough quota to handle the modification, try
> > clearing whatever space the filesystem might have been hanging onto in
> > the hopes of speeding up the filesystem.  The flushing behavior will
> > become particularly important when we add deferred inode inactivation
> > because that will increase the amount of space that isn't actively tied
> > to user data.
> > 
> > Signed-off-by: Darrick J. Wong <djwong@kernel.org>
> > ---
> >  fs/xfs/xfs_quota.h       |    7 +++--
> >  fs/xfs/xfs_reflink.c     |    7 ++++-
> >  fs/xfs/xfs_trans.c       |   12 +++++++-
> >  fs/xfs/xfs_trans_dquot.c |   69 ++++++++++++++++++++++++++++++++++++++++++----
> >  4 files changed, 84 insertions(+), 11 deletions(-)
> > 
> > 
> ...
> > diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
> > index 6c68635cc6ac..1217e6c41aa5 100644
> > --- a/fs/xfs/xfs_trans.c
> > +++ b/fs/xfs/xfs_trans.c
> ...
> > @@ -1046,8 +1047,10 @@ xfs_trans_alloc_inode(
> >  {
> >  	struct xfs_trans	*tp;
> >  	struct xfs_mount	*mp = ip->i_mount;
> > +	unsigned int		qretry = 0;
> >  	int			error;
> >  
> > +retry:
> >  	error = xfs_trans_alloc(mp, resv, dblocks,
> >  			rblocks / mp->m_sb.sb_rextsize,
> >  			force ? XFS_TRANS_RESERVE : 0, &tp);
> > @@ -1064,9 +1067,16 @@ xfs_trans_alloc_inode(
> >  		goto out_cancel;
> >  	}
> >  
> > -	error = xfs_trans_reserve_quota_nblks(tp, ip, dblocks, rblocks, force);
> > +	error = xfs_trans_reserve_quota_nblks(tp, ip, dblocks, rblocks, force,
> > +			&qretry);
> >  	if (error)
> >  		goto out_cancel;
> > +	if (qretry) {
> > +		xfs_trans_cancel(tp);
> > +		xfs_iunlock(ip, XFS_ILOCK_EXCL);
> > +		xfs_blockgc_free_quota(ip, 0);
> > +		goto retry;
> > +	}
> 
> I'm not following why we need to plumb this retry logic down through the
> quota code and then down into a separate helper (which makes the whole
> thing rather circuitous at first glance). Can't we check for
> EDQUOT/ENOSPC here and retry using a local boolean?

Well now that I've rewritten the entry functions I guess this seems
obvious in retrospect.  Forest through the trees, etc. :)

Will change.

--D

> Brian
> 
> >  
> >  	*tpp = tp;
> >  	return 0;
> > diff --git a/fs/xfs/xfs_trans_dquot.c b/fs/xfs/xfs_trans_dquot.c
> > index 73ef5994d09d..cb1fa4b047d6 100644
> > --- a/fs/xfs/xfs_trans_dquot.c
> > +++ b/fs/xfs/xfs_trans_dquot.c
> > @@ -770,11 +770,67 @@ xfs_trans_reserve_quota_bydquots(
> >  	return error;
> >  }
> >  
> > +/*
> > + * Decide what to do after an attempt to reserve some quota.  This will set
> > + * the retry and error parameters as needed, and returns true if the quota
> > + * reservation succeeded.
> > + */
> > +static inline bool
> > +reservation_success(
> > +	unsigned int		qflag,
> > +	unsigned int		*retry,
> > +	int			*error)
> > +{
> > +	/*
> > +	 * The caller is not interested in retries.  Return whether or not we
> > +	 * got an error code.
> > +	 */
> > +	if (retry == NULL)
> > +		return *error == 0;
> > +
> > +	if (*error == -EDQUOT || *error == -ENOSPC) {
> > +		/*
> > +		 * There isn't enough quota left to allow the reservation.
> > +		 *
> > +		 * If none of the retry bits are set, this is the first time
> > +		 * that we failed a quota reservation.  Zero the error code and
> > +		 * set the appropriate quota flag in *retry to encourage the
> > +		 * xfs_trans_reserve_quota_nblks caller to clear some space and
> > +		 * call back.
> > +		 *
> > +		 * If any of the retry bits are set, this means that we failed
> > +		 * the quota reservation once before, tried to free some quota,
> > +		 * and have now failed the second quota reservation attempt.
> > +		 * Pass the error back to the caller; we're done.
> > +		 */
> > +		if (!(*retry))
> > +			*error = 0;
> > +
> > +		*retry |= qflag;
> > +		return false;
> > +	}
> > +
> > +	/* A non-quota error occurred; there is no retry. */
> > +	if (*error)
> > +		return false;
> > +
> > +	/*
> > +	 * The reservation succeeded.  Clear the quota flag from the retry
> > +	 * state because there is nothing to retry.
> > +	 */
> > +	*retry &= ~qflag;
> > +	return true;
> > +}
> >  
> >  /*
> > - * Lock the dquot and change the reservation if we can.
> > - * This doesn't change the actual usage, just the reservation.
> > - * The inode sent in is locked.
> > + * Lock the dquot and change the reservation if we can.  This doesn't change
> > + * the actual usage, just the reservation.  The caller must hold ILOCK_EXCL on
> > + * the inode.  If @retry is not a NULL pointer, the caller must ensure that
> > + * *retry is set to 0 before the first time this function is called.
> > + *
> > + * If the quota reservation fails because we hit a quota limit (and retry is
> > + * not a NULL pointer, and *retry is zero), this function will set *retry to
> > + * nonzero and return zero.
> >   */
> >  int
> >  xfs_trans_reserve_quota_nblks(
> > @@ -782,7 +838,8 @@ xfs_trans_reserve_quota_nblks(
> >  	struct xfs_inode	*ip,
> >  	int64_t			dblocks,
> >  	int64_t			rblocks,
> > -	bool			force)
> > +	bool			force,
> > +	unsigned int		*retry)
> >  {
> >  	struct xfs_mount	*mp = ip->i_mount;
> >  	unsigned int		qflags = 0;
> > @@ -801,14 +858,14 @@ xfs_trans_reserve_quota_nblks(
> >  	error = xfs_trans_reserve_quota_bydquots(tp, mp, ip->i_udquot,
> >  			ip->i_gdquot, ip->i_pdquot, dblocks, 0,
> >  			XFS_QMOPT_RES_REGBLKS | qflags);
> > -	if (error)
> > +	if (!reservation_success(XFS_QMOPT_RES_REGBLKS, retry, &error))
> >  		return error;
> >  
> >  	/* Do the same but for realtime blocks. */
> >  	error = xfs_trans_reserve_quota_bydquots(tp, mp, ip->i_udquot,
> >  			ip->i_gdquot, ip->i_pdquot, rblocks, 0,
> >  			XFS_QMOPT_RES_RTBLKS | qflags);
> > -	if (error) {
> > +	if (!reservation_success(XFS_QMOPT_RES_RTBLKS, retry, &error)) {
> >  		xfs_trans_reserve_quota_bydquots(tp, mp, ip->i_udquot,
> >  				ip->i_gdquot, ip->i_pdquot, -dblocks, 0,
> >  				XFS_QMOPT_RES_REGBLKS);
> > 
> 

  parent reply	other threads:[~2021-01-29 17:50 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-01-29  2:17 [PATCHSET v6 00/12] xfs: try harder to reclaim space when we run out Darrick J. Wong
2021-01-29  2:17 ` [PATCH 01/12] xfs: trigger all block gc scans when low on quota space Darrick J. Wong
2021-01-29  2:17 ` [PATCH 02/12] xfs: don't stall cowblocks scan if we can't take locks Darrick J. Wong
2021-01-29  2:18 ` [PATCH 03/12] xfs: xfs_inode_free_quota_blocks should scan project quota Darrick J. Wong
2021-01-29  2:18 ` [PATCH 04/12] xfs: move and rename xfs_inode_free_quota_blocks to avoid conflicts Darrick J. Wong
2021-01-29  2:18 ` [PATCH 05/12] xfs: pass flags and return gc errors from xfs_blockgc_free_quota Darrick J. Wong
2021-01-29  2:18 ` [PATCH 06/12] xfs: try worst case space reservation upfront in xfs_reflink_remap_extent Darrick J. Wong
2021-01-29  2:18 ` [PATCH 07/12] xfs: flush eof/cowblocks if we can't reserve quota for file blocks Darrick J. Wong
     [not found]   ` <20210129160944.GE2665284@bfoster>
2021-01-29 17:47     ` Darrick J. Wong [this message]
2021-01-29  2:18 ` [PATCH 08/12] xfs: flush eof/cowblocks if we can't reserve quota for inode creation Darrick J. Wong
2021-01-29  2:18 ` [PATCH 09/12] xfs: flush eof/cowblocks if we can't reserve quota for chown Darrick J. Wong
2021-01-29  2:18 ` [PATCH 10/12] xfs: add a tracepoint for blockgc scans Darrick J. Wong
2021-01-29  2:18 ` [PATCH 11/12] xfs: refactor xfs_icache_free_{eof,cow}blocks call sites Darrick J. Wong
2021-01-29  2:18 ` [PATCH 12/12] xfs: flush speculative space allocations when we run out of space Darrick J. Wong
     [not found]   ` <20210129161047.GH2665284@bfoster>
2021-01-29 17:34     ` Darrick J. Wong
  -- strict thread matches above, loose matches on Subject: below --
2021-02-01  2:05 [PATCHSET v7 00/12] xfs: try harder to reclaim space when we run out Darrick J. Wong
2021-02-01  2:06 ` [PATCH 07/12] xfs: flush eof/cowblocks if we can't reserve quota for file blocks Darrick J. Wong
2021-02-01 12:32   ` Christoph Hellwig
2021-02-01 19:01     ` Darrick J. Wong
2021-02-02 15:38   ` Brian Foster
2021-02-02 16:53     ` Darrick J. Wong

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210129174716.GI7695@magnolia \
    --to=djwong@kernel.org \
    --cc=bfoster@redhat.com \
    --cc=david@fromorbit.com \
    --cc=hch@infradead.org \
    --cc=linux-xfs@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.