diff options
| author | Christian Brauner <brauner@kernel.org> | 2026-06-16 13:58:18 +0200 |
|---|---|---|
| committer | Christian Brauner <brauner@kernel.org> | 2026-06-29 10:31:49 +0200 |
| commit | 8b6b55bfc7d1a2d9e60a9cabc84ff888440a712a (patch) | |
| tree | 87f9eb6da178d03bd4be1173aaecec61cbc6f454 /drivers/phy/axiado/git@git.tavy.me:linux.git | |
| parent | 48b1cc0ac94d1ae89af7ab74e0329a8446b46715 (diff) | |
btrfs: deny freezing devices undergoing a replace
A device replace opens a target and, on success, frees the source on a live
filesystem from btrfs_dev_replace_finishing() - which cannot fail and also
runs from a kthread on mount resume. A bdev_freeze() racing the source free
or the target swap-in would freeze the filesystem through a claim that is
being torn down or replaced, leaving nothing for bdev_thaw() to rebalance.
Make both devices unfreezable for the whole replace, with the invariant that
a STARTED replace holds one deny on each device and any other state holds
none. The target is denied at open (btrfs_open_device_deny_freeze(), undone
on btrfs_init_dev_replace_tgtdev()'s error unwind); the source is denied at
the start of btrfs_dev_replace_start(), before mark_block_group_to_copy() so
every 'leave' unwind sees both denied.
The deny tracks the STARTED state and is dropped whenever the replace leaves
it: btrfs_dev_replace_finishing() re-allows the target it makes a member and
frees the source through btrfs_close_bdev(allow_freeze=true), and its
scrub-error path re-allows both as it cancels. Its early failures (before
the device swap) keep the replace STARTED and resumable, so both stay denied.
Suspending for unmount re-allows both, so they are reopened freezable at the
next mount where btrfs_resume_dev_replace_async() re-denies them (staying
suspended if a device is frozen right then); a replace cancelled from the
suspended state therefore destroys the target without allowing.
btrfs_close_bdev() and btrfs_destroy_dev_replace_tgtdev() take an allow_freeze
argument to carry this distinction; the unmount path
(btrfs_close_one_device()) passes false.
On resume, a failed kthread_run() re-allows both devices and goes through the
suspend path, resetting the replace to SUSPENDED and finishing the exclusive
operation instead of returning straight away. The (re)mount still aborts on
that error; routing it through suspend keeps the deny balanced against the
unmount teardown and additionally drops BTRFS_EXCLOP_DEV_REPLACE, closing a
pre-existing leak that was harmless on the failed mount that frees the fs but
would have wedged future exclusive operations after a failed remount-rw.
Link: https://patch.msgid.link/20260616-work-super-freeze_deny_upstream-v2-5-b3567c7f994b@kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Diffstat (limited to 'drivers/phy/axiado/git@git.tavy.me:linux.git')
0 files changed, 0 insertions, 0 deletions
