Re: [PATCH v4 2/2] btrfs: reset device back to allocation state when removing

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




On 26.11.19 г. 10:40 ч., Johannes Thumshirn wrote:
> When closing a device, btrfs_close_one_device() first allocates a new
> device, copies the device to close's name, replaces it in the dev_list
> with the copy and then finally frees it.
> 
> This involves two memory allocation, which can potentially fail. As this
> code path is tricky to unwind, the allocation failures where handled by
> BUG_ON()s.
> 
> But this copying isn't strictly needed, all that is needed is resetting
> the device in question to it's state it had after the allocation.
> 
> Signed-off-by: Johannes Thumshirn <jthumshirn@xxxxxxx>

Overall looks good one minor nit which can be fixed at commit time (or
ignored).

Reviewed-by: Nikolay Borisov <nborisov@xxxxxxxx>
> 
> ---
> Changes to v3:
> - Clear DEV_STATE_WRITABLE _after_ btrfs_close_bdev() (Nik)
> ---
>  fs/btrfs/volumes.c | 38 +++++++++++++++++---------------------
>  1 file changed, 17 insertions(+), 21 deletions(-)
> 
> diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
> index 2398b071bcf6..efabffa54a45 100644
> --- a/fs/btrfs/volumes.c
> +++ b/fs/btrfs/volumes.c
> @@ -1064,8 +1064,6 @@ static void btrfs_close_bdev(struct btrfs_device *device)
>  static void btrfs_close_one_device(struct btrfs_device *device)
>  {
>  	struct btrfs_fs_devices *fs_devices = device->fs_devices;
> -	struct btrfs_device *new_device;
> -	struct rcu_string *name;
>  
>  	if (test_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state) &&
>  	    device->devid != BTRFS_DEV_REPLACE_DEVID) {
> @@ -1073,29 +1071,27 @@ static void btrfs_close_one_device(struct btrfs_device *device)
>  		fs_devices->rw_devices--;
>  	}
>  
> -	if (test_bit(BTRFS_DEV_STATE_MISSING, &device->dev_state))
> +	if (test_bit(BTRFS_DEV_STATE_MISSING, &device->dev_state)) {
>  		fs_devices->missing_devices--;
> +		clear_bit(BTRFS_DEV_STATE_MISSING, &device->dev_state);
> +	}
nit: you can use test_and_clear_bit

>  
> +	clear_bit(BTRFS_DEV_STATE_IN_FS_METADATA, &device->dev_state);
>  	btrfs_close_bdev(device);
> -	if (device->bdev)
> +	if (device->bdev) {
>  		fs_devices->open_devices--;
> -
> -	new_device = btrfs_alloc_device(NULL, &device->devid,
> -					device->uuid);
> -	BUG_ON(IS_ERR(new_device)); /* -ENOMEM */
> -
> -	/* Safe because we are under uuid_mutex */
> -	if (device->name) {
> -		name = rcu_string_strdup(device->name->str, GFP_NOFS);
> -		BUG_ON(!name); /* -ENOMEM */
> -		rcu_assign_pointer(new_device->name, name);
> -	}
> -
> -	list_replace_rcu(&device->dev_list, &new_device->dev_list);
> -	new_device->fs_devices = device->fs_devices;
> -
> -	synchronize_rcu();
> -	btrfs_free_device(device);
> +		device->bdev = NULL;
> +	}
> +	clear_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state);
> +
> +	/* Verify the device is back in a pristine state  */
> +	ASSERT(!test_bit(BTRFS_DEV_STATE_FLUSH_SENT, &device->dev_state));
> +	ASSERT(!test_bit(BTRFS_DEV_STATE_REPLACE_TGT, &device->dev_state));
> +	ASSERT(list_empty(&device->dev_alloc_list));
> +	ASSERT(list_empty(&device->post_commit_list));
> +	ASSERT(atomic_read(&device->reada_in_flight) == 0);
> +	ASSERT(atomic_read(&device->dev_stats_ccnt) == 0);
> +	ASSERT(RB_EMPTY_ROOT(&device->alloc_state.state));
>  }
>  
>  static int close_fs_devices(struct btrfs_fs_devices *fs_devices)
> 



[Index of Archives]     [Linux Filesystem Development]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux