[PATCH 0/2] ext4: fix fast commit and extent status after unwritten extent zero-out
From: Daejun Park via B4 Relay
Date: Tue Oct 06 2026 - 20:41:45 EST
When ext4_ext_convert_to_initialized() converts part of an unwritten
extent, it may zero out the blocks around the range and convert them
too, and ext4_split_extent() does the same with a whole extent when a
split fails. Two things go wrong around that.
1/2: if the zeroout fails, the blocks on that side stay unwritten in the
extent tree, but the extent status tree caches them as written. Reads
return old disk contents, and writes go in place without converting the
extent, so they read back as zeroes once the entry is dropped.
2/2: when the zeroout succeeds, fast commit is told only about the range
that was written. A later in-place overwrite of a zeroed block is not
tracked either, and after a crash the fsynced data reads back as zeroes.
2/2 depends on 1/2. With 2/2 alone, the blocks that failed to zero out
are tracked as well, and fast commit replay converts them to written on
disk, so the old contents survive the crash: with the dm-error
reproducer described in 1/2, block 1 reads back as old data after
replay on a kernel with only 2/2, and as zeroes with both patches.
Tested in QEMU on ext4 dev 9091c97be340 plus this series:
- the reproducer described in 2/2, with -o nodelalloc and with
-o dioread_lock, also on a PROVE_LOCKING and DEBUG_ATOMIC_SLEEP kernel
(no report), and the dm-error reproducer described in 1/2;
- xfstests ext4/044 ext4/045 generic/455 generic/456 generic/482 with
-O fast_commit, with and without -o nodelalloc: the same results as
without the series (generic/455 fails on both, at different marks);
- the ext4 KUnit tests, 72 of 72, including the split cases that zero
out. They are the only ones to reach the second hunk of 2/2, and they
run without fast commit, so its tracking is not exercised.
For stable: 2/2 needs ext4_split_extent_zeroout(), which came in 7.0,
hence "# 7.0.x". Before that only its ext4_zeroout_es() part applies.
---
Daejun Park (2):
ext4: don't cache unzeroed blocks as written after a failed zeroout
ext4: track zeroed out blocks of unwritten extents for fast commit
fs/ext4/extents.c | 29 ++++++++++++++++++++++++-----
1 file changed, 24 insertions(+), 5 deletions(-)
---
base-commit: 9091c97be34083587a75db174aab51551d8e8543
change-id: 20261006-ext4-fc-zeroout-e429007c72a0
Best regards,
--
Daejun Park <daejun7.park@xxxxxxxxxxx>