Add zfs_vdev_direct_read_verify tunable - #18794
Conversation
| */ | ||
| if ((zio->io_flags & ZIO_FLAG_DIO_READ) && | ||
| zfs_vdev_direct_read_verify == 0) | ||
| return (zio); |
There was a problem hiding this comment.
We can tighten up this check. I'd suggest pushing it in to zio_checksum_error() and restricting it to failed Direct IO reads using ABDs constructed from user pages. Everything else we still should report checksum errors for. Something like this (untested):
diff --git a/module/zfs/zio_checksum.c b/module/zfs/zio_checksum.c
index 1d0646a611..96e2395864 100644
--- a/module/zfs/zio_checksum.c
+++ b/module/zfs/zio_checksum.c
@@ -585,6 +585,11 @@ zio_checksum_error(zio_t *zio, zio_bad_cksum_t *info)
info->zbc_injected = 1;
}
+ if (error == ECKSUM && (zio->io_flags & ZIO_FLAG_DIO_READ) &&
+ abd_is_from_pages(data) && zfs_vdev_direct_read_verify == 0) {
+ error = 0;
+ }
+
return (error);
}
| 'dio_compression', 'dio_dedup', 'dio_encryption', 'dio_grow_block', | ||
| 'dio_max_recordsize', 'dio_mixed', 'dio_mmap', 'dio_overwrites', | ||
| 'dio_property', 'dio_random', 'dio_read_verify', 'dio_recordsize', | ||
| 'dio_property', 'dio_random', 'dio_read_verify', 'dio_read_verify_tunable', 'dio_recordsize', |
There was a problem hiding this comment.
cstyle: 80 columns limit.
| .Fx | ||
| before the Direct I/O write is issued. | ||
| . | ||
| .It Sy zfs_vdev_direct_read_verify Ns = Ns Sy 1 Ns | Ns 0 Pq uint |
There was a problem hiding this comment.
Should be added alphabetically, so let's put this zfs_vdev_direct_read_verify before zfs_vdev_direct_write_verify.
Applications that issue concurrent O_DIRECT reads and recycle their I/O buffers across in-flight requests (e.g. QEMU's block layer) can trip the Direct I/O read checksum verify: the buffer is overwritten by another request before the post-read verify of the previous one runs. This is not data corruption -- the on-disk block is correct and ZFS returns the right data via a buffered re-read -- but it produces a flood of spurious dio_verify_rd zevents, and the verify-and-refallback storm can stall the workload under load. Unlike the write case, read verification provides no data-integrity guarantee (the on-disk block is already correct); it only detects the caller mutating its own buffer mid-flight. Add a zfs_vdev_direct_read_verify module parameter, mirroring zfs_vdev_direct_write_verify, so this verification can be disabled for workloads that legitimately recycle buffers. The default of 1 preserves the current behavior. The check is applied in zio_checksum_error() and restricted to Direct I/O reads whose buffer is backed by user pages (abd_is_from_pages()), so it covers every vdev type in one place while still reporting genuine checksum errors and any read not served from user pages. Adds a ZTS test (dio_read_verify_tunable) exercising both settings across the stripe, mirror, raidz, and draid vdev types. Closes openzfs#18610 Signed-off-by: Michael Heller <michael.heller@gmail.com>
|
Thanks for the review — all three addressed:
The |
amotin
left a comment
There was a problem hiding this comment.
I feel it is too much. As I understand, you are effectively ignoring all ZFS checksums on reads if the I/O is Direct. It cover not only the case of buffer corruption by application, but also valid checksum errors from disk. I was going to say that it allow RAIDZ to do recovery writes, but in fact it may not even notice that something is wrong to issue recovery, but instead return garbage to the application.
|
Thanks @amotin — fair, and I don't want to trade away real corruption detection on Direct reads. You're right that at Two ways forward, your call:
My inclination is (1), since #18795 addresses the actual pain without the downside you flagged — but I'm happy to do (2) if you'd rather keep an explicit knob. Which do you prefer? |
|
Yeah, I'd close this unless you find something much better. Tunable to ignore errors sounds wrong. I generally don't like tunables. |
|
Makes sense — closing this. Thanks for the reviews, @amotin and @behlendorf. #18795 handles the event storm (the concrete #18610 symptom) without the integrity tradeoff, so I'll let that carry the fix. |
|
Yeah, agreed this is just too heavy handed. I'm glad we were at least able to mitigate the symptoms with #18795. |
Motivation and Context
Applications that issue concurrent
O_DIRECTreads and recycle their I/Obuffers across in-flight requests (e.g. QEMU's block layer) trip the Direct I/O
read checksum verify: the buffer is overwritten by another request before the
post-read verify of the previous one runs. This is not data corruption —
the on-disk block is correct and ZFS returns the right data via a buffered
re-read — but it produces a flood of spurious
dio_verify_rdzevents, and theverify-and-refallback storm can stall the workload under load. See #18610 for a
reproduction and analysis.
Unlike the write case, read verification provides no data-integrity guarantee
(the on-disk block is already correct); it only detects the caller mutating its
own buffer mid-flight. As discussed in #18610, @behlendorf agreed that a knob
modeled on
zfs_vdev_direct_write_verifywas the right approach.Description
Add a
zfs_vdev_direct_read_verifymodule parameter, mirroringzfs_vdev_direct_write_verify, so Direct I/O read verification can be disabledfor workloads that legitimately recycle buffers. The default of
1preservesthe current behavior.
The DIO read verify is performed per top-level vdev type, so the tunable is
honored in each path:
zio_checksum_verify()(disk/file),raidz_checksum_verify()(raidz and draid), and the indirect (device removal) path. Mirror vdevs inherit
the behavior from their children.
How Has This Been Tested?
New ZTS test
dio_read_verify_tunableexercises both settings (0 and 1) acrossthe stripe, mirror, raidz, and draid vdev types, asserting that
=0produces nodio_verify_rdevents while=1reports them, with the pool error-free in bothcases. Passing locally; cstyle clean.
Types of changes
Checklist:
Signed-off-by.Closes #18610