diff options
Diffstat (limited to 'fs/btrfs/volumes.c')
| -rw-r--r-- | fs/btrfs/volumes.c | 20 | 
1 files changed, 18 insertions, 2 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 35bb2d4ed29..5989a92236f 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -684,6 +684,12 @@ int btrfs_close_devices(struct btrfs_fs_devices *fs_devices)  		__btrfs_close_devices(fs_devices);  		free_fs_devices(fs_devices);  	} +	/* +	 * Wait for rcu kworkers under __btrfs_close_devices +	 * to finish all blkdev_puts so device is really +	 * free when umount is done. +	 */ +	rcu_barrier();  	return ret;  } @@ -2379,7 +2385,11 @@ static int btrfs_relocate_chunk(struct btrfs_root *root,  		return ret;  	trans = btrfs_start_transaction(root, 0); -	BUG_ON(IS_ERR(trans)); +	if (IS_ERR(trans)) { +		ret = PTR_ERR(trans); +		btrfs_std_error(root->fs_info, ret); +		return ret; +	}  	lock_chunks(root); @@ -3050,7 +3060,8 @@ static void __cancel_balance(struct btrfs_fs_info *fs_info)  	unset_balance_control(fs_info);  	ret = del_balance_item(fs_info->tree_root); -	BUG_ON(ret); +	if (ret) +		btrfs_std_error(fs_info, ret);  	atomic_set(&fs_info->mutually_exclusive_operation_running, 0);  } @@ -3230,6 +3241,11 @@ int btrfs_balance(struct btrfs_balance_control *bctl,  		update_ioctl_balance_args(fs_info, 0, bargs);  	} +	if ((ret && ret != -ECANCELED && ret != -ENOSPC) || +	    balance_need_close(fs_info)) { +		__cancel_balance(fs_info); +	} +  	wake_up(&fs_info->balance_wait_q);  	return ret;  |