diff options
author | Darrick J. Wong <darrick.wong@oracle.com> | 2019-08-30 15:45:05 -0700 |
---|---|---|
committer | Darrick J. Wong <darrick.wong@oracle.com> | 2019-10-19 10:39:11 -0700 |
commit | 0eb7dd4e4e25147ec47adc54e30fda87d071ab27 (patch) | |
tree | d00f579c7946530f719d1d839b6c5fbcc57357de /fs/xfs/xfs_bmap_util.c | |
parent | 9e67ed13c6823f164b6617fa812f648548ec2310 (diff) |
xfs: flush speculative space allocations when we run out of quota
If a fs modification (creation, file write, reflink, 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 <darrick.wong@oracle.com>
Diffstat (limited to 'fs/xfs/xfs_bmap_util.c')
-rw-r--r-- | fs/xfs/xfs_bmap_util.c | 17 |
1 files changed, 17 insertions, 0 deletions
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index 8088b99c2d16..b8e2bff30704 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c @@ -900,6 +900,7 @@ xfs_alloc_file_space( */ while (allocatesize_fsb && !error) { xfs_fileoff_t s, e; + bool cleared_space = false; /* * Determine space reservations for data/realtime. @@ -942,6 +943,7 @@ xfs_alloc_file_space( /* * Allocate and setup the transaction. */ +retry: error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, resrtextents, 0, &tp); @@ -958,6 +960,20 @@ xfs_alloc_file_space( xfs_ilock(ip, XFS_ILOCK_EXCL); error = xfs_trans_reserve_quota_nblks(tp, ip, qblocks, 0, quota_flag); + /* + * We weren't able to reserve enough quota to handle fallocate. + * Flush any disk space that was being held in the hopes of + * speeding up the filesystem. We hold the IOLOCK so we cannot + * do a synchronous scan. + */ + if ((error == -ENOSPC || error == -EDQUOT) && !cleared_space) { + xfs_trans_cancel(tp); + xfs_iunlock(ip, XFS_ILOCK_EXCL); + cleared_space = xfs_inode_free_quota_blocks(ip, false); + if (cleared_space) + goto retry; + goto error2; + } if (error) goto error1; @@ -996,6 +1012,7 @@ error0: /* unlock inode, unreserve quota blocks, cancel trans */ error1: /* Just cancel transaction */ xfs_trans_cancel(tp); xfs_iunlock(ip, XFS_ILOCK_EXCL); +error2: return error; } |