xfs: flush eof/cowblocks if we can't reserve quota for file blocks
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> Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Brian Foster <bfoster@redhat.com>
This commit is contained in:
parent
4ca7420568
commit
766aabd599
|
@ -1092,6 +1092,11 @@ xfs_reflink_remap_extent(
|
||||||
* count. This is suboptimal, but the VFS flushed the dest range
|
* count. This is suboptimal, but the VFS flushed the dest range
|
||||||
* before we started. That should have removed all the delalloc
|
* before we started. That should have removed all the delalloc
|
||||||
* reservations, but we code defensively.
|
* reservations, but we code defensively.
|
||||||
|
*
|
||||||
|
* xfs_trans_alloc_inode above already tried to grab an even larger
|
||||||
|
* quota reservation, and kicked off a blockgc scan if it couldn't.
|
||||||
|
* If we can't get a potentially smaller quota reservation now, we're
|
||||||
|
* done.
|
||||||
*/
|
*/
|
||||||
if (!quota_reserved && !smap_real && dmap_written) {
|
if (!quota_reserved && !smap_real && dmap_written) {
|
||||||
error = xfs_trans_reserve_quota_nblks(tp, ip,
|
error = xfs_trans_reserve_quota_nblks(tp, ip,
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include "xfs_inode.h"
|
#include "xfs_inode.h"
|
||||||
#include "xfs_dquot_item.h"
|
#include "xfs_dquot_item.h"
|
||||||
#include "xfs_dquot.h"
|
#include "xfs_dquot.h"
|
||||||
|
#include "xfs_icache.h"
|
||||||
|
|
||||||
kmem_zone_t *xfs_trans_zone;
|
kmem_zone_t *xfs_trans_zone;
|
||||||
|
|
||||||
|
@ -1046,8 +1047,10 @@ xfs_trans_alloc_inode(
|
||||||
{
|
{
|
||||||
struct xfs_trans *tp;
|
struct xfs_trans *tp;
|
||||||
struct xfs_mount *mp = ip->i_mount;
|
struct xfs_mount *mp = ip->i_mount;
|
||||||
|
bool retried = false;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
|
retry:
|
||||||
error = xfs_trans_alloc(mp, resv, dblocks,
|
error = xfs_trans_alloc(mp, resv, dblocks,
|
||||||
rblocks / mp->m_sb.sb_rextsize,
|
rblocks / mp->m_sb.sb_rextsize,
|
||||||
force ? XFS_TRANS_RESERVE : 0, &tp);
|
force ? XFS_TRANS_RESERVE : 0, &tp);
|
||||||
|
@ -1065,6 +1068,13 @@ xfs_trans_alloc_inode(
|
||||||
}
|
}
|
||||||
|
|
||||||
error = xfs_trans_reserve_quota_nblks(tp, ip, dblocks, rblocks, force);
|
error = xfs_trans_reserve_quota_nblks(tp, ip, dblocks, rblocks, force);
|
||||||
|
if ((error == -EDQUOT || error == -ENOSPC) && !retried) {
|
||||||
|
xfs_trans_cancel(tp);
|
||||||
|
xfs_iunlock(ip, XFS_ILOCK_EXCL);
|
||||||
|
xfs_blockgc_free_quota(ip, 0);
|
||||||
|
retried = true;
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
if (error)
|
if (error)
|
||||||
goto out_cancel;
|
goto out_cancel;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue