summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2019-05-21 17:07:29 -0700
committerDarrick J. Wong <darrick.wong@oracle.com>2019-08-16 19:06:28 -0700
commit05b13c1a498871e2dec305e02cb1a75013f3c5e1 (patch)
tree40a22d13a23fbdbbc433c83386e0641c41f50e4e /fs
parent73835ed66ba6a38f7bf721537c0b1051e8cccf6f (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>
Diffstat (limited to 'fs')
-rw-r--r--fs/xfs/xfs_iomap.c16
1 files changed, 15 insertions, 1 deletions
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index eef047902e70..f07df3b77a22 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -572,6 +572,7 @@ xfs_file_iomap_begin_delay(
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 whichfork = XFS_DATA_FORK;
int error = 0;
@@ -579,7 +580,7 @@ xfs_file_iomap_begin_delay(
ASSERT(!xfs_get_extsz_hint(ip));
xfs_ilock(ip, XFS_ILOCK_EXCL);
-
+start_over:
if (unlikely(XFS_TEST_ERROR(
(XFS_IFORK_FORMAT(ip, XFS_DATA_FORK) != XFS_DINODE_FMT_EXTENTS &&
XFS_IFORK_FORMAT(ip, XFS_DATA_FORK) != XFS_DINODE_FMT_BTREE),
@@ -724,6 +725,19 @@ 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;
+ whichfork = XFS_DATA_FORK;
+ xfs_iunlock(ip, XFS_ILOCK_EXCL);
+ xfs_inactive_force(mp);
+ xfs_ilock(ip, XFS_ILOCK_EXCL);
+ error = 0;
+ goto start_over;
+ }
/* retry without any preallocation */
trace_xfs_delalloc_enospc(ip, offset, count);
if (prealloc_blocks) {