aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r--fs/btrfs/inode.c60
1 files changed, 42 insertions, 18 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 6a7d9160df27..1e725a48467c 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -2302,40 +2302,64 @@ out_unlock:
2302 2302
2303static int btrfs_ioctl_snap_create(struct btrfs_root *root, void __user *arg) 2303static int btrfs_ioctl_snap_create(struct btrfs_root *root, void __user *arg)
2304{ 2304{
2305 struct btrfs_ioctl_vol_args vol_args; 2305 struct btrfs_ioctl_vol_args *vol_args;
2306 struct btrfs_dir_item *di; 2306 struct btrfs_dir_item *di;
2307 struct btrfs_path *path; 2307 struct btrfs_path *path;
2308 int namelen;
2309 u64 root_dirid; 2308 u64 root_dirid;
2309 int namelen;
2310 int ret;
2310 2311
2311 if (copy_from_user(&vol_args, arg, sizeof(vol_args))) 2312 vol_args = kmalloc(sizeof(*vol_args), GFP_NOFS);
2312 return -EFAULT;
2313 2313
2314 namelen = strlen(vol_args.name); 2314 if (!vol_args)
2315 if (namelen > BTRFS_VOL_NAME_MAX) 2315 return -ENOMEM;
2316 return -EINVAL; 2316
2317 if (strchr(vol_args.name, '/')) 2317 if (copy_from_user(vol_args, arg, sizeof(*vol_args))) {
2318 return -EINVAL; 2318 ret = -EFAULT;
2319 goto out;
2320 }
2321
2322 namelen = strlen(vol_args->name);
2323 if (namelen > BTRFS_VOL_NAME_MAX) {
2324 ret = -EINVAL;
2325 goto out;
2326 }
2327 if (strchr(vol_args->name, '/')) {
2328 ret = -EINVAL;
2329 goto out;
2330 }
2319 2331
2320 path = btrfs_alloc_path(); 2332 path = btrfs_alloc_path();
2321 if (!path) 2333 if (!path) {
2322 return -ENOMEM; 2334 ret = -ENOMEM;
2335 goto out;
2336 }
2323 2337
2324 root_dirid = root->fs_info->sb->s_root->d_inode->i_ino, 2338 root_dirid = root->fs_info->sb->s_root->d_inode->i_ino,
2325 mutex_lock(&root->fs_info->fs_mutex); 2339 mutex_lock(&root->fs_info->fs_mutex);
2326 di = btrfs_lookup_dir_item(NULL, root->fs_info->tree_root, 2340 di = btrfs_lookup_dir_item(NULL, root->fs_info->tree_root,
2327 path, root_dirid, 2341 path, root_dirid,
2328 vol_args.name, namelen, 0); 2342 vol_args->name, namelen, 0);
2329 mutex_unlock(&root->fs_info->fs_mutex); 2343 mutex_unlock(&root->fs_info->fs_mutex);
2330 btrfs_free_path(path); 2344 btrfs_free_path(path);
2331 if (di && !IS_ERR(di)) 2345
2332 return -EEXIST; 2346 if (di && !IS_ERR(di)) {
2333 if (IS_ERR(di)) 2347 ret = -EEXIST;
2334 return PTR_ERR(di); 2348 goto out;
2349 }
2350
2351 if (IS_ERR(di)) {
2352 ret = PTR_ERR(di);
2353 goto out;
2354 }
2335 2355
2336 if (root == root->fs_info->tree_root) 2356 if (root == root->fs_info->tree_root)
2337 return create_subvol(root, vol_args.name, namelen); 2357 ret = create_subvol(root, vol_args->name, namelen);
2338 return create_snapshot(root, vol_args.name, namelen); 2358 else
2359 ret = create_snapshot(root, vol_args->name, namelen);
2360out:
2361 kfree(vol_args);
2362 return ret;
2339} 2363}
2340 2364
2341static int btrfs_ioctl_defrag(struct file *file) 2365static int btrfs_ioctl_defrag(struct file *file)