mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-12-27 12:21:22 -05:00
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>
This commit is contained in:
committed by
Carlos Maiolino
parent
fc40459de8
commit
8dc15b7a6e
@@ -1240,6 +1240,38 @@ xfs_falloc_insert_range(
|
||||
return xfs_insert_file_space(XFS_I(inode), offset, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* For various operations we need to zero up to one block at each end of
|
||||
* the affected range. For zoned file systems this will require a space
|
||||
* allocation, for which we need a reservation ahead of time.
|
||||
*/
|
||||
#define XFS_ZONED_ZERO_EDGE_SPACE_RES 2
|
||||
|
||||
/*
|
||||
* Zero range implements a full zeroing mechanism but is only used in limited
|
||||
* situations. It is more efficient to allocate unwritten extents than to
|
||||
* perform zeroing here, so use an errortag to randomly force zeroing on DEBUG
|
||||
* kernels for added test coverage.
|
||||
*
|
||||
* On zoned file systems, the error is already injected by
|
||||
* xfs_file_zoned_fallocate, which then reserves the additional space needed.
|
||||
* We only check for this extra space reservation here.
|
||||
*/
|
||||
static inline bool
|
||||
xfs_falloc_force_zero(
|
||||
struct xfs_inode *ip,
|
||||
struct xfs_zone_alloc_ctx *ac)
|
||||
{
|
||||
if (xfs_is_zoned_inode(ip)) {
|
||||
if (ac->reserved_blocks > XFS_ZONED_ZERO_EDGE_SPACE_RES) {
|
||||
ASSERT(IS_ENABLED(CONFIG_XFS_DEBUG));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return XFS_TEST_ERROR(ip->i_mount, XFS_ERRTAG_FORCE_ZERO_RANGE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Punch a hole and prealloc the range. We use a hole punch rather than
|
||||
* unwritten extent conversion for two reasons:
|
||||
@@ -1268,14 +1300,7 @@ xfs_falloc_zero_range(
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
/*
|
||||
* Zero range implements a full zeroing mechanism but is only used in
|
||||
* limited situations. It is more efficient to allocate unwritten
|
||||
* extents than to perform zeroing here, so use an errortag to randomly
|
||||
* force zeroing on DEBUG kernels for added test coverage.
|
||||
*/
|
||||
if (XFS_TEST_ERROR(ip->i_mount,
|
||||
XFS_ERRTAG_FORCE_ZERO_RANGE)) {
|
||||
if (xfs_falloc_force_zero(ip, ac)) {
|
||||
error = xfs_zero_range(ip, offset, len, ac, NULL);
|
||||
} else {
|
||||
error = xfs_free_file_space(ip, offset, len, ac);
|
||||
@@ -1423,13 +1448,26 @@ xfs_file_zoned_fallocate(
|
||||
{
|
||||
struct xfs_zone_alloc_ctx ac = { };
|
||||
struct xfs_inode *ip = XFS_I(file_inode(file));
|
||||
struct xfs_mount *mp = ip->i_mount;
|
||||
xfs_filblks_t count_fsb;
|
||||
int error;
|
||||
|
||||
error = xfs_zoned_space_reserve(ip->i_mount, 2, XFS_ZR_RESERVED, &ac);
|
||||
/*
|
||||
* If full zeroing is forced by the error injection knob, we need a
|
||||
* space reservation that covers the entire range. See the comment in
|
||||
* xfs_zoned_write_space_reserve for the rationale for the calculation.
|
||||
* Otherwise just reserve space for the two boundary blocks.
|
||||
*/
|
||||
count_fsb = XFS_ZONED_ZERO_EDGE_SPACE_RES;
|
||||
if ((mode & FALLOC_FL_MODE_MASK) == FALLOC_FL_ZERO_RANGE &&
|
||||
XFS_TEST_ERROR(mp, XFS_ERRTAG_FORCE_ZERO_RANGE))
|
||||
count_fsb += XFS_B_TO_FSB(mp, len) + 1;
|
||||
|
||||
error = xfs_zoned_space_reserve(mp, count_fsb, XFS_ZR_RESERVED, &ac);
|
||||
if (error)
|
||||
return error;
|
||||
error = __xfs_file_fallocate(file, mode, offset, len, &ac);
|
||||
xfs_zoned_space_unreserve(ip->i_mount, &ac);
|
||||
xfs_zoned_space_unreserve(mp, &ac);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user