You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This walk is inherently racy w.r.t. dbuf eviction and sync.
Consider:
0. A large sparse file with 3 levels of indirection.
1. A new L1 block is added to a brand new L2 block.
2. The L1 block syncs out and is immediately evicted.
3. Before the L3->L2 BP is updated in the L3 block,
dnode_free_range attempts to free the new L1.
In this case neither dnode_dirty_l1range nor dnode_next_offset
can find the newly synced-out L1 block and its L0 blocks:
- dnode_dirty_l1range uses in-memory index but the L1 is evicted
- dnode_next_offset considers on-disk BPs but the L3->L2 is missing
And then free_children will later PANIC because the L1 was not dirtied
during open context when freeing the range.
This case was found during testing llseek(SEEK_HOLE/SEEK_DATA)
without txg sync and is distinct from the _other_ free_childen
panic found and addressed by openzfs#16025.
The fix is to replace dnode_dirty_l1range with
dnode_next_offset(DNODE_FIND_DIRTY) which knows how to
find all dirty L1 blocks.
This PR also changes to use minlvl=1 to avoid redirtying
L2 blocks that are only dirtied in a prior txg. Successive
frees otherwise needlessly redirty already-empty L1s which
wastes time during txg sync turning them back into holes.
Signed-off-by: Robert Evans <[email protected]>
0 commit comments