aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ioctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/ioctl.c')
-rw-r--r--fs/btrfs/ioctl.c44
1 files changed, 27 insertions, 17 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 7cc2e8e075b4..f87552a1d7ea 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -947,31 +947,41 @@ out:
947 947
948static noinline int btrfs_ioctl_snap_create(struct file *file, 948static noinline int btrfs_ioctl_snap_create(struct file *file,
949 void __user *arg, int subvol, 949 void __user *arg, int subvol,
950 int async) 950 int v2)
951{ 951{
952 struct btrfs_ioctl_vol_args *vol_args = NULL; 952 struct btrfs_ioctl_vol_args *vol_args = NULL;
953 struct btrfs_ioctl_async_vol_args *async_vol_args = NULL; 953 struct btrfs_ioctl_vol_args_v2 *vol_args_v2 = NULL;
954 char *name; 954 char *name;
955 u64 fd; 955 u64 fd;
956 u64 transid = 0;
957 int ret; 956 int ret;
958 957
959 if (async) { 958 if (v2) {
960 async_vol_args = memdup_user(arg, sizeof(*async_vol_args)); 959 u64 transid = 0;
961 if (IS_ERR(async_vol_args)) 960 u64 *ptr = NULL;
962 return PTR_ERR(async_vol_args);
963 961
964 name = async_vol_args->name; 962 vol_args_v2 = memdup_user(arg, sizeof(*vol_args_v2));
965 fd = async_vol_args->fd; 963 if (IS_ERR(vol_args_v2))
966 async_vol_args->name[BTRFS_SNAPSHOT_NAME_MAX] = '\0'; 964 return PTR_ERR(vol_args_v2);
965
966 if (vol_args_v2->flags & ~BTRFS_SUBVOL_CREATE_ASYNC) {
967 ret = -EINVAL;
968 goto out;
969 }
970
971 name = vol_args_v2->name;
972 fd = vol_args_v2->fd;
973 vol_args_v2->name[BTRFS_SUBVOL_NAME_MAX] = '\0';
974
975 if (vol_args_v2->flags & BTRFS_SUBVOL_CREATE_ASYNC)
976 ptr = &transid;
967 977
968 ret = btrfs_ioctl_snap_create_transid(file, name, fd, 978 ret = btrfs_ioctl_snap_create_transid(file, name, fd,
969 subvol, &transid); 979 subvol, ptr);
970 980
971 if (ret == 0 && 981 if (ret == 0 && ptr &&
972 copy_to_user(arg + 982 copy_to_user(arg +
973 offsetof(struct btrfs_ioctl_async_vol_args, 983 offsetof(struct btrfs_ioctl_vol_args_v2,
974 transid), &transid, sizeof(transid))) 984 transid), ptr, sizeof(*ptr)))
975 ret = -EFAULT; 985 ret = -EFAULT;
976 } else { 986 } else {
977 vol_args = memdup_user(arg, sizeof(*vol_args)); 987 vol_args = memdup_user(arg, sizeof(*vol_args));
@@ -984,9 +994,9 @@ static noinline int btrfs_ioctl_snap_create(struct file *file,
984 ret = btrfs_ioctl_snap_create_transid(file, name, fd, 994 ret = btrfs_ioctl_snap_create_transid(file, name, fd,
985 subvol, NULL); 995 subvol, NULL);
986 } 996 }
987 997out:
988 kfree(vol_args); 998 kfree(vol_args);
989 kfree(async_vol_args); 999 kfree(vol_args_v2);
990 1000
991 return ret; 1001 return ret;
992} 1002}
@@ -2248,7 +2258,7 @@ long btrfs_ioctl(struct file *file, unsigned int
2248 return btrfs_ioctl_getversion(file, argp); 2258 return btrfs_ioctl_getversion(file, argp);
2249 case BTRFS_IOC_SNAP_CREATE: 2259 case BTRFS_IOC_SNAP_CREATE:
2250 return btrfs_ioctl_snap_create(file, argp, 0, 0); 2260 return btrfs_ioctl_snap_create(file, argp, 0, 0);
2251 case BTRFS_IOC_SNAP_CREATE_ASYNC: 2261 case BTRFS_IOC_SNAP_CREATE_V2:
2252 return btrfs_ioctl_snap_create(file, argp, 0, 1); 2262 return btrfs_ioctl_snap_create(file, argp, 0, 1);
2253 case BTRFS_IOC_SUBVOL_CREATE: 2263 case BTRFS_IOC_SUBVOL_CREATE:
2254 return btrfs_ioctl_snap_create(file, argp, 1, 0); 2264 return btrfs_ioctl_snap_create(file, argp, 1, 0);