summaryrefslogtreecommitdiff
path: root/fs/xfs/xfs_icache.c
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2020-02-19 17:02:04 -0800
committerDarrick J. Wong <darrick.wong@oracle.com>2020-06-01 21:16:35 -0700
commitcd9cd0a830470a9510dbd63f986b9befae6c6d3c (patch)
treed123ed2b39eea8377c5fb67e89572097f6e109b0 /fs/xfs/xfs_icache.c
parent11ccd1f3e71f45a0223b95f1c0640ef688cf96f9 (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.c40
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