On Thu, Mar 10, 2022 at 01:53:33PM -0800, Darrick J. Wong wrote: > From: Darrick J. Wong <djwong@xxxxxxxxxx> > > XFS does not reserve quota for directory expansion when linking or > unlinking children from 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 link()/unlink() to exceed > quota. > > The fix for this is nuanced -- link operations don't always expand the > directory, and we allow a link to proceed with no space reservation if > we don't need to add a block to the directory to handle the addition. > Unlink operations generally do not expand the directory (you'd have to > free a block and then cause a btree split) and we can defer the > directory block freeing if there is no space reservation. > > Moreover, 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. > > To fix both cases, create a new xfs_trans_alloc_dir function that > allocates the transaction, locks and joins the inodes, and reserves > quota for the directory. If there isn't sufficient space or quota, > we'll switch the caller to reservationless mode. This should prevent > quota usage overruns with the least restriction in functionality. > > Signed-off-by: Darrick J. Wong <djwong@xxxxxxxxxx> > --- > fs/xfs/xfs_inode.c | 46 ++++++++++------------------ > fs/xfs/xfs_trans.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++ > fs/xfs/xfs_trans.h | 3 ++ > 3 files changed, 106 insertions(+), 29 deletions(-) Looks good. Reviewed-by: Dave Chinner <dchinner@xxxxxxxxxx> -- Dave Chinner david@xxxxxxxxxxxxx