summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2020-10-25 17:14:51 -0700
committerDarrick J. Wong <darrick.wong@oracle.com>2020-10-26 18:32:19 -0700
commitc199963c19551aa14e4f8fb2d5e5753ddbec4877 (patch)
tree8c5e11d8dfab80b3275784cd1d9a6e2268589004
parent3d46c44ae16bada5457adf9baffd4d19a611e6eb (diff)
xfs: force inode inactivation and retry fs writes when there isn't space
Any time we try to modify a file's contents and it fails due to ENOSPC or EDQUOT, force inactivation work to free up some resources and try one more time. Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
-rw-r--r--fs/xfs/xfs_iomap.c14
1 files changed, 14 insertions, 0 deletions
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index 045bb386a20f..669878f3a49e 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -877,6 +877,7 @@ xfs_buffered_write_iomap_begin(
struct xfs_iext_cursor icur, ccur;
xfs_fsblock_t prealloc_blocks = 0;
bool eof = false, cow_eof = false, shared = false;
+ bool cleared_space = false;
int allocfork = XFS_DATA_FORK;
int error = 0;
@@ -887,6 +888,7 @@ xfs_buffered_write_iomap_begin(
ASSERT(!XFS_IS_REALTIME_INODE(ip));
+start_over:
xfs_ilock(ip, XFS_ILOCK_EXCL);
if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(&ip->i_df)) ||
@@ -1036,6 +1038,18 @@ retry:
break;
case -ENOSPC:
case -EDQUOT:
+ /*
+ * If the delalloc reservation failed due to a lack of space,
+ * try to flush inactive inodes to free some space.
+ */
+ if (!cleared_space) {
+ cleared_space = true;
+ allocfork = XFS_DATA_FORK;
+ xfs_iunlock(ip, XFS_ILOCK_EXCL);
+ xfs_inactive_force(mp);
+ error = 0;
+ goto start_over;
+ }
/* retry without any preallocation */
trace_xfs_delalloc_enospc(ip, offset, count);
if (prealloc_blocks) {