diff options
| author | Gary Guo <gary@garyguo.net> | 2026-04-15 21:51:53 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-04-15 21:51:53 +0000 |
| commit | 1644e2ffd2640fa3e2c191ceaf048a5fc8399493 (patch) | |
| tree | f6104f1bdc6f8e3aa95095701294ae88549ada56 /sys/dev/netmap/netmap_vale.c | |
| parent | 4b4ae48f9a286ac536679d68dce9aa46d126249b (diff) | |
Fix read corruption after block clone after truncate
When copy_file_range overwrites a recent truncation, subsequent reads
can incorrectly determine that it is read hole instead of reading the
cloned blocks.
This can happen when the following conditions are met:
- Truncate adds blkid to dn_free_ranges
- A new TXG is created
- copy_file_range calls dmu_brt_clone which override the block pointer
and set DB_NOFILL
- Subsequent read, given DB_NOFILL, hits dbuf_read_impl and
dbuf_read_hole
- dbuf_read_hole calls dnode_block_freed, which returns TRUE because the
truncated blkids are still in dn_free_ranges
This will not happen if the clone and truncate are in the same TXG,
because the block clone would update the current TXG's dn_free_ranges,
which is why this bug only triggers under high IO load (such as
compilation).
Fix this by skipping the dnode_block_freed call if the block is
overridden. The fix shouldn't cause an issue when the cloned block is
subsequently freed in later TXGs, as dbuf_undirty would remove the
override.
This requires a dedicated test program as it is much harder to trigger
with scripts (this needs to generate a lot of I/O in short period of
time for the bug to trigger reliably).
Assisted-by: Gemini:gemini-3.1-pro
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Tony Hutter <hutter2@llnl.gov>
Signed-off-by: Gary Guo <gary@kernel.org>
Closes #18412
Closes #18421
Diffstat (limited to 'sys/dev/netmap/netmap_vale.c')
0 files changed, 0 insertions, 0 deletions
