• D
    xfs: reserve quota for dir expansion when linking/unlinking files · 871b9316
    Darrick J. Wong 提交于
    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: NDarrick J. Wong <djwong@kernel.org>
    Reviewed-by: NDave Chinner <dchinner@redhat.com>
    871b9316
xfs_inode.c 105.0 KB