diff options
author | Darrick J. Wong <darrick.wong@oracle.com> | 2020-10-25 17:14:51 -0700 |
---|---|---|
committer | Darrick J. Wong <darrick.wong@oracle.com> | 2020-10-26 18:32:19 -0700 |
commit | c199963c19551aa14e4f8fb2d5e5753ddbec4877 (patch) | |
tree | 8c5e11d8dfab80b3275784cd1d9a6e2268589004 | |
parent | 3d46c44ae16bada5457adf9baffd4d19a611e6eb (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.c | 14 |
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) { |