Skip to content

Commit cea67ab

Browse files
jeffmahoneykdave
authored andcommitted
btrfs: clean the old superblocks before freeing the device
btrfs_rm_device frees the block device but then re-opens it using the saved device name. A race exists between the close and the re-open that allows the block size to be changed. The result is getting stuck forever in the reclaim loop in __getblk_slow. This patch moves the superblock cleanup before closing the block device, which is also consistent with other callers. We also don't need a private copy of dev_name as the whole routine operates under the uuid_mutex. Signed-off-by: Jeff Mahoney <[email protected]> Reviewed-by: David Sterba <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent 0279422 commit cea67ab

File tree

1 file changed

+11
-27
lines changed

1 file changed

+11
-27
lines changed

fs/btrfs/volumes.c

Lines changed: 11 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1846,7 +1846,6 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path, u64 devid)
18461846
u64 num_devices;
18471847
int ret = 0;
18481848
bool clear_super = false;
1849-
char *dev_name = NULL;
18501849

18511850
mutex_lock(&uuid_mutex);
18521851

@@ -1882,11 +1881,6 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path, u64 devid)
18821881
list_del_init(&device->dev_alloc_list);
18831882
device->fs_devices->rw_devices--;
18841883
unlock_chunks(root);
1885-
dev_name = kstrdup(device->name->str, GFP_KERNEL);
1886-
if (!dev_name) {
1887-
ret = -ENOMEM;
1888-
goto error_undo;
1889-
}
18901884
clear_super = true;
18911885
}
18921886

@@ -1936,14 +1930,21 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path, u64 devid)
19361930
btrfs_sysfs_rm_device_link(root->fs_info->fs_devices, device);
19371931
}
19381932

1939-
btrfs_close_bdev(device);
1940-
1941-
call_rcu(&device->rcu, free_device);
1942-
19431933
num_devices = btrfs_super_num_devices(root->fs_info->super_copy) - 1;
19441934
btrfs_set_super_num_devices(root->fs_info->super_copy, num_devices);
19451935
mutex_unlock(&root->fs_info->fs_devices->device_list_mutex);
19461936

1937+
/*
1938+
* at this point, the device is zero sized and detached from
1939+
* the devices list. All that's left is to zero out the old
1940+
* supers and free the device.
1941+
*/
1942+
if (device->writeable)
1943+
btrfs_scratch_superblocks(device->bdev, device->name->str);
1944+
1945+
btrfs_close_bdev(device);
1946+
call_rcu(&device->rcu, free_device);
1947+
19471948
if (cur_devices->open_devices == 0) {
19481949
struct btrfs_fs_devices *fs_devices;
19491950
fs_devices = root->fs_info->fs_devices;
@@ -1962,24 +1963,7 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path, u64 devid)
19621963
root->fs_info->num_tolerated_disk_barrier_failures =
19631964
btrfs_calc_num_tolerated_disk_barrier_failures(root->fs_info);
19641965

1965-
/*
1966-
* at this point, the device is zero sized. We want to
1967-
* remove it from the devices list and zero out the old super
1968-
*/
1969-
if (clear_super) {
1970-
struct block_device *bdev;
1971-
1972-
bdev = blkdev_get_by_path(dev_name, FMODE_READ | FMODE_EXCL,
1973-
root->fs_info->bdev_holder);
1974-
if (!IS_ERR(bdev)) {
1975-
btrfs_scratch_superblocks(bdev, dev_name);
1976-
blkdev_put(bdev, FMODE_READ | FMODE_EXCL);
1977-
}
1978-
}
1979-
19801966
out:
1981-
kfree(dev_name);
1982-
19831967
mutex_unlock(&uuid_mutex);
19841968
return ret;
19851969

0 commit comments

Comments
 (0)