diff options
Diffstat (limited to 'fs/btrfs/ioctl.c')
| -rw-r--r-- | fs/btrfs/ioctl.c | 56 |
1 files changed, 34 insertions, 22 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index f1c9bb4079ed..f87552a1d7ea 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
| @@ -947,23 +947,42 @@ 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; | ||
| 977 | |||
| 978 | ret = btrfs_ioctl_snap_create_transid(file, name, fd, | ||
| 979 | subvol, ptr); | ||
| 980 | |||
| 981 | if (ret == 0 && ptr && | ||
| 982 | copy_to_user(arg + | ||
| 983 | offsetof(struct btrfs_ioctl_vol_args_v2, | ||
| 984 | transid), ptr, sizeof(*ptr))) | ||
| 985 | ret = -EFAULT; | ||
| 967 | } else { | 986 | } else { |
| 968 | vol_args = memdup_user(arg, sizeof(*vol_args)); | 987 | vol_args = memdup_user(arg, sizeof(*vol_args)); |
| 969 | if (IS_ERR(vol_args)) | 988 | if (IS_ERR(vol_args)) |
| @@ -971,20 +990,13 @@ static noinline int btrfs_ioctl_snap_create(struct file *file, | |||
| 971 | name = vol_args->name; | 990 | name = vol_args->name; |
| 972 | fd = vol_args->fd; | 991 | fd = vol_args->fd; |
| 973 | vol_args->name[BTRFS_PATH_NAME_MAX] = '\0'; | 992 | vol_args->name[BTRFS_PATH_NAME_MAX] = '\0'; |
| 974 | } | ||
| 975 | |||
| 976 | ret = btrfs_ioctl_snap_create_transid(file, name, fd, | ||
| 977 | subvol, &transid); | ||
| 978 | 993 | ||
| 979 | if (!ret && async) { | 994 | ret = btrfs_ioctl_snap_create_transid(file, name, fd, |
| 980 | if (copy_to_user(arg + | 995 | subvol, NULL); |
| 981 | offsetof(struct btrfs_ioctl_async_vol_args, | ||
| 982 | transid), &transid, sizeof(transid))) | ||
| 983 | return -EFAULT; | ||
| 984 | } | 996 | } |
| 985 | 997 | out: | |
| 986 | kfree(vol_args); | 998 | kfree(vol_args); |
| 987 | kfree(async_vol_args); | 999 | kfree(vol_args_v2); |
| 988 | 1000 | ||
| 989 | return ret; | 1001 | return ret; |
| 990 | } | 1002 | } |
| @@ -2246,7 +2258,7 @@ long btrfs_ioctl(struct file *file, unsigned int | |||
| 2246 | return btrfs_ioctl_getversion(file, argp); | 2258 | return btrfs_ioctl_getversion(file, argp); |
| 2247 | case BTRFS_IOC_SNAP_CREATE: | 2259 | case BTRFS_IOC_SNAP_CREATE: |
| 2248 | return btrfs_ioctl_snap_create(file, argp, 0, 0); | 2260 | return btrfs_ioctl_snap_create(file, argp, 0, 0); |
| 2249 | case BTRFS_IOC_SNAP_CREATE_ASYNC: | 2261 | case BTRFS_IOC_SNAP_CREATE_V2: |
| 2250 | return btrfs_ioctl_snap_create(file, argp, 0, 1); | 2262 | return btrfs_ioctl_snap_create(file, argp, 0, 1); |
| 2251 | case BTRFS_IOC_SUBVOL_CREATE: | 2263 | case BTRFS_IOC_SUBVOL_CREATE: |
| 2252 | return btrfs_ioctl_snap_create(file, argp, 1, 0); | 2264 | return btrfs_ioctl_snap_create(file, argp, 1, 0); |
