diff options
Diffstat (limited to 'fs/btrfs/scrub.c')
| -rw-r--r-- | fs/btrfs/scrub.c | 46 | 
1 files changed, 18 insertions, 28 deletions
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index a18e0e23f6a6..2544805544f0 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c @@ -2717,8 +2717,6 @@ int scrub_enumerate_chunks(struct scrub_ctx *sctx,  		mutex_unlock(&fs_info->scrub_lock);  		wake_up(&fs_info->scrub_pause_wait); -		dev_replace->cursor_left = dev_replace->cursor_right; -		dev_replace->item_needs_writeback = 1;  		btrfs_put_block_group(cache);  		if (ret)  			break; @@ -2732,6 +2730,9 @@ int scrub_enumerate_chunks(struct scrub_ctx *sctx,  			break;  		} +		dev_replace->cursor_left = dev_replace->cursor_right; +		dev_replace->item_needs_writeback = 1; +  		key.offset = found_key.offset + length;  		btrfs_release_path(path);  	} @@ -2783,7 +2784,6 @@ static noinline_for_stack int scrub_workers_get(struct btrfs_fs_info *fs_info,  {  	int ret = 0; -	mutex_lock(&fs_info->scrub_lock);  	if (fs_info->scrub_workers_refcnt == 0) {  		if (is_dev_replace)  			btrfs_init_workers(&fs_info->scrub_workers, "scrub", 1, @@ -2813,21 +2813,17 @@ static noinline_for_stack int scrub_workers_get(struct btrfs_fs_info *fs_info,  	}  	++fs_info->scrub_workers_refcnt;  out: -	mutex_unlock(&fs_info->scrub_lock); -  	return ret;  }  static noinline_for_stack void scrub_workers_put(struct btrfs_fs_info *fs_info)  { -	mutex_lock(&fs_info->scrub_lock);  	if (--fs_info->scrub_workers_refcnt == 0) {  		btrfs_stop_workers(&fs_info->scrub_workers);  		btrfs_stop_workers(&fs_info->scrub_wr_completion_workers);  		btrfs_stop_workers(&fs_info->scrub_nocow_workers);  	}  	WARN_ON(fs_info->scrub_workers_refcnt < 0); -	mutex_unlock(&fs_info->scrub_lock);  }  int btrfs_scrub_dev(struct btrfs_fs_info *fs_info, u64 devid, u64 start, @@ -2888,23 +2884,18 @@ int btrfs_scrub_dev(struct btrfs_fs_info *fs_info, u64 devid, u64 start,  		return -EINVAL;  	} -	ret = scrub_workers_get(fs_info, is_dev_replace); -	if (ret) -		return ret;  	mutex_lock(&fs_info->fs_devices->device_list_mutex);  	dev = btrfs_find_device(fs_info, devid, NULL, NULL);  	if (!dev || (dev->missing && !is_dev_replace)) {  		mutex_unlock(&fs_info->fs_devices->device_list_mutex); -		scrub_workers_put(fs_info);  		return -ENODEV;  	} -	mutex_lock(&fs_info->scrub_lock); +	mutex_lock(&fs_info->scrub_lock);  	if (!dev->in_fs_metadata || dev->is_tgtdev_for_dev_replace) {  		mutex_unlock(&fs_info->scrub_lock);  		mutex_unlock(&fs_info->fs_devices->device_list_mutex); -		scrub_workers_put(fs_info);  		return -EIO;  	} @@ -2915,10 +2906,17 @@ int btrfs_scrub_dev(struct btrfs_fs_info *fs_info, u64 devid, u64 start,  		btrfs_dev_replace_unlock(&fs_info->dev_replace);  		mutex_unlock(&fs_info->scrub_lock);  		mutex_unlock(&fs_info->fs_devices->device_list_mutex); -		scrub_workers_put(fs_info);  		return -EINPROGRESS;  	}  	btrfs_dev_replace_unlock(&fs_info->dev_replace); + +	ret = scrub_workers_get(fs_info, is_dev_replace); +	if (ret) { +		mutex_unlock(&fs_info->scrub_lock); +		mutex_unlock(&fs_info->fs_devices->device_list_mutex); +		return ret; +	} +  	sctx = scrub_setup_ctx(dev, is_dev_replace);  	if (IS_ERR(sctx)) {  		mutex_unlock(&fs_info->scrub_lock); @@ -2931,13 +2929,15 @@ int btrfs_scrub_dev(struct btrfs_fs_info *fs_info, u64 devid, u64 start,  	atomic_inc(&fs_info->scrubs_running);  	mutex_unlock(&fs_info->scrub_lock); -	mutex_unlock(&fs_info->fs_devices->device_list_mutex);  	if (!is_dev_replace) { -		down_read(&fs_info->scrub_super_lock); +		/* +		 * by holding device list mutex, we can +		 * kick off writing super in log tree sync. +		 */  		ret = scrub_supers(sctx, dev); -		up_read(&fs_info->scrub_super_lock);  	} +	mutex_unlock(&fs_info->fs_devices->device_list_mutex);  	if (!ret)  		ret = scrub_enumerate_chunks(sctx, dev, start, end, @@ -2954,10 +2954,10 @@ int btrfs_scrub_dev(struct btrfs_fs_info *fs_info, u64 devid, u64 start,  	mutex_lock(&fs_info->scrub_lock);  	dev->scrub_device = NULL; +	scrub_workers_put(fs_info);  	mutex_unlock(&fs_info->scrub_lock);  	scrub_free_ctx(sctx); -	scrub_workers_put(fs_info);  	return ret;  } @@ -2987,16 +2987,6 @@ void btrfs_scrub_continue(struct btrfs_root *root)  	wake_up(&fs_info->scrub_pause_wait);  } -void btrfs_scrub_pause_super(struct btrfs_root *root) -{ -	down_write(&root->fs_info->scrub_super_lock); -} - -void btrfs_scrub_continue_super(struct btrfs_root *root) -{ -	up_write(&root->fs_info->scrub_super_lock); -} -  int btrfs_scrub_cancel(struct btrfs_fs_info *fs_info)  {  	mutex_lock(&fs_info->scrub_lock);  |