summaryrefslogtreecommitdiff
path: root/fs/xfs/xfs_icache.c
diff options
context:
space:
mode:
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