diff options
Diffstat (limited to 'fs/btrfs/ioctl.c')
| -rw-r--r-- | fs/btrfs/ioctl.c | 317 | 
1 files changed, 236 insertions, 81 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 5b3429ab8ec..4b4516770f0 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -55,6 +55,7 @@  #include "backref.h"  #include "rcu-string.h"  #include "send.h" +#include "dev-replace.h"  /* Mask out flags that are inappropriate for the given type of inode. */  static inline __u32 btrfs_mask_flags(umode_t mode, __u32 flags) @@ -140,8 +141,11 @@ void btrfs_inherit_iflags(struct inode *inode, struct inode *dir)  		BTRFS_I(inode)->flags |= BTRFS_INODE_COMPRESS;  	} -	if (flags & BTRFS_INODE_NODATACOW) +	if (flags & BTRFS_INODE_NODATACOW) {  		BTRFS_I(inode)->flags |= BTRFS_INODE_NODATACOW; +		if (S_ISREG(inode->i_mode)) +			BTRFS_I(inode)->flags |= BTRFS_INODE_NODATASUM; +	}  	btrfs_update_iflags(inode);  } @@ -571,8 +575,12 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry,  		ret = btrfs_commit_transaction(trans,  					       root->fs_info->extent_root);  	} -	if (ret) +	if (ret) { +		/* cleanup_transaction has freed this for us */ +		if (trans->aborted) +			pending_snapshot = NULL;  		goto fail; +	}  	ret = pending_snapshot->error;  	if (ret) @@ -705,6 +713,16 @@ static noinline int btrfs_mksubvol(struct path *parent,  	if (error)  		goto out_dput; +	/* +	 * even if this name doesn't exist, we may get hash collisions. +	 * check for them now when we can safely fail +	 */ +	error = btrfs_check_dir_item_collision(BTRFS_I(dir)->root, +					       dir->i_ino, name, +					       namelen); +	if (error) +		goto out_dput; +  	down_read(&BTRFS_I(dir)->root->fs_info->subvol_sem);  	if (btrfs_root_refs(&BTRFS_I(dir)->root->root_item) == 0) @@ -1293,12 +1311,13 @@ out_ra:  	return ret;  } -static noinline int btrfs_ioctl_resize(struct btrfs_root *root, +static noinline int btrfs_ioctl_resize(struct file *file,  					void __user *arg)  {  	u64 new_size;  	u64 old_size;  	u64 devid = 1; +	struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root;  	struct btrfs_ioctl_vol_args *vol_args;  	struct btrfs_trans_handle *trans;  	struct btrfs_device *device = NULL; @@ -1313,13 +1332,17 @@ static noinline int btrfs_ioctl_resize(struct btrfs_root *root,  	if (!capable(CAP_SYS_ADMIN))  		return -EPERM; -	mutex_lock(&root->fs_info->volume_mutex); -	if (root->fs_info->balance_ctl) { -		printk(KERN_INFO "btrfs: balance in progress\n"); -		ret = -EINVAL; -		goto out; +	ret = mnt_want_write_file(file); +	if (ret) +		return ret; + +	if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running, +			1)) { +		pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n"); +		return -EINPROGRESS;  	} +	mutex_lock(&root->fs_info->volume_mutex);  	vol_args = memdup_user(arg, sizeof(*vol_args));  	if (IS_ERR(vol_args)) {  		ret = PTR_ERR(vol_args); @@ -1339,7 +1362,7 @@ static noinline int btrfs_ioctl_resize(struct btrfs_root *root,  		printk(KERN_INFO "btrfs: resizing devid %llu\n",  		       (unsigned long long)devid);  	} -	device = btrfs_find_device(root, devid, NULL, NULL); +	device = btrfs_find_device(root->fs_info, devid, NULL, NULL);  	if (!device) {  		printk(KERN_INFO "btrfs: resizer unable to find device %llu\n",  		       (unsigned long long)devid); @@ -1371,6 +1394,11 @@ static noinline int btrfs_ioctl_resize(struct btrfs_root *root,  		}  	} +	if (device->is_tgtdev_for_dev_replace) { +		ret = -EINVAL; +		goto out_free; +	} +  	old_size = device->total_bytes;  	if (mod < 0) { @@ -1409,12 +1437,14 @@ static noinline int btrfs_ioctl_resize(struct btrfs_root *root,  		btrfs_commit_transaction(trans, root);  	} else if (new_size < old_size) {  		ret = btrfs_shrink_device(device, new_size); -	} +	} /* equal, nothing need to do */  out_free:  	kfree(vol_args);  out:  	mutex_unlock(&root->fs_info->volume_mutex); +	mnt_drop_write_file(file); +	atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0);  	return ret;  } @@ -2156,9 +2186,17 @@ static int btrfs_ioctl_defrag(struct file *file, void __user *argp)  	if (btrfs_root_readonly(root))  		return -EROFS; +	if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running, +			1)) { +		pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n"); +		return -EINPROGRESS; +	}  	ret = mnt_want_write_file(file); -	if (ret) +	if (ret) { +		atomic_set(&root->fs_info->mutually_exclusive_operation_running, +			   0);  		return ret; +	}  	switch (inode->i_mode & S_IFMT) {  	case S_IFDIR: @@ -2210,6 +2248,7 @@ static int btrfs_ioctl_defrag(struct file *file, void __user *argp)  	}  out:  	mnt_drop_write_file(file); +	atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0);  	return ret;  } @@ -2221,13 +2260,13 @@ static long btrfs_ioctl_add_dev(struct btrfs_root *root, void __user *arg)  	if (!capable(CAP_SYS_ADMIN))  		return -EPERM; -	mutex_lock(&root->fs_info->volume_mutex); -	if (root->fs_info->balance_ctl) { -		printk(KERN_INFO "btrfs: balance in progress\n"); -		ret = -EINVAL; -		goto out; +	if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running, +			1)) { +		pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n"); +		return -EINPROGRESS;  	} +	mutex_lock(&root->fs_info->volume_mutex);  	vol_args = memdup_user(arg, sizeof(*vol_args));  	if (IS_ERR(vol_args)) {  		ret = PTR_ERR(vol_args); @@ -2240,27 +2279,31 @@ static long btrfs_ioctl_add_dev(struct btrfs_root *root, void __user *arg)  	kfree(vol_args);  out:  	mutex_unlock(&root->fs_info->volume_mutex); +	atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0);  	return ret;  } -static long btrfs_ioctl_rm_dev(struct btrfs_root *root, void __user *arg) +static long btrfs_ioctl_rm_dev(struct file *file, void __user *arg)  { +	struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root;  	struct btrfs_ioctl_vol_args *vol_args;  	int ret;  	if (!capable(CAP_SYS_ADMIN))  		return -EPERM; -	if (root->fs_info->sb->s_flags & MS_RDONLY) -		return -EROFS; +	ret = mnt_want_write_file(file); +	if (ret) +		return ret; -	mutex_lock(&root->fs_info->volume_mutex); -	if (root->fs_info->balance_ctl) { -		printk(KERN_INFO "btrfs: balance in progress\n"); -		ret = -EINVAL; -		goto out; +	if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running, +			1)) { +		pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n"); +		mnt_drop_write_file(file); +		return -EINPROGRESS;  	} +	mutex_lock(&root->fs_info->volume_mutex);  	vol_args = memdup_user(arg, sizeof(*vol_args));  	if (IS_ERR(vol_args)) {  		ret = PTR_ERR(vol_args); @@ -2273,6 +2316,8 @@ static long btrfs_ioctl_rm_dev(struct btrfs_root *root, void __user *arg)  	kfree(vol_args);  out:  	mutex_unlock(&root->fs_info->volume_mutex); +	mnt_drop_write_file(file); +	atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0);  	return ret;  } @@ -2328,7 +2373,7 @@ static long btrfs_ioctl_dev_info(struct btrfs_root *root, void __user *arg)  		s_uuid = di_args->uuid;  	mutex_lock(&fs_devices->device_list_mutex); -	dev = btrfs_find_device(root, di_args->devid, s_uuid, NULL); +	dev = btrfs_find_device(root->fs_info, di_args->devid, s_uuid, NULL);  	mutex_unlock(&fs_devices->device_list_mutex);  	if (!dev) { @@ -2821,12 +2866,19 @@ static long btrfs_ioctl_default_subvol(struct file *file, void __user *argp)  	struct btrfs_disk_key disk_key;  	u64 objectid = 0;  	u64 dir_id; +	int ret;  	if (!capable(CAP_SYS_ADMIN))  		return -EPERM; -	if (copy_from_user(&objectid, argp, sizeof(objectid))) -		return -EFAULT; +	ret = mnt_want_write_file(file); +	if (ret) +		return ret; + +	if (copy_from_user(&objectid, argp, sizeof(objectid))) { +		ret = -EFAULT; +		goto out; +	}  	if (!objectid)  		objectid = root->root_key.objectid; @@ -2836,21 +2888,28 @@ static long btrfs_ioctl_default_subvol(struct file *file, void __user *argp)  	location.offset = (u64)-1;  	new_root = btrfs_read_fs_root_no_name(root->fs_info, &location); -	if (IS_ERR(new_root)) -		return PTR_ERR(new_root); +	if (IS_ERR(new_root)) { +		ret = PTR_ERR(new_root); +		goto out; +	} -	if (btrfs_root_refs(&new_root->root_item) == 0) -		return -ENOENT; +	if (btrfs_root_refs(&new_root->root_item) == 0) { +		ret = -ENOENT; +		goto out; +	}  	path = btrfs_alloc_path(); -	if (!path) -		return -ENOMEM; +	if (!path) { +		ret = -ENOMEM; +		goto out; +	}  	path->leave_spinning = 1;  	trans = btrfs_start_transaction(root, 1);  	if (IS_ERR(trans)) {  		btrfs_free_path(path); -		return PTR_ERR(trans); +		ret = PTR_ERR(trans); +		goto out;  	}  	dir_id = btrfs_super_root_dir(root->fs_info->super_copy); @@ -2861,7 +2920,8 @@ static long btrfs_ioctl_default_subvol(struct file *file, void __user *argp)  		btrfs_end_transaction(trans, root);  		printk(KERN_ERR "Umm, you don't have the default dir item, "  		       "this isn't going to work\n"); -		return -ENOENT; +		ret = -ENOENT; +		goto out;  	}  	btrfs_cpu_key_to_disk(&disk_key, &new_root->root_key); @@ -2871,8 +2931,9 @@ static long btrfs_ioctl_default_subvol(struct file *file, void __user *argp)  	btrfs_set_fs_incompat(root->fs_info, DEFAULT_SUBVOL);  	btrfs_end_transaction(trans, root); - -	return 0; +out: +	mnt_drop_write_file(file); +	return ret;  }  void btrfs_get_block_group_info(struct list_head *groups_list, @@ -3036,32 +3097,38 @@ long btrfs_ioctl_trans_end(struct file *file)  	return 0;  } -static noinline long btrfs_ioctl_start_sync(struct file *file, void __user *argp) +static noinline long btrfs_ioctl_start_sync(struct btrfs_root *root, +					    void __user *argp)  { -	struct btrfs_root *root = BTRFS_I(file->f_dentry->d_inode)->root;  	struct btrfs_trans_handle *trans;  	u64 transid;  	int ret; -	trans = btrfs_start_transaction(root, 0); -	if (IS_ERR(trans)) -		return PTR_ERR(trans); +	trans = btrfs_attach_transaction(root); +	if (IS_ERR(trans)) { +		if (PTR_ERR(trans) != -ENOENT) +			return PTR_ERR(trans); + +		/* No running transaction, don't bother */ +		transid = root->fs_info->last_trans_committed; +		goto out; +	}  	transid = trans->transid;  	ret = btrfs_commit_transaction_async(trans, root, 0);  	if (ret) {  		btrfs_end_transaction(trans, root);  		return ret;  	} - +out:  	if (argp)  		if (copy_to_user(argp, &transid, sizeof(transid)))  			return -EFAULT;  	return 0;  } -static noinline long btrfs_ioctl_wait_sync(struct file *file, void __user *argp) +static noinline long btrfs_ioctl_wait_sync(struct btrfs_root *root, +					   void __user *argp)  { -	struct btrfs_root *root = BTRFS_I(file->f_dentry->d_inode)->root;  	u64 transid;  	if (argp) { @@ -3073,10 +3140,11 @@ static noinline long btrfs_ioctl_wait_sync(struct file *file, void __user *argp)  	return btrfs_wait_for_commit(root, transid);  } -static long btrfs_ioctl_scrub(struct btrfs_root *root, void __user *arg) +static long btrfs_ioctl_scrub(struct file *file, void __user *arg)  { -	int ret; +	struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root;  	struct btrfs_ioctl_scrub_args *sa; +	int ret;  	if (!capable(CAP_SYS_ADMIN))  		return -EPERM; @@ -3085,12 +3153,22 @@ static long btrfs_ioctl_scrub(struct btrfs_root *root, void __user *arg)  	if (IS_ERR(sa))  		return PTR_ERR(sa); -	ret = btrfs_scrub_dev(root, sa->devid, sa->start, sa->end, -			      &sa->progress, sa->flags & BTRFS_SCRUB_READONLY); +	if (!(sa->flags & BTRFS_SCRUB_READONLY)) { +		ret = mnt_want_write_file(file); +		if (ret) +			goto out; +	} + +	ret = btrfs_scrub_dev(root->fs_info, sa->devid, sa->start, sa->end, +			      &sa->progress, sa->flags & BTRFS_SCRUB_READONLY, +			      0);  	if (copy_to_user(arg, sa, sizeof(*sa)))  		ret = -EFAULT; +	if (!(sa->flags & BTRFS_SCRUB_READONLY)) +		mnt_drop_write_file(file); +out:  	kfree(sa);  	return ret;  } @@ -3100,7 +3178,7 @@ static long btrfs_ioctl_scrub_cancel(struct btrfs_root *root, void __user *arg)  	if (!capable(CAP_SYS_ADMIN))  		return -EPERM; -	return btrfs_scrub_cancel(root); +	return btrfs_scrub_cancel(root->fs_info);  }  static long btrfs_ioctl_scrub_progress(struct btrfs_root *root, @@ -3149,6 +3227,51 @@ static long btrfs_ioctl_get_dev_stats(struct btrfs_root *root,  	return ret;  } +static long btrfs_ioctl_dev_replace(struct btrfs_root *root, void __user *arg) +{ +	struct btrfs_ioctl_dev_replace_args *p; +	int ret; + +	if (!capable(CAP_SYS_ADMIN)) +		return -EPERM; + +	p = memdup_user(arg, sizeof(*p)); +	if (IS_ERR(p)) +		return PTR_ERR(p); + +	switch (p->cmd) { +	case BTRFS_IOCTL_DEV_REPLACE_CMD_START: +		if (atomic_xchg( +			&root->fs_info->mutually_exclusive_operation_running, +			1)) { +			pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n"); +			ret = -EINPROGRESS; +		} else { +			ret = btrfs_dev_replace_start(root, p); +			atomic_set( +			 &root->fs_info->mutually_exclusive_operation_running, +			 0); +		} +		break; +	case BTRFS_IOCTL_DEV_REPLACE_CMD_STATUS: +		btrfs_dev_replace_status(root->fs_info, p); +		ret = 0; +		break; +	case BTRFS_IOCTL_DEV_REPLACE_CMD_CANCEL: +		ret = btrfs_dev_replace_cancel(root->fs_info, p); +		break; +	default: +		ret = -EINVAL; +		break; +	} + +	if (copy_to_user(arg, p, sizeof(*p))) +		ret = -EFAULT; + +	kfree(p); +	return ret; +} +  static long btrfs_ioctl_ino_to_path(struct btrfs_root *root, void __user *arg)  {  	int ret = 0; @@ -3315,6 +3438,7 @@ static long btrfs_ioctl_balance(struct file *file, void __user *arg)  	struct btrfs_ioctl_balance_args *bargs;  	struct btrfs_balance_control *bctl;  	int ret; +	int need_to_clear_lock = 0;  	if (!capable(CAP_SYS_ADMIN))  		return -EPERM; @@ -3350,10 +3474,13 @@ static long btrfs_ioctl_balance(struct file *file, void __user *arg)  		bargs = NULL;  	} -	if (fs_info->balance_ctl) { +	if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running, +			1)) { +		pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n");  		ret = -EINPROGRESS;  		goto out_bargs;  	} +	need_to_clear_lock = 1;  	bctl = kzalloc(sizeof(*bctl), GFP_NOFS);  	if (!bctl) { @@ -3387,6 +3514,9 @@ do_balance:  out_bargs:  	kfree(bargs);  out: +	if (need_to_clear_lock) +		atomic_set(&root->fs_info->mutually_exclusive_operation_running, +			   0);  	mutex_unlock(&fs_info->balance_mutex);  	mutex_unlock(&fs_info->volume_mutex);  	mnt_drop_write_file(file); @@ -3441,8 +3571,9 @@ out:  	return ret;  } -static long btrfs_ioctl_quota_ctl(struct btrfs_root *root, void __user *arg) +static long btrfs_ioctl_quota_ctl(struct file *file, void __user *arg)  { +	struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root;  	struct btrfs_ioctl_quota_ctl_args *sa;  	struct btrfs_trans_handle *trans = NULL;  	int ret; @@ -3451,12 +3582,15 @@ static long btrfs_ioctl_quota_ctl(struct btrfs_root *root, void __user *arg)  	if (!capable(CAP_SYS_ADMIN))  		return -EPERM; -	if (root->fs_info->sb->s_flags & MS_RDONLY) -		return -EROFS; +	ret = mnt_want_write_file(file); +	if (ret) +		return ret;  	sa = memdup_user(arg, sizeof(*sa)); -	if (IS_ERR(sa)) -		return PTR_ERR(sa); +	if (IS_ERR(sa)) { +		ret = PTR_ERR(sa); +		goto drop_write; +	}  	if (sa->cmd != BTRFS_QUOTA_CTL_RESCAN) {  		trans = btrfs_start_transaction(root, 2); @@ -3489,14 +3623,16 @@ static long btrfs_ioctl_quota_ctl(struct btrfs_root *root, void __user *arg)  		if (err && !ret)  			ret = err;  	} -  out:  	kfree(sa); +drop_write: +	mnt_drop_write_file(file);  	return ret;  } -static long btrfs_ioctl_qgroup_assign(struct btrfs_root *root, void __user *arg) +static long btrfs_ioctl_qgroup_assign(struct file *file, void __user *arg)  { +	struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root;  	struct btrfs_ioctl_qgroup_assign_args *sa;  	struct btrfs_trans_handle *trans;  	int ret; @@ -3505,12 +3641,15 @@ static long btrfs_ioctl_qgroup_assign(struct btrfs_root *root, void __user *arg)  	if (!capable(CAP_SYS_ADMIN))  		return -EPERM; -	if (root->fs_info->sb->s_flags & MS_RDONLY) -		return -EROFS; +	ret = mnt_want_write_file(file); +	if (ret) +		return ret;  	sa = memdup_user(arg, sizeof(*sa)); -	if (IS_ERR(sa)) -		return PTR_ERR(sa); +	if (IS_ERR(sa)) { +		ret = PTR_ERR(sa); +		goto drop_write; +	}  	trans = btrfs_join_transaction(root);  	if (IS_ERR(trans)) { @@ -3533,11 +3672,14 @@ static long btrfs_ioctl_qgroup_assign(struct btrfs_root *root, void __user *arg)  out:  	kfree(sa); +drop_write: +	mnt_drop_write_file(file);  	return ret;  } -static long btrfs_ioctl_qgroup_create(struct btrfs_root *root, void __user *arg) +static long btrfs_ioctl_qgroup_create(struct file *file, void __user *arg)  { +	struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root;  	struct btrfs_ioctl_qgroup_create_args *sa;  	struct btrfs_trans_handle *trans;  	int ret; @@ -3546,12 +3688,15 @@ static long btrfs_ioctl_qgroup_create(struct btrfs_root *root, void __user *arg)  	if (!capable(CAP_SYS_ADMIN))  		return -EPERM; -	if (root->fs_info->sb->s_flags & MS_RDONLY) -		return -EROFS; +	ret = mnt_want_write_file(file); +	if (ret) +		return ret;  	sa = memdup_user(arg, sizeof(*sa)); -	if (IS_ERR(sa)) -		return PTR_ERR(sa); +	if (IS_ERR(sa)) { +		ret = PTR_ERR(sa); +		goto drop_write; +	}  	trans = btrfs_join_transaction(root);  	if (IS_ERR(trans)) { @@ -3573,11 +3718,14 @@ static long btrfs_ioctl_qgroup_create(struct btrfs_root *root, void __user *arg)  out:  	kfree(sa); +drop_write: +	mnt_drop_write_file(file);  	return ret;  } -static long btrfs_ioctl_qgroup_limit(struct btrfs_root *root, void __user *arg) +static long btrfs_ioctl_qgroup_limit(struct file *file, void __user *arg)  { +	struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root;  	struct btrfs_ioctl_qgroup_limit_args *sa;  	struct btrfs_trans_handle *trans;  	int ret; @@ -3587,12 +3735,15 @@ static long btrfs_ioctl_qgroup_limit(struct btrfs_root *root, void __user *arg)  	if (!capable(CAP_SYS_ADMIN))  		return -EPERM; -	if (root->fs_info->sb->s_flags & MS_RDONLY) -		return -EROFS; +	ret = mnt_want_write_file(file); +	if (ret) +		return ret;  	sa = memdup_user(arg, sizeof(*sa)); -	if (IS_ERR(sa)) -		return PTR_ERR(sa); +	if (IS_ERR(sa)) { +		ret = PTR_ERR(sa); +		goto drop_write; +	}  	trans = btrfs_join_transaction(root);  	if (IS_ERR(trans)) { @@ -3615,6 +3766,8 @@ static long btrfs_ioctl_qgroup_limit(struct btrfs_root *root, void __user *arg)  out:  	kfree(sa); +drop_write: +	mnt_drop_write_file(file);  	return ret;  } @@ -3735,11 +3888,11 @@ long btrfs_ioctl(struct file *file, unsigned int  	case BTRFS_IOC_DEFRAG_RANGE:  		return btrfs_ioctl_defrag(file, argp);  	case BTRFS_IOC_RESIZE: -		return btrfs_ioctl_resize(root, argp); +		return btrfs_ioctl_resize(file, argp);  	case BTRFS_IOC_ADD_DEV:  		return btrfs_ioctl_add_dev(root, argp);  	case BTRFS_IOC_RM_DEV: -		return btrfs_ioctl_rm_dev(root, argp); +		return btrfs_ioctl_rm_dev(file, argp);  	case BTRFS_IOC_FS_INFO:  		return btrfs_ioctl_fs_info(root, argp);  	case BTRFS_IOC_DEV_INFO: @@ -3768,11 +3921,11 @@ long btrfs_ioctl(struct file *file, unsigned int  		btrfs_sync_fs(file->f_dentry->d_sb, 1);  		return 0;  	case BTRFS_IOC_START_SYNC: -		return btrfs_ioctl_start_sync(file, argp); +		return btrfs_ioctl_start_sync(root, argp);  	case BTRFS_IOC_WAIT_SYNC: -		return btrfs_ioctl_wait_sync(file, argp); +		return btrfs_ioctl_wait_sync(root, argp);  	case BTRFS_IOC_SCRUB: -		return btrfs_ioctl_scrub(root, argp); +		return btrfs_ioctl_scrub(file, argp);  	case BTRFS_IOC_SCRUB_CANCEL:  		return btrfs_ioctl_scrub_cancel(root, argp);  	case BTRFS_IOC_SCRUB_PROGRESS: @@ -3790,13 +3943,15 @@ long btrfs_ioctl(struct file *file, unsigned int  	case BTRFS_IOC_GET_DEV_STATS:  		return btrfs_ioctl_get_dev_stats(root, argp);  	case BTRFS_IOC_QUOTA_CTL: -		return btrfs_ioctl_quota_ctl(root, argp); +		return btrfs_ioctl_quota_ctl(file, argp);  	case BTRFS_IOC_QGROUP_ASSIGN: -		return btrfs_ioctl_qgroup_assign(root, argp); +		return btrfs_ioctl_qgroup_assign(file, argp);  	case BTRFS_IOC_QGROUP_CREATE: -		return btrfs_ioctl_qgroup_create(root, argp); +		return btrfs_ioctl_qgroup_create(file, argp);  	case BTRFS_IOC_QGROUP_LIMIT: -		return btrfs_ioctl_qgroup_limit(root, argp); +		return btrfs_ioctl_qgroup_limit(file, argp); +	case BTRFS_IOC_DEV_REPLACE: +		return btrfs_ioctl_dev_replace(root, argp);  	}  	return -ENOTTY;  |