btrfs: stripe_meta: carry raid56 metadata groups through a runtime enable or disable
The property path arms and disarms the trapped-space accounting of the
cached block groups, but stripe_alloc_sweep_groups() walked only DATA
space_infos: a runtime enable left already-cached raid56 metadata groups
unarmed until something else (a new chunk, a read-write transition)
initialised them, so their trapped and claimable bytes were missing from
metadata admission; a runtime disable left armed metadata groups' bytes
in the space_info after the option was gone. Walk METADATA space_infos
too, for both directions.
Two more things a runtime toggle needs under raid56 metadata:
The metadata retirement at commit returned at once without the option,
so after a disable the running transaction's open metadata runs were
never closed or drained and their block group references were held
until unmount, where btrfs_free_block_groups() asserts on them. Retire
unconditionally; the walk is over the list of groups with open runs and
is empty when there is nothing to do.
And the enable-time drain that keeps the write-hole check quiet until the
legacy allocator's writes have landed only waited for data (delalloc and
ordered extents). Tree blocks the legacy allocator placed in the
transaction that was running at the flip are written by that
transaction's commit, into the partly used stripes they were allocated
in -- under raid56 metadata that commit is the last legacy
read-modify-write, and the metadata RMW reporter says so:
read-modify-write of stripe
42860544 rewrites parity over committed
tree block
42860544 at generation 10 ... while writing generation 11:
write hole
btrfs: sub-stripe write to stripe
42860544 (block group
34603008)
outside any live stripe run: write hole window violated
WARNING: CPU: 1 PID: 408294 at fs/btrfs/block-group.c:2889
btrfs_stripe_check_write+0x109/0x150
Commit that transaction from the drain worker before arming the check.
The exposure of the enabling transaction itself is inherent -- its
blocks are already placed -- and bounded to that one commit.
Found by stripe-meta-toggle-test.sh (runtime enable with a fill to the
metadata edge, then a property-enabled filesystem disabled and
unmounted), on raid5 and raid6 metadata.
Assisted-by: Claude:claude-fable-5-1