* [PATCH] xfs: fix XFS_ERRTAG_FORCE_ZERO_RANGE for zoned file system
@ 2025-12-10 9:03 Christoph Hellwig
2025-12-10 15:36 ` Brian Foster
0 siblings, 1 reply; 7+ messages in thread
From: Christoph Hellwig @ 2025-12-10 9:03 UTC (permalink / raw)
To: cem; +Cc: bfoster, linux-xfs
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>
---
fs/xfs/xfs_file.c | 46 ++++++++++++++++++++++++++++++++--------------
1 file changed, 32 insertions(+), 14 deletions(-)
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index 6108612182e2..dbf37adf3a6b 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -1254,7 +1254,8 @@ xfs_falloc_zero_range(
int mode,
loff_t offset,
loff_t len,
- struct xfs_zone_alloc_ctx *ac)
+ struct xfs_zone_alloc_ctx *ac,
+ bool force_zero_range)
{
struct inode *inode = file_inode(file);
struct xfs_inode *ip = XFS_I(inode);
@@ -1274,8 +1275,7 @@ xfs_falloc_zero_range(
* 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 (force_zero_range) {
error = xfs_zero_range(ip, offset, len, ac, NULL);
} else {
error = xfs_free_file_space(ip, offset, len, ac);
@@ -1357,7 +1357,8 @@ __xfs_file_fallocate(
int mode,
loff_t offset,
loff_t len,
- struct xfs_zone_alloc_ctx *ac)
+ struct xfs_zone_alloc_ctx *ac,
+ bool force_zero_range)
{
struct inode *inode = file_inode(file);
struct xfs_inode *ip = XFS_I(inode);
@@ -1393,7 +1394,8 @@ __xfs_file_fallocate(
error = xfs_falloc_insert_range(file, offset, len);
break;
case FALLOC_FL_ZERO_RANGE:
- error = xfs_falloc_zero_range(file, mode, offset, len, ac);
+ error = xfs_falloc_zero_range(file, mode, offset, len, ac,
+ force_zero_range);
break;
case FALLOC_FL_UNSHARE_RANGE:
error = xfs_falloc_unshare_range(file, mode, offset, len);
@@ -1419,17 +1421,24 @@ xfs_file_zoned_fallocate(
struct file *file,
int mode,
loff_t offset,
- loff_t len)
+ loff_t len,
+ bool force_zero_range)
{
struct xfs_zone_alloc_ctx ac = { };
struct xfs_inode *ip = XFS_I(file_inode(file));
+ struct xfs_mount *mp = ip->i_mount;
int error;
+ xfs_filblks_t count_fsb = 2;
- error = xfs_zoned_space_reserve(ip->i_mount, 2, XFS_ZR_RESERVED, &ac);
+ if (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);
+ error = __xfs_file_fallocate(file, mode, offset, len, &ac,
+ force_zero_range);
+ xfs_zoned_space_unreserve(mp, &ac);
return error;
}
@@ -1441,12 +1450,18 @@ xfs_file_fallocate(
loff_t len)
{
struct inode *inode = file_inode(file);
+ struct xfs_inode *ip = XFS_I(inode);
+ bool force_zero_range = false;
if (!S_ISREG(inode->i_mode))
return -EINVAL;
if (mode & ~XFS_FALLOC_FL_SUPPORTED)
return -EOPNOTSUPP;
+ if ((mode & FALLOC_FL_MODE_MASK) == FALLOC_FL_ZERO_RANGE &&
+ XFS_TEST_ERROR(ip->i_mount, XFS_ERRTAG_FORCE_ZERO_RANGE))
+ force_zero_range = true;
+
/*
* For zoned file systems, zeroing the first and last block of a hole
* punch requires allocating a new block to rewrite the remaining data
@@ -1455,11 +1470,14 @@ xfs_file_fallocate(
* expected to be able to punch a hole even on a completely full
* file system.
*/
- if (xfs_is_zoned_inode(XFS_I(inode)) &&
- (mode & (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_ZERO_RANGE |
- FALLOC_FL_COLLAPSE_RANGE)))
- return xfs_file_zoned_fallocate(file, mode, offset, len);
- return __xfs_file_fallocate(file, mode, offset, len, NULL);
+ if (xfs_is_zoned_inode(ip) &&
+ (force_zero_range ||
+ (mode & (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_ZERO_RANGE |
+ FALLOC_FL_COLLAPSE_RANGE))))
+ return xfs_file_zoned_fallocate(file, mode, offset, len,
+ force_zero_range);
+ return __xfs_file_fallocate(file, mode, offset, len, NULL,
+ force_zero_range);
}
STATIC int
--
2.47.3
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [PATCH] xfs: fix XFS_ERRTAG_FORCE_ZERO_RANGE for zoned file system
2025-12-10 9:03 [PATCH] xfs: fix XFS_ERRTAG_FORCE_ZERO_RANGE for zoned file system Christoph Hellwig
@ 2025-12-10 15:36 ` Brian Foster
2025-12-10 15:40 ` Christoph Hellwig
0 siblings, 1 reply; 7+ messages in thread
From: Brian Foster @ 2025-12-10 15:36 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: cem, linux-xfs
On Wed, Dec 10, 2025 at 10:03:55AM +0100, Christoph Hellwig wrote:
> 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>
> ---
Is there a reason in particular for testing this with the zone mode?
It's just a DEBUG thing for the zeroing mechanism. Why not just filter
out the is_zoned_inode() case at the injection site?
I suppose you could argue there is a point if we have separate zoned
mode iomap callbacks and whatnot, but I agree the factoring here is a
little unfortunate. I wonder if it would be nicer if we could set a flag
or something on an ac and toggle the zone mode off that, but on a quick
look I don't see a flag field in the zone ctx.
Hmm.. I wonder if we could still do something more clever where the zone
mode has its own injection site to bump the res, and then the lower
level logic just checks whether the reservation is sufficient for a full
zero..? I'm not totally sure if that's ultimately cleaner, but maybe
worth a thought..
Brian
> fs/xfs/xfs_file.c | 46 ++++++++++++++++++++++++++++++++--------------
> 1 file changed, 32 insertions(+), 14 deletions(-)
>
> diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
> index 6108612182e2..dbf37adf3a6b 100644
> --- a/fs/xfs/xfs_file.c
> +++ b/fs/xfs/xfs_file.c
> @@ -1254,7 +1254,8 @@ xfs_falloc_zero_range(
> int mode,
> loff_t offset,
> loff_t len,
> - struct xfs_zone_alloc_ctx *ac)
> + struct xfs_zone_alloc_ctx *ac,
> + bool force_zero_range)
> {
> struct inode *inode = file_inode(file);
> struct xfs_inode *ip = XFS_I(inode);
> @@ -1274,8 +1275,7 @@ xfs_falloc_zero_range(
> * 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 (force_zero_range) {
> error = xfs_zero_range(ip, offset, len, ac, NULL);
> } else {
> error = xfs_free_file_space(ip, offset, len, ac);
> @@ -1357,7 +1357,8 @@ __xfs_file_fallocate(
> int mode,
> loff_t offset,
> loff_t len,
> - struct xfs_zone_alloc_ctx *ac)
> + struct xfs_zone_alloc_ctx *ac,
> + bool force_zero_range)
> {
> struct inode *inode = file_inode(file);
> struct xfs_inode *ip = XFS_I(inode);
> @@ -1393,7 +1394,8 @@ __xfs_file_fallocate(
> error = xfs_falloc_insert_range(file, offset, len);
> break;
> case FALLOC_FL_ZERO_RANGE:
> - error = xfs_falloc_zero_range(file, mode, offset, len, ac);
> + error = xfs_falloc_zero_range(file, mode, offset, len, ac,
> + force_zero_range);
> break;
> case FALLOC_FL_UNSHARE_RANGE:
> error = xfs_falloc_unshare_range(file, mode, offset, len);
> @@ -1419,17 +1421,24 @@ xfs_file_zoned_fallocate(
> struct file *file,
> int mode,
> loff_t offset,
> - loff_t len)
> + loff_t len,
> + bool force_zero_range)
> {
> struct xfs_zone_alloc_ctx ac = { };
> struct xfs_inode *ip = XFS_I(file_inode(file));
> + struct xfs_mount *mp = ip->i_mount;
> int error;
> + xfs_filblks_t count_fsb = 2;
>
> - error = xfs_zoned_space_reserve(ip->i_mount, 2, XFS_ZR_RESERVED, &ac);
> + if (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);
> + error = __xfs_file_fallocate(file, mode, offset, len, &ac,
> + force_zero_range);
> + xfs_zoned_space_unreserve(mp, &ac);
> return error;
> }
>
> @@ -1441,12 +1450,18 @@ xfs_file_fallocate(
> loff_t len)
> {
> struct inode *inode = file_inode(file);
> + struct xfs_inode *ip = XFS_I(inode);
> + bool force_zero_range = false;
>
> if (!S_ISREG(inode->i_mode))
> return -EINVAL;
> if (mode & ~XFS_FALLOC_FL_SUPPORTED)
> return -EOPNOTSUPP;
>
> + if ((mode & FALLOC_FL_MODE_MASK) == FALLOC_FL_ZERO_RANGE &&
> + XFS_TEST_ERROR(ip->i_mount, XFS_ERRTAG_FORCE_ZERO_RANGE))
> + force_zero_range = true;
> +
> /*
> * For zoned file systems, zeroing the first and last block of a hole
> * punch requires allocating a new block to rewrite the remaining data
> @@ -1455,11 +1470,14 @@ xfs_file_fallocate(
> * expected to be able to punch a hole even on a completely full
> * file system.
> */
> - if (xfs_is_zoned_inode(XFS_I(inode)) &&
> - (mode & (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_ZERO_RANGE |
> - FALLOC_FL_COLLAPSE_RANGE)))
> - return xfs_file_zoned_fallocate(file, mode, offset, len);
> - return __xfs_file_fallocate(file, mode, offset, len, NULL);
> + if (xfs_is_zoned_inode(ip) &&
> + (force_zero_range ||
> + (mode & (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_ZERO_RANGE |
> + FALLOC_FL_COLLAPSE_RANGE))))
> + return xfs_file_zoned_fallocate(file, mode, offset, len,
> + force_zero_range);
> + return __xfs_file_fallocate(file, mode, offset, len, NULL,
> + force_zero_range);
> }
>
> STATIC int
> --
> 2.47.3
>
>
^ permalink raw reply [flat|nested] 7+ messages in thread* Re: [PATCH] xfs: fix XFS_ERRTAG_FORCE_ZERO_RANGE for zoned file system
2025-12-10 15:36 ` Brian Foster
@ 2025-12-10 15:40 ` Christoph Hellwig
2025-12-10 17:14 ` Brian Foster
0 siblings, 1 reply; 7+ messages in thread
From: Christoph Hellwig @ 2025-12-10 15:40 UTC (permalink / raw)
To: Brian Foster; +Cc: Christoph Hellwig, cem, linux-xfs
On Wed, Dec 10, 2025 at 10:36:55AM -0500, Brian Foster wrote:
> Is there a reason in particular for testing this with the zone mode?
> It's just a DEBUG thing for the zeroing mechanism. Why not just filter
> out the is_zoned_inode() case at the injection site?
Because I also want to be able to test the zeroing code for zoned
file systems, especially given zeroing is a bit of painful area
for out of place write file systems like zoned XFS.
> I suppose you could argue there is a point if we have separate zoned
> mode iomap callbacks and whatnot, but I agree the factoring here is a
> little unfortunate. I wonder if it would be nicer if we could set a flag
> or something on an ac and toggle the zone mode off that, but on a quick
> look I don't see a flag field in the zone ctx.
I don't really follow what you mean here.
> Hmm.. I wonder if we could still do something more clever where the zone
> mode has its own injection site to bump the res, and then the lower
> level logic just checks whether the reservation is sufficient for a full
> zero..? I'm not totally sure if that's ultimately cleaner, but maybe
> worth a thought..
We could have a different site for that injection, but we'd still need
to move the current one or at least make it conditional so that it
can't trigger for zoned mode. I doubt that's less ugly than this
version.
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] xfs: fix XFS_ERRTAG_FORCE_ZERO_RANGE for zoned file system
2025-12-10 15:40 ` Christoph Hellwig
@ 2025-12-10 17:14 ` Brian Foster
2025-12-10 17:18 ` Christoph Hellwig
2025-12-12 7:39 ` Christoph Hellwig
0 siblings, 2 replies; 7+ messages in thread
From: Brian Foster @ 2025-12-10 17:14 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: cem, linux-xfs
On Wed, Dec 10, 2025 at 04:40:16PM +0100, Christoph Hellwig wrote:
> On Wed, Dec 10, 2025 at 10:36:55AM -0500, Brian Foster wrote:
> > Is there a reason in particular for testing this with the zone mode?
> > It's just a DEBUG thing for the zeroing mechanism. Why not just filter
> > out the is_zoned_inode() case at the injection site?
>
> Because I also want to be able to test the zeroing code for zoned
> file systems, especially given zeroing is a bit of painful area
> for out of place write file systems like zoned XFS.
>
> > I suppose you could argue there is a point if we have separate zoned
> > mode iomap callbacks and whatnot, but I agree the factoring here is a
> > little unfortunate. I wonder if it would be nicer if we could set a flag
> > or something on an ac and toggle the zone mode off that, but on a quick
> > look I don't see a flag field in the zone ctx.
>
> I don't really follow what you mean here.
>
I was just rambling about if/how we might be able to use the ac..
> > Hmm.. I wonder if we could still do something more clever where the zone
> > mode has its own injection site to bump the res, and then the lower
> > level logic just checks whether the reservation is sufficient for a full
> > zero..? I'm not totally sure if that's ultimately cleaner, but maybe
> > worth a thought..
>
> We could have a different site for that injection, but we'd still need
> to move the current one or at least make it conditional so that it
> can't trigger for zoned mode. I doubt that's less ugly than this
> version.
>
Well yeah, it would look something like this at the current site:
if (!is_inode_zoned() && XFS_TEST_ERROR(...) ||
ac->reserved_blocks == magic_default_res + len)
xfs_zero_range(...);
else
xfs_free_file_space(...);
... and the higher level zoned code would clone the XFS_TEST_ERROR() to
create the block reservation condition to trigger it.
Alternatively perhaps you could make that check look something like:
if (XFS_TEST_ERROR() && (!ac || ac->res > len))
...
else
...
... and let the res side always bump the res in DEBUG mode, with a
fallback on -ENOSPC or something.
Actually the latter sounds potentially more clean to me, but I don't
object to this if not.
Brian
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] xfs: fix XFS_ERRTAG_FORCE_ZERO_RANGE for zoned file system
2025-12-10 17:14 ` Brian Foster
@ 2025-12-10 17:18 ` Christoph Hellwig
2025-12-12 7:39 ` Christoph Hellwig
1 sibling, 0 replies; 7+ messages in thread
From: Christoph Hellwig @ 2025-12-10 17:18 UTC (permalink / raw)
To: Brian Foster; +Cc: Christoph Hellwig, cem, linux-xfs
On Wed, Dec 10, 2025 at 12:14:35PM -0500, Brian Foster wrote:
> Well yeah, it would look something like this at the current site:
>
> if (!is_inode_zoned() && XFS_TEST_ERROR(...) ||
> ac->reserved_blocks == magic_default_res + len)
> xfs_zero_range(...);
> else
> xfs_free_file_space(...);
>
> ... and the higher level zoned code would clone the XFS_TEST_ERROR() to
> create the block reservation condition to trigger it.
>
> Alternatively perhaps you could make that check look something like:
>
> if (XFS_TEST_ERROR() && (!ac || ac->res > len))
> ...
> else
> ...
>
> ... and let the res side always bump the res in DEBUG mode, with a
> fallback on -ENOSPC or something.
That would be less invasive for sure. But also a bit weird, as it
encodes quite a lot of detailed knowledge of the reservations here.
I could live with it, but I fear it would have a chance to break
in not very nice ways in the future.
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] xfs: fix XFS_ERRTAG_FORCE_ZERO_RANGE for zoned file system
2025-12-10 17:14 ` Brian Foster
2025-12-10 17:18 ` Christoph Hellwig
@ 2025-12-12 7:39 ` Christoph Hellwig
2025-12-12 12:24 ` Brian Foster
1 sibling, 1 reply; 7+ messages in thread
From: Christoph Hellwig @ 2025-12-12 7:39 UTC (permalink / raw)
To: Brian Foster; +Cc: Christoph Hellwig, cem, linux-xfs
On Wed, Dec 10, 2025 at 12:14:35PM -0500, Brian Foster wrote:
> Well yeah, it would look something like this at the current site:
>
> if (!is_inode_zoned() && XFS_TEST_ERROR(...) ||
> ac->reserved_blocks == magic_default_res + len)
> xfs_zero_range(...);
> else
> xfs_free_file_space(...);
>
> ... and the higher level zoned code would clone the XFS_TEST_ERROR() to
> create the block reservation condition to trigger it.
>
> Alternatively perhaps you could make that check look something like:
>
> if (XFS_TEST_ERROR() && (!ac || ac->res > len))
> ...
> else
> ...
I had to juggle this a bit to not trigger the wrong way and add a
helper. The changes are a bit bigger than the original version,
but I guess you'll probably prefer it because it keeps things more
contained in the zoned code?
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index 6108612182e2..d70c8e0d802b 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -1240,6 +1240,28 @@ xfs_falloc_insert_range(
return xfs_insert_file_space(XFS_I(inode), offset, len);
}
+#define XFS_ZONED_ZERO_RANGE_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 (ac)
+ return ac->reserved_blocks > XFS_ZONED_ZERO_RANGE_SPACE_RES;
+ 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 +1290,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 +1438,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 nob, 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_RANGE_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;
}
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [PATCH] xfs: fix XFS_ERRTAG_FORCE_ZERO_RANGE for zoned file system
2025-12-12 7:39 ` Christoph Hellwig
@ 2025-12-12 12:24 ` Brian Foster
0 siblings, 0 replies; 7+ messages in thread
From: Brian Foster @ 2025-12-12 12:24 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: cem, linux-xfs
On Fri, Dec 12, 2025 at 08:39:37AM +0100, Christoph Hellwig wrote:
> On Wed, Dec 10, 2025 at 12:14:35PM -0500, Brian Foster wrote:
> > Well yeah, it would look something like this at the current site:
> >
> > if (!is_inode_zoned() && XFS_TEST_ERROR(...) ||
> > ac->reserved_blocks == magic_default_res + len)
> > xfs_zero_range(...);
> > else
> > xfs_free_file_space(...);
> >
> > ... and the higher level zoned code would clone the XFS_TEST_ERROR() to
> > create the block reservation condition to trigger it.
> >
> > Alternatively perhaps you could make that check look something like:
> >
> > if (XFS_TEST_ERROR() && (!ac || ac->res > len))
> > ...
> > else
> > ...
>
> I had to juggle this a bit to not trigger the wrong way and add a
> helper. The changes are a bit bigger than the original version,
> but I guess you'll probably prefer it because it keeps things more
> contained in the zoned code?
>
Thanks for taking a stab at this. I agree that the whole indirect logic
trigger based on res thing is a wart/tradeoff, but even still I think I
like this better probably for the reasons you stated. It feels more
encapsulated, and is still limited to DEBUG mode so doesn't worry me as
much.
A few minor comments below, but otherwise if this works for you and
there aren't strong opinions to the contrary:
Reviewed-by: Brian Foster <bfoster@redhat.com>
> diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
> index 6108612182e2..d70c8e0d802b 100644
> --- a/fs/xfs/xfs_file.c
> +++ b/fs/xfs/xfs_file.c
> @@ -1240,6 +1240,28 @@ xfs_falloc_insert_range(
> return xfs_insert_file_space(XFS_I(inode), offset, len);
> }
>
> +#define XFS_ZONED_ZERO_RANGE_SPACE_RES 2
> +
This 2 block res isn't purely a zero range thing, right? It looks like
it's for a few different falloc ops.. perhaps ZONED_FALLOC_SPACE_RES (or
whatever else that is less zero specific)..?
> +/*
> + * 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 (ac)
> + return ac->reserved_blocks > XFS_ZONED_ZERO_RANGE_SPACE_RES;
Random thought: I wonder if doing something like:
if (!IS_ENABLED(CONFIG_XFS_DEBUG))
return false;
... in this helper would shore up the logic a bit? Just a bit of
defensive logic against the indirection since the helper already exists.
I also wonder if that would help the compiler optimize this out on
!DEBUG builds.
> + 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:
...
> @@ -1423,13 +1438,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 nob, we need a space
s/nob/knob/ ;)
Thanks!
Brian
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2025-12-12 12:24 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-12-10 9:03 [PATCH] xfs: fix XFS_ERRTAG_FORCE_ZERO_RANGE for zoned file system Christoph Hellwig
2025-12-10 15:36 ` Brian Foster
2025-12-10 15:40 ` Christoph Hellwig
2025-12-10 17:14 ` Brian Foster
2025-12-10 17:18 ` Christoph Hellwig
2025-12-12 7:39 ` Christoph Hellwig
2025-12-12 12:24 ` Brian Foster
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox