diff options
Diffstat (limited to 'fs/btrfs/dev-replace.c')
| -rw-r--r-- | fs/btrfs/dev-replace.c | 64 | 
1 files changed, 23 insertions, 41 deletions
| diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c index dec01970d8c5..2aa48aecc52b 100644 --- a/fs/btrfs/dev-replace.c +++ b/fs/btrfs/dev-replace.c @@ -382,14 +382,6 @@ out:  	return ret;  } -void btrfs_after_dev_replace_commit(struct btrfs_fs_info *fs_info) -{ -	struct btrfs_dev_replace *dev_replace = &fs_info->dev_replace; - -	dev_replace->committed_cursor_left = -		dev_replace->cursor_left_last_write_of_item; -} -  static char* btrfs_dev_name(struct btrfs_device *device)  {  	if (!device || test_bit(BTRFS_DEV_STATE_MISSING, &device->dev_state)) @@ -408,11 +400,12 @@ int btrfs_dev_replace_start(struct btrfs_fs_info *fs_info,  	int ret;  	struct btrfs_device *tgt_device = NULL;  	struct btrfs_device *src_device = NULL; +	bool need_unlock; -	ret = btrfs_find_device_by_devspec(fs_info, srcdevid, -					    srcdev_name, &src_device); -	if (ret) -		return ret; +	src_device = btrfs_find_device_by_devspec(fs_info, srcdevid, +						  srcdev_name); +	if (IS_ERR(src_device)) +		return PTR_ERR(src_device);  	ret = btrfs_init_dev_replace_tgtdev(fs_info, tgtdev_name,  					    src_device, &tgt_device); @@ -432,6 +425,7 @@ int btrfs_dev_replace_start(struct btrfs_fs_info *fs_info,  		return PTR_ERR(trans);  	} +	need_unlock = true;  	btrfs_dev_replace_write_lock(dev_replace);  	switch (dev_replace->replace_state) {  	case BTRFS_IOCTL_DEV_REPLACE_STATE_NEVER_STARTED: @@ -440,6 +434,7 @@ int btrfs_dev_replace_start(struct btrfs_fs_info *fs_info,  		break;  	case BTRFS_IOCTL_DEV_REPLACE_STATE_STARTED:  	case BTRFS_IOCTL_DEV_REPLACE_STATE_SUSPENDED: +		ASSERT(0);  		ret = BTRFS_IOCTL_DEV_REPLACE_RESULT_ALREADY_STARTED;  		goto leave;  	} @@ -470,6 +465,7 @@ int btrfs_dev_replace_start(struct btrfs_fs_info *fs_info,  	atomic64_set(&dev_replace->num_write_errors, 0);  	atomic64_set(&dev_replace->num_uncorrectable_read_errors, 0);  	btrfs_dev_replace_write_unlock(dev_replace); +	need_unlock = false;  	ret = btrfs_sysfs_add_device_link(tgt_device->fs_devices, tgt_device);  	if (ret) @@ -481,7 +477,12 @@ int btrfs_dev_replace_start(struct btrfs_fs_info *fs_info,  	trans = btrfs_start_transaction(root, 0);  	if (IS_ERR(trans)) {  		ret = PTR_ERR(trans); +		need_unlock = true;  		btrfs_dev_replace_write_lock(dev_replace); +		dev_replace->replace_state = +			BTRFS_IOCTL_DEV_REPLACE_STATE_NEVER_STARTED; +		dev_replace->srcdev = NULL; +		dev_replace->tgtdev = NULL;  		goto leave;  	} @@ -503,9 +504,8 @@ int btrfs_dev_replace_start(struct btrfs_fs_info *fs_info,  	return ret;  leave: -	dev_replace->srcdev = NULL; -	dev_replace->tgtdev = NULL; -	btrfs_dev_replace_write_unlock(dev_replace); +	if (need_unlock) +		btrfs_dev_replace_write_unlock(dev_replace);  	btrfs_destroy_dev_replace_tgtdev(tgt_device);  	return ret;  } @@ -545,8 +545,8 @@ int btrfs_dev_replace_by_ioctl(struct btrfs_fs_info *fs_info,  static void btrfs_rm_dev_replace_blocked(struct btrfs_fs_info *fs_info)  {  	set_bit(BTRFS_FS_STATE_DEV_REPLACING, &fs_info->fs_state); -	wait_event(fs_info->replace_wait, !percpu_counter_sum( -		   &fs_info->bio_counter)); +	wait_event(fs_info->dev_replace.replace_wait, !percpu_counter_sum( +		   &fs_info->dev_replace.bio_counter));  }  /* @@ -555,7 +555,7 @@ static void btrfs_rm_dev_replace_blocked(struct btrfs_fs_info *fs_info)  static void btrfs_rm_dev_replace_unblocked(struct btrfs_fs_info *fs_info)  {  	clear_bit(BTRFS_FS_STATE_DEV_REPLACING, &fs_info->fs_state); -	wake_up(&fs_info->replace_wait); +	wake_up(&fs_info->dev_replace.replace_wait);  }  static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info, @@ -961,13 +961,10 @@ int btrfs_dev_replace_is_ongoing(struct btrfs_dev_replace *dev_replace)  void btrfs_dev_replace_read_lock(struct btrfs_dev_replace *dev_replace)  {  	read_lock(&dev_replace->lock); -	atomic_inc(&dev_replace->read_locks);  }  void btrfs_dev_replace_read_unlock(struct btrfs_dev_replace *dev_replace)  { -	ASSERT(atomic_read(&dev_replace->read_locks) > 0); -	atomic_dec(&dev_replace->read_locks);  	read_unlock(&dev_replace->lock);  } @@ -985,7 +982,6 @@ again:  void btrfs_dev_replace_write_unlock(struct btrfs_dev_replace *dev_replace)  { -	ASSERT(atomic_read(&dev_replace->blocking_readers) == 0);  	write_unlock(&dev_replace->lock);  } @@ -994,45 +990,31 @@ void btrfs_dev_replace_set_lock_blocking(  					struct btrfs_dev_replace *dev_replace)  {  	/* only set blocking for read lock */ -	ASSERT(atomic_read(&dev_replace->read_locks) > 0);  	atomic_inc(&dev_replace->blocking_readers);  	read_unlock(&dev_replace->lock);  } -/* acquire read lock and dec blocking cnt */ -void btrfs_dev_replace_clear_lock_blocking( -					struct btrfs_dev_replace *dev_replace) -{ -	/* only set blocking for read lock */ -	ASSERT(atomic_read(&dev_replace->read_locks) > 0); -	ASSERT(atomic_read(&dev_replace->blocking_readers) > 0); -	read_lock(&dev_replace->lock); -	/* Barrier implied by atomic_dec_and_test */ -	if (atomic_dec_and_test(&dev_replace->blocking_readers)) -		cond_wake_up_nomb(&dev_replace->read_lock_wq); -} -  void btrfs_bio_counter_inc_noblocked(struct btrfs_fs_info *fs_info)  { -	percpu_counter_inc(&fs_info->bio_counter); +	percpu_counter_inc(&fs_info->dev_replace.bio_counter);  }  void btrfs_bio_counter_sub(struct btrfs_fs_info *fs_info, s64 amount)  { -	percpu_counter_sub(&fs_info->bio_counter, amount); -	cond_wake_up_nomb(&fs_info->replace_wait); +	percpu_counter_sub(&fs_info->dev_replace.bio_counter, amount); +	cond_wake_up_nomb(&fs_info->dev_replace.replace_wait);  }  void btrfs_bio_counter_inc_blocked(struct btrfs_fs_info *fs_info)  {  	while (1) { -		percpu_counter_inc(&fs_info->bio_counter); +		percpu_counter_inc(&fs_info->dev_replace.bio_counter);  		if (likely(!test_bit(BTRFS_FS_STATE_DEV_REPLACING,  				     &fs_info->fs_state)))  			break;  		btrfs_bio_counter_dec(fs_info); -		wait_event(fs_info->replace_wait, +		wait_event(fs_info->dev_replace.replace_wait,  			   !test_bit(BTRFS_FS_STATE_DEV_REPLACING,  				     &fs_info->fs_state));  	} | 
