Patch "btrfs: clean the old superblocks before freeing the device" has been added to the 4.8-stable tree
Subsystems (2)
This is a note to let you know that I've just added the patch titled
btrfs: clean the old superblocks before freeing the device
to the 4.8-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
btrfs-clean-the-old-superblocks-before-freeing-the-device.patch
and it can be found in the queue-4.8 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
cea67ab92d3d4da9f2b4141d87cb8664757daca0Mon Sep 17 00:00:00 2001
From: Jeff Mahoney <[email protected]>
Date: Tue, 20 Sep 2016 08:50:21 -0400
Subject: btrfs: clean the old superblocks before freeing the device
From: Jeff Mahoney <[email protected]>
commit cea67ab92d3d4da9f2b4141d87cb8664757daca0 upstream.
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.
--- fs/btrfs/volumes.c | 38 +++++++++++--------------------------- 1 file changed, 11 insertions(+), 27 deletions(-)
fs/btrfs/volumes.c +11 -27
@@ -1846,7 +1846,6 @@ int btrfs_rm_device(struct btrfs_root *ru64 num_devices;int ret =0 ;bool clear_super = false; -char *dev_name =NULL ;mutex_lock (&uuid_mutex);
@@ -1882,11 +1881,6 @@ int btrfs_rm_device(struct btrfs_root *rlist_del_init (&device->dev_alloc_list); device->fs_devices->rw_devices--;unlock_chunks (root); - dev_name =kstrdup (device->name->str,GFP_KERNEL ); -if (!dev_name) { - ret = -ENOMEM ; - goto error_undo; - } clear_super = true; }
@@ -1936,14 +1930,21 @@ int btrfs_rm_device(struct btrfs_root *rbtrfs_sysfs_rm_device_link (root->fs_info->fs_devices, device); } -btrfs_close_bdev (device); - -call_rcu (&device->rcu, free_device); - num_devices =btrfs_super_num_devices (root->fs_info->super_copy) -1 ;btrfs_set_super_num_devices (root->fs_info->super_copy, num_devices);mutex_unlock (&root->fs_info->fs_devices->device_list_mutex); +/* +* at this point, the device is zero sized and detached from +* the devices list. All that's left is to zero out the old +* supers and free the device. +*/ +if (device->writeable) +btrfs_scratch_superblocks (device->bdev, device->name->str); + +btrfs_close_bdev (device); +call_rcu (&device->rcu, free_device); +if (cur_devices->open_devices ==0 ) {struct btrfs_fs_devices *fs_devices; fs_devices = root->fs_info->fs_devices;
@@ -1962,24 +1963,7 @@ int btrfs_rm_device(struct btrfs_root *r root->fs_info->num_tolerated_disk_barrier_failures =btrfs_calc_num_tolerated_disk_barrier_failures (root->fs_info); -/* -* at this point, the device is zero sized. We want to -* remove it from the devices list and zero out the old super -*/ -if (clear_super) { -struct block_device *bdev; - - bdev =blkdev_get_by_path (dev_name,FMODE_READ |FMODE_EXCL , - root->fs_info->bdev_holder); -if (!IS_ERR (bdev)) { -btrfs_scratch_superblocks (bdev, dev_name); -blkdev_put (bdev,FMODE_READ |FMODE_EXCL ); - } - } - out: -kfree (dev_name); -mutex_unlock (&uuid_mutex);return ret;
Patches currently in stable-queue which might be from [email protected] are
queue-4.8/btrfs-clean-the-old-superblocks-before-freeing-the-device.patch queue-4.8/btrfs-fix-bug_on-in-btrfs_mark_buffer_dirty.patch