diff options
author | Darrick J. Wong <darrick.wong@oracle.com> | 2020-02-19 17:02:04 -0800 |
---|---|---|
committer | Darrick J. Wong <darrick.wong@oracle.com> | 2020-06-01 21:16:35 -0700 |
commit | cd9cd0a830470a9510dbd63f986b9befae6c6d3c (patch) | |
tree | d123ed2b39eea8377c5fb67e89572097f6e109b0 /fs/xfs/xfs_icache.c | |
parent | 11ccd1f3e71f45a0223b95f1c0640ef688cf96f9 (diff) |
xfs: flush speculative space allocations when we run out of spacereclaim-space-harder_2020-06-01
If a fs modification (creation, file write, reflink, etc.) is unable to
reserve enough space 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_icache.c')
-rw-r--r-- | fs/xfs/xfs_icache.c | 40 |
1 files changed, 37 insertions, 3 deletions
diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c index b1e598543b6e..cc1fb0f49854 100644 --- a/fs/xfs/xfs_icache.c +++ b/fs/xfs/xfs_icache.c @@ -26,6 +26,9 @@ #include <linux/iversion.h> +STATIC int xfs_inode_free_eofblocks(struct xfs_inode *ip, void *args); +STATIC int xfs_inode_free_cowblocks(struct xfs_inode *ip, void *args); + /* * flags for incore inode iterator */ @@ -978,6 +981,21 @@ xfs_queue_eofblocks( rcu_read_unlock(); } +/* Scan all incore inodes for block preallocations that we can remove. */ +static inline int +xfs_blockgc_scan( + struct xfs_mount *mp, + struct xfs_eofblocks *eofb) +{ + int error; + + error = xfs_icache_free_eofblocks(mp, eofb); + if (error && error != -EAGAIN) + return error; + + return xfs_icache_free_cowblocks(mp, eofb); +} + void xfs_eofblocks_worker( struct work_struct *work) @@ -1605,9 +1623,25 @@ xfs_inode_free_quota_blocks( trace_xfs_inode_free_quota_blocks(ip->i_mount, &eofb, _RET_IP_); - xfs_icache_free_eofblocks(ip->i_mount, &eofb); - xfs_icache_free_cowblocks(ip->i_mount, &eofb); - return true; + return xfs_blockgc_scan(ip->i_mount, &eofb) == 0; +} + +/* + * Try to free space in the filesystem by purging eofblocks and cowblocks. + */ +int +xfs_inode_free_blocks( + struct xfs_mount *mp, + bool sync) +{ + struct xfs_eofblocks eofb = {0}; + + if (sync) + eofb.eof_flags |= XFS_EOF_FLAGS_SYNC; + + trace_xfs_inode_free_blocks(mp, &eofb, _RET_IP_); + + return xfs_blockgc_scan(mp, &eofb); } static inline unsigned long |