Skip to content

Commit 8dc15b7

Browse files
Christoph Hellwigcmaiolino
authored andcommitted
xfs: fix XFS_ERRTAG_FORCE_ZERO_RANGE for zoned file system
The new XFS_ERRTAG_FORCE_ZERO_RANGE error tag added by commit ea9989668081 ("xfs: error tag to force zeroing on debug kernels") fails to account for the zoned space reservation rules and this reliably fails xfs/131 because the zeroing operation returns -EIO. Fix this by reserving enough space to zero the entire range, which requires a bit of (fairly ugly) reshuffling to do the error injection early enough to affect the space reservation. Fixes: ea9989668081 ("xfs: error tag to force zeroing on debug kernels") Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Brian Foster <bfoster@redhat.com> Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com> Signed-off-by: Carlos Maiolino <cem@kernel.org>
1 parent fc40459 commit 8dc15b7

1 file changed

Lines changed: 48 additions & 10 deletions

File tree

fs/xfs/xfs_file.c

Lines changed: 48 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1240,6 +1240,38 @@ xfs_falloc_insert_range(
12401240
return xfs_insert_file_space(XFS_I(inode), offset, len);
12411241
}
12421242

1243+
/*
1244+
* For various operations we need to zero up to one block at each end of
1245+
* the affected range. For zoned file systems this will require a space
1246+
* allocation, for which we need a reservation ahead of time.
1247+
*/
1248+
#define XFS_ZONED_ZERO_EDGE_SPACE_RES 2
1249+
1250+
/*
1251+
* Zero range implements a full zeroing mechanism but is only used in limited
1252+
* situations. It is more efficient to allocate unwritten extents than to
1253+
* perform zeroing here, so use an errortag to randomly force zeroing on DEBUG
1254+
* kernels for added test coverage.
1255+
*
1256+
* On zoned file systems, the error is already injected by
1257+
* xfs_file_zoned_fallocate, which then reserves the additional space needed.
1258+
* We only check for this extra space reservation here.
1259+
*/
1260+
static inline bool
1261+
xfs_falloc_force_zero(
1262+
struct xfs_inode *ip,
1263+
struct xfs_zone_alloc_ctx *ac)
1264+
{
1265+
if (xfs_is_zoned_inode(ip)) {
1266+
if (ac->reserved_blocks > XFS_ZONED_ZERO_EDGE_SPACE_RES) {
1267+
ASSERT(IS_ENABLED(CONFIG_XFS_DEBUG));
1268+
return true;
1269+
}
1270+
return false;
1271+
}
1272+
return XFS_TEST_ERROR(ip->i_mount, XFS_ERRTAG_FORCE_ZERO_RANGE);
1273+
}
1274+
12431275
/*
12441276
* Punch a hole and prealloc the range. We use a hole punch rather than
12451277
* unwritten extent conversion for two reasons:
@@ -1268,14 +1300,7 @@ xfs_falloc_zero_range(
12681300
if (error)
12691301
return error;
12701302

1271-
/*
1272-
* Zero range implements a full zeroing mechanism but is only used in
1273-
* limited situations. It is more efficient to allocate unwritten
1274-
* extents than to perform zeroing here, so use an errortag to randomly
1275-
* force zeroing on DEBUG kernels for added test coverage.
1276-
*/
1277-
if (XFS_TEST_ERROR(ip->i_mount,
1278-
XFS_ERRTAG_FORCE_ZERO_RANGE)) {
1303+
if (xfs_falloc_force_zero(ip, ac)) {
12791304
error = xfs_zero_range(ip, offset, len, ac, NULL);
12801305
} else {
12811306
error = xfs_free_file_space(ip, offset, len, ac);
@@ -1423,13 +1448,26 @@ xfs_file_zoned_fallocate(
14231448
{
14241449
struct xfs_zone_alloc_ctx ac = { };
14251450
struct xfs_inode *ip = XFS_I(file_inode(file));
1451+
struct xfs_mount *mp = ip->i_mount;
1452+
xfs_filblks_t count_fsb;
14261453
int error;
14271454

1428-
error = xfs_zoned_space_reserve(ip->i_mount, 2, XFS_ZR_RESERVED, &ac);
1455+
/*
1456+
* If full zeroing is forced by the error injection knob, we need a
1457+
* space reservation that covers the entire range. See the comment in
1458+
* xfs_zoned_write_space_reserve for the rationale for the calculation.
1459+
* Otherwise just reserve space for the two boundary blocks.
1460+
*/
1461+
count_fsb = XFS_ZONED_ZERO_EDGE_SPACE_RES;
1462+
if ((mode & FALLOC_FL_MODE_MASK) == FALLOC_FL_ZERO_RANGE &&
1463+
XFS_TEST_ERROR(mp, XFS_ERRTAG_FORCE_ZERO_RANGE))
1464+
count_fsb += XFS_B_TO_FSB(mp, len) + 1;
1465+
1466+
error = xfs_zoned_space_reserve(mp, count_fsb, XFS_ZR_RESERVED, &ac);
14291467
if (error)
14301468
return error;
14311469
error = __xfs_file_fallocate(file, mode, offset, len, &ac);
1432-
xfs_zoned_space_unreserve(ip->i_mount, &ac);
1470+
xfs_zoned_space_unreserve(mp, &ac);
14331471
return error;
14341472
}
14351473

0 commit comments

Comments
 (0)