diff options
Diffstat (limited to 'fs/btrfs/ioctl.c')
| -rw-r--r-- | fs/btrfs/ioctl.c | 50 |
1 files changed, 43 insertions, 7 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 14f8e1faa46e..24b776c08d99 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
| @@ -261,6 +261,7 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg) | |||
| 261 | } | 261 | } |
| 262 | 262 | ||
| 263 | btrfs_update_iflags(inode); | 263 | btrfs_update_iflags(inode); |
| 264 | inode_inc_iversion(inode); | ||
| 264 | inode->i_ctime = CURRENT_TIME; | 265 | inode->i_ctime = CURRENT_TIME; |
| 265 | ret = btrfs_update_inode(trans, root, inode); | 266 | ret = btrfs_update_inode(trans, root, inode); |
| 266 | 267 | ||
| @@ -367,7 +368,7 @@ static noinline int create_subvol(struct btrfs_root *root, | |||
| 367 | return PTR_ERR(trans); | 368 | return PTR_ERR(trans); |
| 368 | 369 | ||
| 369 | leaf = btrfs_alloc_free_block(trans, root, root->leafsize, | 370 | leaf = btrfs_alloc_free_block(trans, root, root->leafsize, |
| 370 | 0, objectid, NULL, 0, 0, 0, 0); | 371 | 0, objectid, NULL, 0, 0, 0); |
| 371 | if (IS_ERR(leaf)) { | 372 | if (IS_ERR(leaf)) { |
| 372 | ret = PTR_ERR(leaf); | 373 | ret = PTR_ERR(leaf); |
| 373 | goto fail; | 374 | goto fail; |
| @@ -2262,10 +2263,12 @@ static long btrfs_ioctl_dev_info(struct btrfs_root *root, void __user *arg) | |||
| 2262 | di_args->bytes_used = dev->bytes_used; | 2263 | di_args->bytes_used = dev->bytes_used; |
| 2263 | di_args->total_bytes = dev->total_bytes; | 2264 | di_args->total_bytes = dev->total_bytes; |
| 2264 | memcpy(di_args->uuid, dev->uuid, sizeof(di_args->uuid)); | 2265 | memcpy(di_args->uuid, dev->uuid, sizeof(di_args->uuid)); |
| 2265 | if (dev->name) | 2266 | if (dev->name) { |
| 2266 | strncpy(di_args->path, dev->name, sizeof(di_args->path)); | 2267 | strncpy(di_args->path, dev->name, sizeof(di_args->path)); |
| 2267 | else | 2268 | di_args->path[sizeof(di_args->path) - 1] = 0; |
| 2269 | } else { | ||
| 2268 | di_args->path[0] = '\0'; | 2270 | di_args->path[0] = '\0'; |
| 2271 | } | ||
| 2269 | 2272 | ||
| 2270 | out: | 2273 | out: |
| 2271 | if (ret == 0 && copy_to_user(arg, di_args, sizeof(*di_args))) | 2274 | if (ret == 0 && copy_to_user(arg, di_args, sizeof(*di_args))) |
| @@ -2622,6 +2625,7 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, | |||
| 2622 | btrfs_mark_buffer_dirty(leaf); | 2625 | btrfs_mark_buffer_dirty(leaf); |
| 2623 | btrfs_release_path(path); | 2626 | btrfs_release_path(path); |
| 2624 | 2627 | ||
| 2628 | inode_inc_iversion(inode); | ||
| 2625 | inode->i_mtime = inode->i_ctime = CURRENT_TIME; | 2629 | inode->i_mtime = inode->i_ctime = CURRENT_TIME; |
| 2626 | 2630 | ||
| 2627 | /* | 2631 | /* |
| @@ -2914,7 +2918,7 @@ long btrfs_ioctl_space_info(struct btrfs_root *root, void __user *arg) | |||
| 2914 | up_read(&info->groups_sem); | 2918 | up_read(&info->groups_sem); |
| 2915 | } | 2919 | } |
| 2916 | 2920 | ||
| 2917 | user_dest = (struct btrfs_ioctl_space_info *) | 2921 | user_dest = (struct btrfs_ioctl_space_info __user *) |
| 2918 | (arg + sizeof(struct btrfs_ioctl_space_args)); | 2922 | (arg + sizeof(struct btrfs_ioctl_space_args)); |
| 2919 | 2923 | ||
| 2920 | if (copy_to_user(user_dest, dest_orig, alloc_size)) | 2924 | if (copy_to_user(user_dest, dest_orig, alloc_size)) |
| @@ -3042,6 +3046,28 @@ static long btrfs_ioctl_scrub_progress(struct btrfs_root *root, | |||
| 3042 | return ret; | 3046 | return ret; |
| 3043 | } | 3047 | } |
| 3044 | 3048 | ||
| 3049 | static long btrfs_ioctl_get_dev_stats(struct btrfs_root *root, | ||
| 3050 | void __user *arg, int reset_after_read) | ||
| 3051 | { | ||
| 3052 | struct btrfs_ioctl_get_dev_stats *sa; | ||
| 3053 | int ret; | ||
| 3054 | |||
| 3055 | if (reset_after_read && !capable(CAP_SYS_ADMIN)) | ||
| 3056 | return -EPERM; | ||
| 3057 | |||
| 3058 | sa = memdup_user(arg, sizeof(*sa)); | ||
| 3059 | if (IS_ERR(sa)) | ||
| 3060 | return PTR_ERR(sa); | ||
| 3061 | |||
| 3062 | ret = btrfs_get_dev_stats(root, sa, reset_after_read); | ||
| 3063 | |||
| 3064 | if (copy_to_user(arg, sa, sizeof(*sa))) | ||
| 3065 | ret = -EFAULT; | ||
| 3066 | |||
| 3067 | kfree(sa); | ||
| 3068 | return ret; | ||
| 3069 | } | ||
| 3070 | |||
| 3045 | static long btrfs_ioctl_ino_to_path(struct btrfs_root *root, void __user *arg) | 3071 | static long btrfs_ioctl_ino_to_path(struct btrfs_root *root, void __user *arg) |
| 3046 | { | 3072 | { |
| 3047 | int ret = 0; | 3073 | int ret = 0; |
| @@ -3212,8 +3238,9 @@ void update_ioctl_balance_args(struct btrfs_fs_info *fs_info, int lock, | |||
| 3212 | } | 3238 | } |
| 3213 | } | 3239 | } |
| 3214 | 3240 | ||
| 3215 | static long btrfs_ioctl_balance(struct btrfs_root *root, void __user *arg) | 3241 | static long btrfs_ioctl_balance(struct file *file, void __user *arg) |
| 3216 | { | 3242 | { |
| 3243 | struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root; | ||
| 3217 | struct btrfs_fs_info *fs_info = root->fs_info; | 3244 | struct btrfs_fs_info *fs_info = root->fs_info; |
| 3218 | struct btrfs_ioctl_balance_args *bargs; | 3245 | struct btrfs_ioctl_balance_args *bargs; |
| 3219 | struct btrfs_balance_control *bctl; | 3246 | struct btrfs_balance_control *bctl; |
| @@ -3225,6 +3252,10 @@ static long btrfs_ioctl_balance(struct btrfs_root *root, void __user *arg) | |||
| 3225 | if (fs_info->sb->s_flags & MS_RDONLY) | 3252 | if (fs_info->sb->s_flags & MS_RDONLY) |
| 3226 | return -EROFS; | 3253 | return -EROFS; |
| 3227 | 3254 | ||
| 3255 | ret = mnt_want_write(file->f_path.mnt); | ||
| 3256 | if (ret) | ||
| 3257 | return ret; | ||
| 3258 | |||
| 3228 | mutex_lock(&fs_info->volume_mutex); | 3259 | mutex_lock(&fs_info->volume_mutex); |
| 3229 | mutex_lock(&fs_info->balance_mutex); | 3260 | mutex_lock(&fs_info->balance_mutex); |
| 3230 | 3261 | ||
| @@ -3291,6 +3322,7 @@ out_bargs: | |||
| 3291 | out: | 3322 | out: |
| 3292 | mutex_unlock(&fs_info->balance_mutex); | 3323 | mutex_unlock(&fs_info->balance_mutex); |
| 3293 | mutex_unlock(&fs_info->volume_mutex); | 3324 | mutex_unlock(&fs_info->volume_mutex); |
| 3325 | mnt_drop_write(file->f_path.mnt); | ||
| 3294 | return ret; | 3326 | return ret; |
| 3295 | } | 3327 | } |
| 3296 | 3328 | ||
| @@ -3386,7 +3418,7 @@ long btrfs_ioctl(struct file *file, unsigned int | |||
| 3386 | case BTRFS_IOC_DEV_INFO: | 3418 | case BTRFS_IOC_DEV_INFO: |
| 3387 | return btrfs_ioctl_dev_info(root, argp); | 3419 | return btrfs_ioctl_dev_info(root, argp); |
| 3388 | case BTRFS_IOC_BALANCE: | 3420 | case BTRFS_IOC_BALANCE: |
| 3389 | return btrfs_ioctl_balance(root, NULL); | 3421 | return btrfs_ioctl_balance(file, NULL); |
| 3390 | case BTRFS_IOC_CLONE: | 3422 | case BTRFS_IOC_CLONE: |
| 3391 | return btrfs_ioctl_clone(file, arg, 0, 0, 0); | 3423 | return btrfs_ioctl_clone(file, arg, 0, 0, 0); |
| 3392 | case BTRFS_IOC_CLONE_RANGE: | 3424 | case BTRFS_IOC_CLONE_RANGE: |
| @@ -3419,11 +3451,15 @@ long btrfs_ioctl(struct file *file, unsigned int | |||
| 3419 | case BTRFS_IOC_SCRUB_PROGRESS: | 3451 | case BTRFS_IOC_SCRUB_PROGRESS: |
| 3420 | return btrfs_ioctl_scrub_progress(root, argp); | 3452 | return btrfs_ioctl_scrub_progress(root, argp); |
| 3421 | case BTRFS_IOC_BALANCE_V2: | 3453 | case BTRFS_IOC_BALANCE_V2: |
| 3422 | return btrfs_ioctl_balance(root, argp); | 3454 | return btrfs_ioctl_balance(file, argp); |
| 3423 | case BTRFS_IOC_BALANCE_CTL: | 3455 | case BTRFS_IOC_BALANCE_CTL: |
| 3424 | return btrfs_ioctl_balance_ctl(root, arg); | 3456 | return btrfs_ioctl_balance_ctl(root, arg); |
| 3425 | case BTRFS_IOC_BALANCE_PROGRESS: | 3457 | case BTRFS_IOC_BALANCE_PROGRESS: |
| 3426 | return btrfs_ioctl_balance_progress(root, argp); | 3458 | return btrfs_ioctl_balance_progress(root, argp); |
| 3459 | case BTRFS_IOC_GET_DEV_STATS: | ||
| 3460 | return btrfs_ioctl_get_dev_stats(root, argp, 0); | ||
| 3461 | case BTRFS_IOC_GET_AND_RESET_DEV_STATS: | ||
| 3462 | return btrfs_ioctl_get_dev_stats(root, argp, 1); | ||
| 3427 | } | 3463 | } |
| 3428 | 3464 | ||
| 3429 | return -ENOTTY; | 3465 | return -ENOTTY; |
