diff options
author | Darrick J. Wong <darrick.wong@oracle.com> | 2019-05-21 17:07:29 -0700 |
---|---|---|
committer | Darrick J. Wong <darrick.wong@oracle.com> | 2019-08-16 19:06:28 -0700 |
commit | 05b13c1a498871e2dec305e02cb1a75013f3c5e1 (patch) | |
tree | 40a22d13a23fbdbbc433c83386e0641c41f50e4e /fs | |
parent | 73835ed66ba6a38f7bf721537c0b1051e8cccf6f (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.c | 16 |
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) { |