diff options
author | Sage Weil <sage@inktank.com> | 2013-08-15 14:11:45 -0400 |
---|---|---|
committer | Sage Weil <sage@inktank.com> | 2013-08-15 14:11:45 -0400 |
commit | ee3e542fec6e69bc9fb668698889a37d93950ddf (patch) | |
tree | e74ee766a4764769ef1d3d45d266b4dea64101d3 /fs/btrfs/ioctl.c | |
parent | fe2a801b50c0bb8039d627e5ae1fec249d10ff39 (diff) | |
parent | f1d6e17f540af37bb1891480143669ba7636c4cf (diff) |
Merge remote-tracking branch 'linus/master' into testing
Diffstat (limited to 'fs/btrfs/ioctl.c')
-rw-r--r-- | fs/btrfs/ioctl.c | 82 |
1 files changed, 52 insertions, 30 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 0f81d67cdc8d..238a05545ee2 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -555,6 +555,12 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir, | |||
555 | if (!root->ref_cows) | 555 | if (!root->ref_cows) |
556 | return -EINVAL; | 556 | return -EINVAL; |
557 | 557 | ||
558 | ret = btrfs_start_delalloc_inodes(root, 0); | ||
559 | if (ret) | ||
560 | return ret; | ||
561 | |||
562 | btrfs_wait_ordered_extents(root, 0); | ||
563 | |||
558 | pending_snapshot = kzalloc(sizeof(*pending_snapshot), GFP_NOFS); | 564 | pending_snapshot = kzalloc(sizeof(*pending_snapshot), GFP_NOFS); |
559 | if (!pending_snapshot) | 565 | if (!pending_snapshot) |
560 | return -ENOMEM; | 566 | return -ENOMEM; |
@@ -2354,14 +2360,6 @@ static long btrfs_ioctl_rm_dev(struct file *file, void __user *arg) | |||
2354 | if (ret) | 2360 | if (ret) |
2355 | return ret; | 2361 | return ret; |
2356 | 2362 | ||
2357 | if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running, | ||
2358 | 1)) { | ||
2359 | pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n"); | ||
2360 | mnt_drop_write_file(file); | ||
2361 | return -EINVAL; | ||
2362 | } | ||
2363 | |||
2364 | mutex_lock(&root->fs_info->volume_mutex); | ||
2365 | vol_args = memdup_user(arg, sizeof(*vol_args)); | 2363 | vol_args = memdup_user(arg, sizeof(*vol_args)); |
2366 | if (IS_ERR(vol_args)) { | 2364 | if (IS_ERR(vol_args)) { |
2367 | ret = PTR_ERR(vol_args); | 2365 | ret = PTR_ERR(vol_args); |
@@ -2369,12 +2367,20 @@ static long btrfs_ioctl_rm_dev(struct file *file, void __user *arg) | |||
2369 | } | 2367 | } |
2370 | 2368 | ||
2371 | vol_args->name[BTRFS_PATH_NAME_MAX] = '\0'; | 2369 | vol_args->name[BTRFS_PATH_NAME_MAX] = '\0'; |
2372 | ret = btrfs_rm_device(root, vol_args->name); | ||
2373 | 2370 | ||
2374 | kfree(vol_args); | 2371 | if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running, |
2375 | out: | 2372 | 1)) { |
2373 | ret = BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS; | ||
2374 | goto out; | ||
2375 | } | ||
2376 | |||
2377 | mutex_lock(&root->fs_info->volume_mutex); | ||
2378 | ret = btrfs_rm_device(root, vol_args->name); | ||
2376 | mutex_unlock(&root->fs_info->volume_mutex); | 2379 | mutex_unlock(&root->fs_info->volume_mutex); |
2377 | atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0); | 2380 | atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0); |
2381 | |||
2382 | out: | ||
2383 | kfree(vol_args); | ||
2378 | mnt_drop_write_file(file); | 2384 | mnt_drop_write_file(file); |
2379 | return ret; | 2385 | return ret; |
2380 | } | 2386 | } |
@@ -2480,6 +2486,7 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, | |||
2480 | int ret; | 2486 | int ret; |
2481 | u64 len = olen; | 2487 | u64 len = olen; |
2482 | u64 bs = root->fs_info->sb->s_blocksize; | 2488 | u64 bs = root->fs_info->sb->s_blocksize; |
2489 | int same_inode = 0; | ||
2483 | 2490 | ||
2484 | /* | 2491 | /* |
2485 | * TODO: | 2492 | * TODO: |
@@ -2516,7 +2523,7 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, | |||
2516 | 2523 | ||
2517 | ret = -EINVAL; | 2524 | ret = -EINVAL; |
2518 | if (src == inode) | 2525 | if (src == inode) |
2519 | goto out_fput; | 2526 | same_inode = 1; |
2520 | 2527 | ||
2521 | /* the src must be open for reading */ | 2528 | /* the src must be open for reading */ |
2522 | if (!(src_file.file->f_mode & FMODE_READ)) | 2529 | if (!(src_file.file->f_mode & FMODE_READ)) |
@@ -2547,12 +2554,16 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, | |||
2547 | } | 2554 | } |
2548 | path->reada = 2; | 2555 | path->reada = 2; |
2549 | 2556 | ||
2550 | if (inode < src) { | 2557 | if (!same_inode) { |
2551 | mutex_lock_nested(&inode->i_mutex, I_MUTEX_PARENT); | 2558 | if (inode < src) { |
2552 | mutex_lock_nested(&src->i_mutex, I_MUTEX_CHILD); | 2559 | mutex_lock_nested(&inode->i_mutex, I_MUTEX_PARENT); |
2560 | mutex_lock_nested(&src->i_mutex, I_MUTEX_CHILD); | ||
2561 | } else { | ||
2562 | mutex_lock_nested(&src->i_mutex, I_MUTEX_PARENT); | ||
2563 | mutex_lock_nested(&inode->i_mutex, I_MUTEX_CHILD); | ||
2564 | } | ||
2553 | } else { | 2565 | } else { |
2554 | mutex_lock_nested(&src->i_mutex, I_MUTEX_PARENT); | 2566 | mutex_lock(&src->i_mutex); |
2555 | mutex_lock_nested(&inode->i_mutex, I_MUTEX_CHILD); | ||
2556 | } | 2567 | } |
2557 | 2568 | ||
2558 | /* determine range to clone */ | 2569 | /* determine range to clone */ |
@@ -2570,6 +2581,12 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, | |||
2570 | !IS_ALIGNED(destoff, bs)) | 2581 | !IS_ALIGNED(destoff, bs)) |
2571 | goto out_unlock; | 2582 | goto out_unlock; |
2572 | 2583 | ||
2584 | /* verify if ranges are overlapped within the same file */ | ||
2585 | if (same_inode) { | ||
2586 | if (destoff + len > off && destoff < off + len) | ||
2587 | goto out_unlock; | ||
2588 | } | ||
2589 | |||
2573 | if (destoff > inode->i_size) { | 2590 | if (destoff > inode->i_size) { |
2574 | ret = btrfs_cont_expand(inode, inode->i_size, destoff); | 2591 | ret = btrfs_cont_expand(inode, inode->i_size, destoff); |
2575 | if (ret) | 2592 | if (ret) |
@@ -2846,7 +2863,8 @@ out: | |||
2846 | unlock_extent(&BTRFS_I(src)->io_tree, off, off + len - 1); | 2863 | unlock_extent(&BTRFS_I(src)->io_tree, off, off + len - 1); |
2847 | out_unlock: | 2864 | out_unlock: |
2848 | mutex_unlock(&src->i_mutex); | 2865 | mutex_unlock(&src->i_mutex); |
2849 | mutex_unlock(&inode->i_mutex); | 2866 | if (!same_inode) |
2867 | mutex_unlock(&inode->i_mutex); | ||
2850 | vfree(buf); | 2868 | vfree(buf); |
2851 | btrfs_free_path(path); | 2869 | btrfs_free_path(path); |
2852 | out_fput: | 2870 | out_fput: |
@@ -2951,11 +2969,6 @@ static long btrfs_ioctl_default_subvol(struct file *file, void __user *argp) | |||
2951 | goto out; | 2969 | goto out; |
2952 | } | 2970 | } |
2953 | 2971 | ||
2954 | if (btrfs_root_refs(&new_root->root_item) == 0) { | ||
2955 | ret = -ENOENT; | ||
2956 | goto out; | ||
2957 | } | ||
2958 | |||
2959 | path = btrfs_alloc_path(); | 2972 | path = btrfs_alloc_path(); |
2960 | if (!path) { | 2973 | if (!path) { |
2961 | ret = -ENOMEM; | 2974 | ret = -ENOMEM; |
@@ -3719,9 +3732,6 @@ static long btrfs_ioctl_quota_ctl(struct file *file, void __user *arg) | |||
3719 | break; | 3732 | break; |
3720 | } | 3733 | } |
3721 | 3734 | ||
3722 | if (copy_to_user(arg, sa, sizeof(*sa))) | ||
3723 | ret = -EFAULT; | ||
3724 | |||
3725 | err = btrfs_commit_transaction(trans, root->fs_info->tree_root); | 3735 | err = btrfs_commit_transaction(trans, root->fs_info->tree_root); |
3726 | if (err && !ret) | 3736 | if (err && !ret) |
3727 | ret = err; | 3737 | ret = err; |
@@ -3881,7 +3891,7 @@ drop_write: | |||
3881 | 3891 | ||
3882 | static long btrfs_ioctl_quota_rescan(struct file *file, void __user *arg) | 3892 | static long btrfs_ioctl_quota_rescan(struct file *file, void __user *arg) |
3883 | { | 3893 | { |
3884 | struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root; | 3894 | struct btrfs_root *root = BTRFS_I(file_inode(file))->root; |
3885 | struct btrfs_ioctl_quota_rescan_args *qsa; | 3895 | struct btrfs_ioctl_quota_rescan_args *qsa; |
3886 | int ret; | 3896 | int ret; |
3887 | 3897 | ||
@@ -3914,7 +3924,7 @@ drop_write: | |||
3914 | 3924 | ||
3915 | static long btrfs_ioctl_quota_rescan_status(struct file *file, void __user *arg) | 3925 | static long btrfs_ioctl_quota_rescan_status(struct file *file, void __user *arg) |
3916 | { | 3926 | { |
3917 | struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root; | 3927 | struct btrfs_root *root = BTRFS_I(file_inode(file))->root; |
3918 | struct btrfs_ioctl_quota_rescan_args *qsa; | 3928 | struct btrfs_ioctl_quota_rescan_args *qsa; |
3919 | int ret = 0; | 3929 | int ret = 0; |
3920 | 3930 | ||
@@ -3937,6 +3947,16 @@ static long btrfs_ioctl_quota_rescan_status(struct file *file, void __user *arg) | |||
3937 | return ret; | 3947 | return ret; |
3938 | } | 3948 | } |
3939 | 3949 | ||
3950 | static long btrfs_ioctl_quota_rescan_wait(struct file *file, void __user *arg) | ||
3951 | { | ||
3952 | struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root; | ||
3953 | |||
3954 | if (!capable(CAP_SYS_ADMIN)) | ||
3955 | return -EPERM; | ||
3956 | |||
3957 | return btrfs_qgroup_wait_for_completion(root->fs_info); | ||
3958 | } | ||
3959 | |||
3940 | static long btrfs_ioctl_set_received_subvol(struct file *file, | 3960 | static long btrfs_ioctl_set_received_subvol(struct file *file, |
3941 | void __user *arg) | 3961 | void __user *arg) |
3942 | { | 3962 | { |
@@ -4020,7 +4040,7 @@ out: | |||
4020 | 4040 | ||
4021 | static int btrfs_ioctl_get_fslabel(struct file *file, void __user *arg) | 4041 | static int btrfs_ioctl_get_fslabel(struct file *file, void __user *arg) |
4022 | { | 4042 | { |
4023 | struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root; | 4043 | struct btrfs_root *root = BTRFS_I(file_inode(file))->root; |
4024 | const char *label = root->fs_info->super_copy->label; | 4044 | const char *label = root->fs_info->super_copy->label; |
4025 | size_t len = strnlen(label, BTRFS_LABEL_SIZE); | 4045 | size_t len = strnlen(label, BTRFS_LABEL_SIZE); |
4026 | int ret; | 4046 | int ret; |
@@ -4039,7 +4059,7 @@ static int btrfs_ioctl_get_fslabel(struct file *file, void __user *arg) | |||
4039 | 4059 | ||
4040 | static int btrfs_ioctl_set_fslabel(struct file *file, void __user *arg) | 4060 | static int btrfs_ioctl_set_fslabel(struct file *file, void __user *arg) |
4041 | { | 4061 | { |
4042 | struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root; | 4062 | struct btrfs_root *root = BTRFS_I(file_inode(file))->root; |
4043 | struct btrfs_super_block *super_block = root->fs_info->super_copy; | 4063 | struct btrfs_super_block *super_block = root->fs_info->super_copy; |
4044 | struct btrfs_trans_handle *trans; | 4064 | struct btrfs_trans_handle *trans; |
4045 | char label[BTRFS_LABEL_SIZE]; | 4065 | char label[BTRFS_LABEL_SIZE]; |
@@ -4179,6 +4199,8 @@ long btrfs_ioctl(struct file *file, unsigned int | |||
4179 | return btrfs_ioctl_quota_rescan(file, argp); | 4199 | return btrfs_ioctl_quota_rescan(file, argp); |
4180 | case BTRFS_IOC_QUOTA_RESCAN_STATUS: | 4200 | case BTRFS_IOC_QUOTA_RESCAN_STATUS: |
4181 | return btrfs_ioctl_quota_rescan_status(file, argp); | 4201 | return btrfs_ioctl_quota_rescan_status(file, argp); |
4202 | case BTRFS_IOC_QUOTA_RESCAN_WAIT: | ||
4203 | return btrfs_ioctl_quota_rescan_wait(file, argp); | ||
4182 | case BTRFS_IOC_DEV_REPLACE: | 4204 | case BTRFS_IOC_DEV_REPLACE: |
4183 | return btrfs_ioctl_dev_replace(root, argp); | 4205 | return btrfs_ioctl_dev_replace(root, argp); |
4184 | case BTRFS_IOC_GET_FSLABEL: | 4206 | case BTRFS_IOC_GET_FSLABEL: |