Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Christoph Hellwig and committed by
Carlos Maiolino
8dc15b7a fc40459d

+48 -10
+48 -10
fs/xfs/xfs_file.c
··· 1241 1241 } 1242 1242 1243 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 + 1275 + /* 1244 1276 * Punch a hole and prealloc the range. We use a hole punch rather than 1245 1277 * unwritten extent conversion for two reasons: 1246 1278 * ··· 1300 1268 if (error) 1301 1269 return error; 1302 1270 1303 - /* 1304 - * Zero range implements a full zeroing mechanism but is only used in 1305 - * limited situations. It is more efficient to allocate unwritten 1306 - * extents than to perform zeroing here, so use an errortag to randomly 1307 - * force zeroing on DEBUG kernels for added test coverage. 1308 - */ 1309 - if (XFS_TEST_ERROR(ip->i_mount, 1310 - XFS_ERRTAG_FORCE_ZERO_RANGE)) { 1271 + if (xfs_falloc_force_zero(ip, ac)) { 1311 1272 error = xfs_zero_range(ip, offset, len, ac, NULL); 1312 1273 } else { 1313 1274 error = xfs_free_file_space(ip, offset, len, ac); ··· 1448 1423 { 1449 1424 struct xfs_zone_alloc_ctx ac = { }; 1450 1425 struct xfs_inode *ip = XFS_I(file_inode(file)); 1426 + struct xfs_mount *mp = ip->i_mount; 1427 + xfs_filblks_t count_fsb; 1451 1428 int error; 1452 1429 1453 - error = xfs_zoned_space_reserve(ip->i_mount, 2, XFS_ZR_RESERVED, &ac); 1430 + /* 1431 + * If full zeroing is forced by the error injection knob, we need a 1432 + * space reservation that covers the entire range. See the comment in 1433 + * xfs_zoned_write_space_reserve for the rationale for the calculation. 1434 + * Otherwise just reserve space for the two boundary blocks. 1435 + */ 1436 + count_fsb = XFS_ZONED_ZERO_EDGE_SPACE_RES; 1437 + if ((mode & FALLOC_FL_MODE_MASK) == FALLOC_FL_ZERO_RANGE && 1438 + XFS_TEST_ERROR(mp, XFS_ERRTAG_FORCE_ZERO_RANGE)) 1439 + count_fsb += XFS_B_TO_FSB(mp, len) + 1; 1440 + 1441 + error = xfs_zoned_space_reserve(mp, count_fsb, XFS_ZR_RESERVED, &ac); 1454 1442 if (error) 1455 1443 return error; 1456 1444 error = __xfs_file_fallocate(file, mode, offset, len, &ac); 1457 - xfs_zoned_space_unreserve(ip->i_mount, &ac); 1445 + xfs_zoned_space_unreserve(mp, &ac); 1458 1446 return error; 1459 1447 } 1460 1448