diff options
Diffstat (limited to 'fs/btrfs/ioctl.c')
-rw-r--r-- | fs/btrfs/ioctl.c | 44 |
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 | ||
948 | static noinline int btrfs_ioctl_snap_create(struct file *file, | 948 | static 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 | 997 | out: | |
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); |