for-5.9-rc7-tag
-----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEE8rQSAMVO+zA4DBdWxWXV+ddtWDsFAl93REAACgkQxWXV+ddt WDv0/A//XYr1XLC/5sMILHqYZ4ogiFxC3Nfjeyt6vfBPX3J0d2eHnw5Rw+ZHHHdQ qtoKWom9ZwCxjybghwmvfxJuohy+6Sc764aEj+rYpUcCmmUZsAZZpmwpZqpYG+0H DEn9p45T0MO+r5lsF/GdNqqsdXZfUlZy7PweIhZucQxENM8cowklqKCo4AU2IEW4 203THU3UxQayn0um6kaiesioh8TtT+R9UVAyyA3n6lGINHKG8AMy0ulS/M2Uzgq5 eAzWne4Opy+wLxubBdeqruPiQrFQp+JV/YhTTEHGKRXykRYXwZnCDYdK27X4UKkt g3Ne0cEd/JuxZfb3Mzsd7+MF0xr9xKJPziFXv7YZt0LkiHE+B0b/DwA9FksR9sdO 4BY2oe0gztstIMqQ5qnriJMDQxonyUt2G65YW8sCI9b32vRYaHLhCWZRYzbmftEO W4FJOnAI2It3Ib0CUkBjkPYkmH113Q6g59k015IpoYRGmExhnC59zhuijdmthxFJ S5PXFymVhxt9iMOKM0jE17Rp/j4hVg/bdFVHJryzlOsldjq63Vukqoo24SQhiqfY qYn/Ilkc/h1YD/pxehFAhZcbGfEdjD5oo8OkGoKIUXfv35r7JH/5F/x+4DxZNnYk n0oHJ7WBR01AlHAcuTvsN7z9O2ZX6wZufkkgKYLBvtGtyC71T3A= =MT2i -----END PGP SIGNATURE----- Merge tag 'for-5.9-rc7-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux Pull btrfs fixes from David Sterba: "Two more fixes. One is for a lockdep warning/lockup (also caught by syzbot), that one has been seen in practice. Regarding the other syzbot reports mentioned last time, they don't seem to be urgent and reliably reproducible so they'll be fixed later. The second fix is for a potential corruption when device replace finishes and the in-memory state of trim is not copied to the new device" * tag 'for-5.9-rc7-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux: btrfs: fix filesystem corruption after a device replace btrfs: move btrfs_rm_dev_replace_free_srcdev outside of all locks btrfs: move btrfs_scratch_superblocks into btrfs_dev_replace_finishing
This commit is contained in:
commit
4e3b9ce271
|
@ -599,6 +599,37 @@ static void btrfs_rm_dev_replace_unblocked(struct btrfs_fs_info *fs_info)
|
|||
wake_up(&fs_info->dev_replace.replace_wait);
|
||||
}
|
||||
|
||||
/*
|
||||
* When finishing the device replace, before swapping the source device with the
|
||||
* target device we must update the chunk allocation state in the target device,
|
||||
* as it is empty because replace works by directly copying the chunks and not
|
||||
* through the normal chunk allocation path.
|
||||
*/
|
||||
static int btrfs_set_target_alloc_state(struct btrfs_device *srcdev,
|
||||
struct btrfs_device *tgtdev)
|
||||
{
|
||||
struct extent_state *cached_state = NULL;
|
||||
u64 start = 0;
|
||||
u64 found_start;
|
||||
u64 found_end;
|
||||
int ret = 0;
|
||||
|
||||
lockdep_assert_held(&srcdev->fs_info->chunk_mutex);
|
||||
|
||||
while (!find_first_extent_bit(&srcdev->alloc_state, start,
|
||||
&found_start, &found_end,
|
||||
CHUNK_ALLOCATED, &cached_state)) {
|
||||
ret = set_extent_bits(&tgtdev->alloc_state, found_start,
|
||||
found_end, CHUNK_ALLOCATED);
|
||||
if (ret)
|
||||
break;
|
||||
start = found_end + 1;
|
||||
}
|
||||
|
||||
free_extent_state(cached_state);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info,
|
||||
int scrub_ret)
|
||||
{
|
||||
|
@ -673,8 +704,14 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info,
|
|||
dev_replace->time_stopped = ktime_get_real_seconds();
|
||||
dev_replace->item_needs_writeback = 1;
|
||||
|
||||
/* replace old device with new one in mapping tree */
|
||||
/*
|
||||
* Update allocation state in the new device and replace the old device
|
||||
* with the new one in the mapping tree.
|
||||
*/
|
||||
if (!scrub_ret) {
|
||||
scrub_ret = btrfs_set_target_alloc_state(src_device, tgt_device);
|
||||
if (scrub_ret)
|
||||
goto error;
|
||||
btrfs_dev_replace_update_device_in_mapping_tree(fs_info,
|
||||
src_device,
|
||||
tgt_device);
|
||||
|
@ -685,6 +722,7 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info,
|
|||
btrfs_dev_name(src_device),
|
||||
src_device->devid,
|
||||
rcu_str_deref(tgt_device->name), scrub_ret);
|
||||
error:
|
||||
up_write(&dev_replace->rwsem);
|
||||
mutex_unlock(&fs_info->chunk_mutex);
|
||||
mutex_unlock(&fs_info->fs_devices->device_list_mutex);
|
||||
|
@ -745,7 +783,9 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info,
|
|||
/* replace the sysfs entry */
|
||||
btrfs_sysfs_remove_devices_dir(fs_info->fs_devices, src_device);
|
||||
btrfs_sysfs_update_devid(tgt_device);
|
||||
btrfs_rm_dev_replace_free_srcdev(src_device);
|
||||
if (test_bit(BTRFS_DEV_STATE_WRITEABLE, &src_device->dev_state))
|
||||
btrfs_scratch_superblocks(fs_info, src_device->bdev,
|
||||
src_device->name->str);
|
||||
|
||||
/* write back the superblocks */
|
||||
trans = btrfs_start_transaction(root, 0);
|
||||
|
@ -754,6 +794,8 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info,
|
|||
|
||||
mutex_unlock(&dev_replace->lock_finishing_cancel_unmount);
|
||||
|
||||
btrfs_rm_dev_replace_free_srcdev(src_device);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1999,9 +1999,9 @@ static u64 btrfs_num_devices(struct btrfs_fs_info *fs_info)
|
|||
return num_devices;
|
||||
}
|
||||
|
||||
static void btrfs_scratch_superblocks(struct btrfs_fs_info *fs_info,
|
||||
struct block_device *bdev,
|
||||
const char *device_path)
|
||||
void btrfs_scratch_superblocks(struct btrfs_fs_info *fs_info,
|
||||
struct block_device *bdev,
|
||||
const char *device_path)
|
||||
{
|
||||
struct btrfs_super_block *disk_super;
|
||||
int copy_num;
|
||||
|
@ -2224,11 +2224,7 @@ void btrfs_rm_dev_replace_free_srcdev(struct btrfs_device *srcdev)
|
|||
struct btrfs_fs_info *fs_info = srcdev->fs_info;
|
||||
struct btrfs_fs_devices *fs_devices = srcdev->fs_devices;
|
||||
|
||||
if (test_bit(BTRFS_DEV_STATE_WRITEABLE, &srcdev->dev_state)) {
|
||||
/* zero out the old super if it is writable */
|
||||
btrfs_scratch_superblocks(fs_info, srcdev->bdev,
|
||||
srcdev->name->str);
|
||||
}
|
||||
mutex_lock(&uuid_mutex);
|
||||
|
||||
btrfs_close_bdev(srcdev);
|
||||
synchronize_rcu();
|
||||
|
@ -2258,6 +2254,7 @@ void btrfs_rm_dev_replace_free_srcdev(struct btrfs_device *srcdev)
|
|||
close_fs_devices(fs_devices);
|
||||
free_fs_devices(fs_devices);
|
||||
}
|
||||
mutex_unlock(&uuid_mutex);
|
||||
}
|
||||
|
||||
void btrfs_destroy_dev_replace_tgtdev(struct btrfs_device *tgtdev)
|
||||
|
|
|
@ -573,6 +573,9 @@ void btrfs_set_fs_info_ptr(struct btrfs_fs_info *fs_info);
|
|||
void btrfs_reset_fs_info_ptr(struct btrfs_fs_info *fs_info);
|
||||
bool btrfs_check_rw_degradable(struct btrfs_fs_info *fs_info,
|
||||
struct btrfs_device *failing_dev);
|
||||
void btrfs_scratch_superblocks(struct btrfs_fs_info *fs_info,
|
||||
struct block_device *bdev,
|
||||
const char *device_path);
|
||||
|
||||
int btrfs_bg_type_to_factor(u64 flags);
|
||||
const char *btrfs_bg_type_to_raid_name(u64 flags);
|
||||
|
|
Loading…
Reference in New Issue