Skip to content

Commit 48af96a

Browse files
Brian Fosterdjwong
authored andcommitted
xfs: don't reserve blocks for right shift transactions
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>
1 parent 353fe44 commit 48af96a

File tree

1 file changed

+10
-10
lines changed

1 file changed

+10
-10
lines changed

fs/xfs/xfs_bmap_util.c

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1385,17 +1385,24 @@ xfs_shift_file_space(
13851385
xfs_fileoff_t stop_fsb;
13861386
xfs_fileoff_t next_fsb;
13871387
xfs_fileoff_t shift_fsb;
1388+
uint resblks;
13881389

13891390
ASSERT(direction == SHIFT_LEFT || direction == SHIFT_RIGHT);
13901391

13911392
if (direction == SHIFT_LEFT) {
1393+
/*
1394+
* Reserve blocks to cover potential extent merges after left
1395+
* shift operations.
1396+
*/
1397+
resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0);
13921398
next_fsb = XFS_B_TO_FSB(mp, offset + len);
13931399
stop_fsb = XFS_B_TO_FSB(mp, VFS_I(ip)->i_size);
13941400
} else {
13951401
/*
13961402
* If right shift, delegate the work of initialization of
13971403
* next_fsb to xfs_bmap_shift_extent as it has ilock held.
13981404
*/
1405+
resblks = 0;
13991406
next_fsb = NULLFSBLOCK;
14001407
stop_fsb = XFS_B_TO_FSB(mp, offset);
14011408
}
@@ -1437,21 +1444,14 @@ xfs_shift_file_space(
14371444
}
14381445

14391446
while (!error && !done) {
1440-
/*
1441-
* We would need to reserve permanent block for transaction.
1442-
* This will come into picture when after shifting extent into
1443-
* hole we found that adjacent extents can be merged which
1444-
* may lead to freeing of a block during record update.
1445-
*/
1446-
error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write,
1447-
XFS_DIOSTRAT_SPACE_RES(mp, 0), 0, 0, &tp);
1447+
error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0, 0,
1448+
&tp);
14481449
if (error)
14491450
break;
14501451

14511452
xfs_ilock(ip, XFS_ILOCK_EXCL);
14521453
error = xfs_trans_reserve_quota(tp, mp, ip->i_udquot,
1453-
ip->i_gdquot, ip->i_pdquot,
1454-
XFS_DIOSTRAT_SPACE_RES(mp, 0), 0,
1454+
ip->i_gdquot, ip->i_pdquot, resblks, 0,
14551455
XFS_QMOPT_RES_REGBLKS);
14561456
if (error)
14571457
goto out_trans_cancel;

0 commit comments

Comments
 (0)