From: "Darrick J. Wong" <djwong@kernel.org>
To: Dave Chinner <david@fromorbit.com>
Cc: linux-xfs@vger.kernel.org
Subject: Re: [PATCH 2/2] xfs: reserve quota for target dir expansion when renaming files
Date: Wed, 9 Mar 2022 15:36:44 -0800 [thread overview]
Message-ID: <20220309233644.GF8224@magnolia> (raw)
In-Reply-To: <20220309220553.GI661808@dread.disaster.area>
On Thu, Mar 10, 2022 at 09:05:53AM +1100, Dave Chinner wrote:
> On Wed, Mar 09, 2022 at 11:22:32AM -0800, Darrick J. Wong wrote:
> > From: Darrick J. Wong <djwong@kernel.org>
> >
> > XFS does not reserve quota for directory expansion when renaming
> > children into a directory. This means that we don't reject the
> > expansion with EDQUOT when we're at or near a hard limit, which means
> > that unprivileged userspace can use rename() to exceed quota.
> >
> > Rename operations don't always expand the target directory, and we allow
> > a rename to proceed with no space reservation if we don't need to add a
> > block to the target directory to handle the addition. Moreover, the
> > unlink operation on the source directory generally does not expand the
> > directory (you'd have to free a block and then cause a btree split) and
> > it's probably of little consequence to leave the corner case that
> > renaming a file out of a directory can increase its size.
> >
> > As with link and unlink, there is a further bug in that we do not
> > trigger the blockgc workers to try to clear space when we're out of
> > quota.
> >
> > Because rename is its own special tricky animal, we'll patch xfs_rename
> > directly to reserve quota to the rename transaction.
>
> Yeah, and this makes it even more tricky - the retry jumps back
> across the RENAME_EXCHANGE callout/exit from xfs_rename. At some
> point we need to clean up the spaghetti that rename has become.
Heh. I did that as a cleanup to the directory code ahead of the
metadata directory tree patchset.
> > Signed-off-by: Darrick J. Wong <djwong@kernel.org>
> > ---
> > fs/xfs/xfs_inode.c | 37 ++++++++++++++++++++++++++++++++++++-
> > 1 file changed, 36 insertions(+), 1 deletion(-)
> >
> >
> > diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
> > index a131bbfe74e4..8ff67b7aad53 100644
> > --- a/fs/xfs/xfs_inode.c
> > +++ b/fs/xfs/xfs_inode.c
> > @@ -3095,7 +3095,8 @@ xfs_rename(
> > bool new_parent = (src_dp != target_dp);
> > bool src_is_directory = S_ISDIR(VFS_I(src_ip)->i_mode);
> > int spaceres;
> > - int error;
> > + bool retried = false;
> > + int error, space_error;
> >
> > trace_xfs_rename(src_dp, target_dp, src_name, target_name);
> >
> > @@ -3119,9 +3120,12 @@ xfs_rename(
> > xfs_sort_for_rename(src_dp, target_dp, src_ip, target_ip, wip,
> > inodes, &num_inodes);
> >
> > +retry:
> > + space_error = 0;
> > spaceres = XFS_RENAME_SPACE_RES(mp, target_name->len);
> > error = xfs_trans_alloc(mp, &M_RES(mp)->tr_rename, spaceres, 0, 0, &tp);
> > if (error == -ENOSPC) {
> > + space_error = error;
>
> nospace_error.
Fixed.
> > spaceres = 0;
> > error = xfs_trans_alloc(mp, &M_RES(mp)->tr_rename, 0, 0, 0,
> > &tp);
> > @@ -3175,6 +3179,31 @@ xfs_rename(
> > target_dp, target_name, target_ip,
> > spaceres);
> >
> > + /*
> > + * Try to reserve quota to handle an expansion of the target directory.
> > + * We'll allow the rename to continue in reservationless mode if we hit
> > + * a space usage constraint. If we trigger reservationless mode, save
> > + * the errno if there isn't any free space in the target directory.
> > + */
> > + if (spaceres != 0) {
> > + error = xfs_trans_reserve_quota_nblks(tp, target_dp, spaceres,
> > + 0, false);
> > + if (error == -EDQUOT || error == -ENOSPC) {
> > + if (!retried) {
> > + xfs_trans_cancel(tp);
> > + xfs_blockgc_free_quota(target_dp, 0);
> > + retried = true;
> > + goto retry;
> > + }
> > +
> > + space_error = error;
> > + spaceres = 0;
> > + error = 0;
> > + }
> > + if (error)
> > + goto out_trans_cancel;
> > + }
> > +
> > /*
> > * Check for expected errors before we dirty the transaction
> > * so we can return an error without a transaction abort.
> > @@ -3215,6 +3244,8 @@ xfs_rename(
> > */
> > if (!spaceres) {
> > error = xfs_dir_canenter(tp, target_dp, target_name);
> > + if (error == -ENOSPC && space_error)
> > + error = space_error;
>
> And move this error transformation to out_trans_cancel: so it only
> has to be coded once.
>
> Other than that, it's about as clean as rename allows it to be right
> now.
Fixed.
--D
> Cheers,
>
> Dave.
> --
> Dave Chinner
> david@fromorbit.com
next prev parent reply other threads:[~2022-03-09 23:36 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-03-09 19:22 [PATCHSET v2 0/2] xfs: make quota reservations for directory changes Darrick J. Wong
2022-03-09 19:22 ` [PATCH 1/2] xfs: reserve quota for dir expansion when linking/unlinking files Darrick J. Wong
2022-03-09 21:48 ` Dave Chinner
2022-03-09 23:33 ` Darrick J. Wong
2022-03-10 1:50 ` Dave Chinner
2022-03-09 19:22 ` [PATCH 2/2] xfs: reserve quota for target dir expansion when renaming files Darrick J. Wong
2022-03-09 22:05 ` Dave Chinner
2022-03-09 23:36 ` Darrick J. Wong [this message]
-- strict thread matches above, loose matches on Subject: below --
2022-03-10 21:53 [PATCHSET v3 0/2] xfs: make quota reservations for directory changes Darrick J. Wong
2022-03-10 21:53 ` [PATCH 2/2] xfs: reserve quota for target dir expansion when renaming files Darrick J. Wong
2022-03-10 22:28 ` Dave Chinner
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=20220309233644.GF8224@magnolia \
--to=djwong@kernel.org \
--cc=david@fromorbit.com \
--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.