aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Foster <bfoster@redhat.com>2017-02-15 13:18:10 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-04-08 03:30:32 -0400
commit5db7b41b607d3b268662f662e8c3dd403f648004 (patch)
treed99c676a2913570ca712bc239d030880e18a9185
parente5e2e56fd4dd808dcd5a81244da2598290fb7782 (diff)
xfs: don't reserve blocks for right shift transactions
commit 48af96ab92bc68fb645068b978ce36df2379e076 upstream. The block reservation for the transaction allocated in xfs_shift_file_space() is an artifact of the original collapse range support. It exists to handle the case where a collapse range occurs, the initial extent is left shifted into a location that forms a contiguous boundary with the previous extent and thus the extents are merged. This code was subsequently refactored and reused for insert range (right shift) support. If an insert range occurs under low free space conditions, the extent at the starting offset is split before the first shift transaction is allocated. If the block reservation fails, this leaves separate, but contiguous extents around in the inode. While not a fatal problem, this is unexpected and will flag a warning on subsequent insert range operations on the inode. This problem has been reproduce intermittently by generic/270 running against a ramdisk device. Since right shift does not create new extent boundaries in the inode, a block reservation for extent merge is unnecessary. Update xfs_shift_file_space() to conditionally reserve fs blocks for left shift transactions only. This avoids the warning reproduced by generic/270. Reported-by: Ross Zwisler <ross.zwisler@linux.intel.com> Signed-off-by: Brian Foster <bfoster@redhat.com> Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--fs/xfs/xfs_bmap_util.c20
1 files changed, 10 insertions, 10 deletions
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
index fd459b69161e..5c395e485170 100644
--- a/fs/xfs/xfs_bmap_util.c
+++ b/fs/xfs/xfs_bmap_util.c
@@ -1387,10 +1387,16 @@ xfs_shift_file_space(
1387 xfs_fileoff_t stop_fsb; 1387 xfs_fileoff_t stop_fsb;
1388 xfs_fileoff_t next_fsb; 1388 xfs_fileoff_t next_fsb;
1389 xfs_fileoff_t shift_fsb; 1389 xfs_fileoff_t shift_fsb;
1390 uint resblks;
1390 1391
1391 ASSERT(direction == SHIFT_LEFT || direction == SHIFT_RIGHT); 1392 ASSERT(direction == SHIFT_LEFT || direction == SHIFT_RIGHT);
1392 1393
1393 if (direction == SHIFT_LEFT) { 1394 if (direction == SHIFT_LEFT) {
1395 /*
1396 * Reserve blocks to cover potential extent merges after left
1397 * shift operations.
1398 */
1399 resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0);
1394 next_fsb = XFS_B_TO_FSB(mp, offset + len); 1400 next_fsb = XFS_B_TO_FSB(mp, offset + len);
1395 stop_fsb = XFS_B_TO_FSB(mp, VFS_I(ip)->i_size); 1401 stop_fsb = XFS_B_TO_FSB(mp, VFS_I(ip)->i_size);
1396 } else { 1402 } else {
@@ -1398,6 +1404,7 @@ xfs_shift_file_space(
1398 * If right shift, delegate the work of initialization of 1404 * If right shift, delegate the work of initialization of
1399 * next_fsb to xfs_bmap_shift_extent as it has ilock held. 1405 * next_fsb to xfs_bmap_shift_extent as it has ilock held.
1400 */ 1406 */
1407 resblks = 0;
1401 next_fsb = NULLFSBLOCK; 1408 next_fsb = NULLFSBLOCK;
1402 stop_fsb = XFS_B_TO_FSB(mp, offset); 1409 stop_fsb = XFS_B_TO_FSB(mp, offset);
1403 } 1410 }
@@ -1439,21 +1446,14 @@ xfs_shift_file_space(
1439 } 1446 }
1440 1447
1441 while (!error && !done) { 1448 while (!error && !done) {
1442 /* 1449 error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0, 0,
1443 * We would need to reserve permanent block for transaction. 1450 &tp);
1444 * This will come into picture when after shifting extent into
1445 * hole we found that adjacent extents can be merged which
1446 * may lead to freeing of a block during record update.
1447 */
1448 error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write,
1449 XFS_DIOSTRAT_SPACE_RES(mp, 0), 0, 0, &tp);
1450 if (error) 1451 if (error)
1451 break; 1452 break;
1452 1453
1453 xfs_ilock(ip, XFS_ILOCK_EXCL); 1454 xfs_ilock(ip, XFS_ILOCK_EXCL);
1454 error = xfs_trans_reserve_quota(tp, mp, ip->i_udquot, 1455 error = xfs_trans_reserve_quota(tp, mp, ip->i_udquot,
1455 ip->i_gdquot, ip->i_pdquot, 1456 ip->i_gdquot, ip->i_pdquot, resblks, 0,
1456 XFS_DIOSTRAT_SPACE_RES(mp, 0), 0,
1457 XFS_QMOPT_RES_REGBLKS); 1457 XFS_QMOPT_RES_REGBLKS);
1458 if (error) 1458 if (error)
1459 goto out_trans_cancel; 1459 goto out_trans_cancel;