Re: [PATCH 06/11] xfs: flush eof/cowblocks if we can't reserve quota for file blocks

Brian Foster
2021-01-25T18:18:55Z

On Sun, Jan 24, 2021 at 09:39:53AM +0000, Christoph Hellwig wrote:
> > + /* We only allow one retry for EDQUOT/ENOSPC. */
> > + if (*retry || (error != -EDQUOT && error != -ENOSPC)) {
> > + *retry = false;
> > + return error;
> > + }
>
> > + /* Release resources, prepare for scan. */
> > + xfs_trans_cancel(*tpp);
> > + *tpp = NULL;
> > + xfs_iunlock(ip, XFS_ILOCK_EXCL);
> > +
> > + /* Try to free some quota for this file's dquots. */
> > + *retry = true;
> > + xfs_blockgc_free_quota(ip, 0);
> > + return 0;
>
> I till have grave reservations about this calling conventions. And if
> you just remove the unlock and th call to xfs_blockgc_free_quota here
> we don't equire a whole lot of boilerplate code in the callers while
> making the code possible to reason about for a mere human.
>

I agree that the retry pattern is rather odd. I'm curious, is there a
specific reason this scanning task has to execute outside of transaction
context in the first place? Assuming it does because the underlying work
may involve more transactions or whatnot, I'm wondering if this logic
could be buried further down in the transaction allocation path.

For example, if we passed the quota reservation and inode down into a
new variant of xfs_trans_alloc(), it could acquire the ilock and attempt
the quota reservation as a final step (to avoid adding an extra
unconditional ilock cycle). If quota res fails, iunlock and release the
log res internally and perform the scan. From there, perhaps we could
retry the quota reservation immediately without logres or the ilock by
saving references to the dquots, and then only reacquire logres/ilock on
success..? Just thinking out loud so that might require further
thought...

Brian