diff options
Diffstat (limited to 'fs/xfs/xfs_reflink.c')
-rw-r--r-- | fs/xfs/xfs_reflink.c | 23 |
1 files changed, 23 insertions, 0 deletions
diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c index 33fdd6c67c32..9a42041c159a 100644 --- a/fs/xfs/xfs_reflink.c +++ b/fs/xfs/xfs_reflink.c @@ -379,6 +379,18 @@ xfs_reflink_allocate_cow( xfs_iunlock(ip, *lockmode); retry: error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0, 0, &tp); + /* + * We weren't able to reserve enough space to handle copy on write. + * Flush any disk space that was being held in the hopes of speeding up + * the filesystem. We potentially hold the IOLOCK so we cannot do a + * synchronous scan. + */ + if (error == -ENOSPC && !cleared_space) { + cleared_space = true; + error = xfs_inode_free_blocks(ip->i_mount, false); + if (!error) + goto retry; + } *lockmode = XFS_ILOCK_EXCL; xfs_ilock(ip, *lockmode); @@ -1027,6 +1039,17 @@ retry: /* Start a rolling transaction to switch the mappings */ resblks = XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK); error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0, 0, &tp); + /* + * We weren't able to reserve enough space for the remapping. Flush + * any disk space that was being held in the hopes of speeding up the + * filesystem. We still hold the IOLOCK so we cannot do a sync scan. + */ + if (error == -ENOSPC && !cleared_space) { + cleared_space = true; + error = xfs_inode_free_blocks(mp, false); + if (!error) + goto retry; + } if (error) goto out; |