summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2019-08-30 15:45:10 -0700
committerDarrick J. Wong <darrick.wong@oracle.com>2019-10-09 09:39:24 -0700
commita6ab93ef18f917e442b2ce300b10c1d6b5c53579 (patch)
tree79adc81bff2983f95e9cfc54efdc01457be28ba7
parent4ec4b2586685b32e1b69bd39a1c193fd4a21d121 (diff)
xfs: force inactivation before fallocate when space is low
If we think that inactivation will free enough blocks to make it easier to satisfy an fallocate request, force inactivation. Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
-rw-r--r--fs/xfs/xfs_bmap_util.c38
1 files changed, 38 insertions, 0 deletions
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
index 484df8c7f02c..f110f2a3dadc 100644
--- a/fs/xfs/xfs_bmap_util.c
+++ b/fs/xfs/xfs_bmap_util.c
@@ -28,6 +28,7 @@
#include "xfs_icache.h"
#include "xfs_iomap.h"
#include "xfs_reflink.h"
+#include "xfs_sb.h"
/* Kernel only BMAP related definitions and functions */
@@ -836,6 +837,41 @@ out_unlock:
return error;
}
+/*
+ * If we suspect that the target device isn't going to be able to satisfy the
+ * entire request, try forcing inode inactivation to free up space. While it's
+ * perfectly fine to fill a preallocation request with a bunch of short
+ * extents, we'd prefer to do the inactivation work now to combat long term
+ * fragmentation in new file data.
+ */
+static void
+xfs_alloc_reclaim_inactive_space(
+ struct xfs_mount *mp,
+ bool is_rt,
+ xfs_filblks_t allocatesize_fsb)
+{
+ struct xfs_perag *pag;
+ struct xfs_sb *sbp = &mp->m_sb;
+ xfs_extlen_t free;
+ xfs_agnumber_t agno;
+
+ if (is_rt) {
+ if (sbp->sb_frextents * sbp->sb_rextsize >= allocatesize_fsb)
+ return;
+ } else {
+ for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) {
+ pag = xfs_perag_get(mp, agno);
+ free = pag->pagf_freeblks;
+ xfs_perag_put(pag);
+
+ if (free >= allocatesize_fsb)
+ return;
+ }
+ }
+
+ xfs_inactive_force(mp);
+}
+
int
xfs_alloc_file_space(
struct xfs_inode *ip,
@@ -925,6 +961,8 @@ xfs_alloc_file_space(
quota_flag = XFS_QMOPT_RES_REGBLKS;
}
+ xfs_alloc_reclaim_inactive_space(mp, rt, allocatesize_fsb);
+
/*
* Allocate and setup the transaction.
*/