diff options
Diffstat (limited to 'fs/btrfs/ioctl.c')
-rw-r--r-- | fs/btrfs/ioctl.c | 100 |
1 files changed, 56 insertions, 44 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 47127c1bd290..e568c472f807 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -181,6 +181,7 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg) | |||
181 | int ret; | 181 | int ret; |
182 | u64 ip_oldflags; | 182 | u64 ip_oldflags; |
183 | unsigned int i_oldflags; | 183 | unsigned int i_oldflags; |
184 | umode_t mode; | ||
184 | 185 | ||
185 | if (btrfs_root_readonly(root)) | 186 | if (btrfs_root_readonly(root)) |
186 | return -EROFS; | 187 | return -EROFS; |
@@ -203,6 +204,7 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg) | |||
203 | 204 | ||
204 | ip_oldflags = ip->flags; | 205 | ip_oldflags = ip->flags; |
205 | i_oldflags = inode->i_flags; | 206 | i_oldflags = inode->i_flags; |
207 | mode = inode->i_mode; | ||
206 | 208 | ||
207 | flags = btrfs_mask_flags(inode->i_mode, flags); | 209 | flags = btrfs_mask_flags(inode->i_mode, flags); |
208 | oldflags = btrfs_flags_to_ioctl(ip->flags); | 210 | oldflags = btrfs_flags_to_ioctl(ip->flags); |
@@ -237,10 +239,31 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg) | |||
237 | ip->flags |= BTRFS_INODE_DIRSYNC; | 239 | ip->flags |= BTRFS_INODE_DIRSYNC; |
238 | else | 240 | else |
239 | ip->flags &= ~BTRFS_INODE_DIRSYNC; | 241 | ip->flags &= ~BTRFS_INODE_DIRSYNC; |
240 | if (flags & FS_NOCOW_FL) | 242 | if (flags & FS_NOCOW_FL) { |
241 | ip->flags |= BTRFS_INODE_NODATACOW; | 243 | if (S_ISREG(mode)) { |
242 | else | 244 | /* |
243 | ip->flags &= ~BTRFS_INODE_NODATACOW; | 245 | * It's safe to turn csums off here, no extents exist. |
246 | * Otherwise we want the flag to reflect the real COW | ||
247 | * status of the file and will not set it. | ||
248 | */ | ||
249 | if (inode->i_size == 0) | ||
250 | ip->flags |= BTRFS_INODE_NODATACOW | ||
251 | | BTRFS_INODE_NODATASUM; | ||
252 | } else { | ||
253 | ip->flags |= BTRFS_INODE_NODATACOW; | ||
254 | } | ||
255 | } else { | ||
256 | /* | ||
257 | * Revert back under same assuptions as above | ||
258 | */ | ||
259 | if (S_ISREG(mode)) { | ||
260 | if (inode->i_size == 0) | ||
261 | ip->flags &= ~(BTRFS_INODE_NODATACOW | ||
262 | | BTRFS_INODE_NODATASUM); | ||
263 | } else { | ||
264 | ip->flags &= ~BTRFS_INODE_NODATACOW; | ||
265 | } | ||
266 | } | ||
244 | 267 | ||
245 | /* | 268 | /* |
246 | * The COMPRESS flag can only be changed by users, while the NOCOMPRESS | 269 | * The COMPRESS flag can only be changed by users, while the NOCOMPRESS |
@@ -516,7 +539,8 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry, | |||
516 | if (!pending_snapshot) | 539 | if (!pending_snapshot) |
517 | return -ENOMEM; | 540 | return -ENOMEM; |
518 | 541 | ||
519 | btrfs_init_block_rsv(&pending_snapshot->block_rsv); | 542 | btrfs_init_block_rsv(&pending_snapshot->block_rsv, |
543 | BTRFS_BLOCK_RSV_TEMP); | ||
520 | pending_snapshot->dentry = dentry; | 544 | pending_snapshot->dentry = dentry; |
521 | pending_snapshot->root = root; | 545 | pending_snapshot->root = root; |
522 | pending_snapshot->readonly = readonly; | 546 | pending_snapshot->readonly = readonly; |
@@ -525,7 +549,7 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry, | |||
525 | *inherit = NULL; /* take responsibility to free it */ | 549 | *inherit = NULL; /* take responsibility to free it */ |
526 | } | 550 | } |
527 | 551 | ||
528 | trans = btrfs_start_transaction(root->fs_info->extent_root, 5); | 552 | trans = btrfs_start_transaction(root->fs_info->extent_root, 6); |
529 | if (IS_ERR(trans)) { | 553 | if (IS_ERR(trans)) { |
530 | ret = PTR_ERR(trans); | 554 | ret = PTR_ERR(trans); |
531 | goto fail; | 555 | goto fail; |
@@ -1022,8 +1046,8 @@ again: | |||
1022 | page_start, page_end - 1, 0, &cached_state); | 1046 | page_start, page_end - 1, 0, &cached_state); |
1023 | clear_extent_bit(&BTRFS_I(inode)->io_tree, page_start, | 1047 | clear_extent_bit(&BTRFS_I(inode)->io_tree, page_start, |
1024 | page_end - 1, EXTENT_DIRTY | EXTENT_DELALLOC | | 1048 | page_end - 1, EXTENT_DIRTY | EXTENT_DELALLOC | |
1025 | EXTENT_DO_ACCOUNTING, 0, 0, &cached_state, | 1049 | EXTENT_DO_ACCOUNTING | EXTENT_DEFRAG, 0, 0, |
1026 | GFP_NOFS); | 1050 | &cached_state, GFP_NOFS); |
1027 | 1051 | ||
1028 | if (i_done != page_cnt) { | 1052 | if (i_done != page_cnt) { |
1029 | spin_lock(&BTRFS_I(inode)->lock); | 1053 | spin_lock(&BTRFS_I(inode)->lock); |
@@ -1034,8 +1058,8 @@ again: | |||
1034 | } | 1058 | } |
1035 | 1059 | ||
1036 | 1060 | ||
1037 | btrfs_set_extent_delalloc(inode, page_start, page_end - 1, | 1061 | set_extent_defrag(&BTRFS_I(inode)->io_tree, page_start, page_end - 1, |
1038 | &cached_state); | 1062 | &cached_state, GFP_NOFS); |
1039 | 1063 | ||
1040 | unlock_extent_cached(&BTRFS_I(inode)->io_tree, | 1064 | unlock_extent_cached(&BTRFS_I(inode)->io_tree, |
1041 | page_start, page_end - 1, &cached_state, | 1065 | page_start, page_end - 1, &cached_state, |
@@ -2351,7 +2375,6 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, | |||
2351 | int ret; | 2375 | int ret; |
2352 | u64 len = olen; | 2376 | u64 len = olen; |
2353 | u64 bs = root->fs_info->sb->s_blocksize; | 2377 | u64 bs = root->fs_info->sb->s_blocksize; |
2354 | u64 hint_byte; | ||
2355 | 2378 | ||
2356 | /* | 2379 | /* |
2357 | * TODO: | 2380 | * TODO: |
@@ -2456,13 +2479,13 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, | |||
2456 | another, and lock file content */ | 2479 | another, and lock file content */ |
2457 | while (1) { | 2480 | while (1) { |
2458 | struct btrfs_ordered_extent *ordered; | 2481 | struct btrfs_ordered_extent *ordered; |
2459 | lock_extent(&BTRFS_I(src)->io_tree, off, off+len); | 2482 | lock_extent(&BTRFS_I(src)->io_tree, off, off + len - 1); |
2460 | ordered = btrfs_lookup_first_ordered_extent(src, off+len); | 2483 | ordered = btrfs_lookup_first_ordered_extent(src, off + len - 1); |
2461 | if (!ordered && | 2484 | if (!ordered && |
2462 | !test_range_bit(&BTRFS_I(src)->io_tree, off, off+len, | 2485 | !test_range_bit(&BTRFS_I(src)->io_tree, off, off + len - 1, |
2463 | EXTENT_DELALLOC, 0, NULL)) | 2486 | EXTENT_DELALLOC, 0, NULL)) |
2464 | break; | 2487 | break; |
2465 | unlock_extent(&BTRFS_I(src)->io_tree, off, off+len); | 2488 | unlock_extent(&BTRFS_I(src)->io_tree, off, off + len - 1); |
2466 | if (ordered) | 2489 | if (ordered) |
2467 | btrfs_put_ordered_extent(ordered); | 2490 | btrfs_put_ordered_extent(ordered); |
2468 | btrfs_wait_ordered_range(src, off, len); | 2491 | btrfs_wait_ordered_range(src, off, len); |
@@ -2536,7 +2559,7 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, | |||
2536 | btrfs_release_path(path); | 2559 | btrfs_release_path(path); |
2537 | 2560 | ||
2538 | if (key.offset + datal <= off || | 2561 | if (key.offset + datal <= off || |
2539 | key.offset >= off+len) | 2562 | key.offset >= off + len - 1) |
2540 | goto next; | 2563 | goto next; |
2541 | 2564 | ||
2542 | memcpy(&new_key, &key, sizeof(new_key)); | 2565 | memcpy(&new_key, &key, sizeof(new_key)); |
@@ -2574,10 +2597,10 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, | |||
2574 | datal -= off - key.offset; | 2597 | datal -= off - key.offset; |
2575 | } | 2598 | } |
2576 | 2599 | ||
2577 | ret = btrfs_drop_extents(trans, inode, | 2600 | ret = btrfs_drop_extents(trans, root, inode, |
2578 | new_key.offset, | 2601 | new_key.offset, |
2579 | new_key.offset + datal, | 2602 | new_key.offset + datal, |
2580 | &hint_byte, 1); | 2603 | 1); |
2581 | if (ret) { | 2604 | if (ret) { |
2582 | btrfs_abort_transaction(trans, root, | 2605 | btrfs_abort_transaction(trans, root, |
2583 | ret); | 2606 | ret); |
@@ -2637,8 +2660,8 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, | |||
2637 | new_key.offset += skip; | 2660 | new_key.offset += skip; |
2638 | } | 2661 | } |
2639 | 2662 | ||
2640 | if (key.offset + datal > off+len) | 2663 | if (key.offset + datal > off + len) |
2641 | trim = key.offset + datal - (off+len); | 2664 | trim = key.offset + datal - (off + len); |
2642 | 2665 | ||
2643 | if (comp && (skip || trim)) { | 2666 | if (comp && (skip || trim)) { |
2644 | ret = -EINVAL; | 2667 | ret = -EINVAL; |
@@ -2648,10 +2671,10 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, | |||
2648 | size -= skip + trim; | 2671 | size -= skip + trim; |
2649 | datal -= skip + trim; | 2672 | datal -= skip + trim; |
2650 | 2673 | ||
2651 | ret = btrfs_drop_extents(trans, inode, | 2674 | ret = btrfs_drop_extents(trans, root, inode, |
2652 | new_key.offset, | 2675 | new_key.offset, |
2653 | new_key.offset + datal, | 2676 | new_key.offset + datal, |
2654 | &hint_byte, 1); | 2677 | 1); |
2655 | if (ret) { | 2678 | if (ret) { |
2656 | btrfs_abort_transaction(trans, root, | 2679 | btrfs_abort_transaction(trans, root, |
2657 | ret); | 2680 | ret); |
@@ -2715,7 +2738,7 @@ next: | |||
2715 | ret = 0; | 2738 | ret = 0; |
2716 | out: | 2739 | out: |
2717 | btrfs_release_path(path); | 2740 | btrfs_release_path(path); |
2718 | unlock_extent(&BTRFS_I(src)->io_tree, off, off+len); | 2741 | unlock_extent(&BTRFS_I(src)->io_tree, off, off + len - 1); |
2719 | out_unlock: | 2742 | out_unlock: |
2720 | mutex_unlock(&src->i_mutex); | 2743 | mutex_unlock(&src->i_mutex); |
2721 | mutex_unlock(&inode->i_mutex); | 2744 | mutex_unlock(&inode->i_mutex); |
@@ -2850,8 +2873,8 @@ static long btrfs_ioctl_default_subvol(struct file *file, void __user *argp) | |||
2850 | return 0; | 2873 | return 0; |
2851 | } | 2874 | } |
2852 | 2875 | ||
2853 | static void get_block_group_info(struct list_head *groups_list, | 2876 | void btrfs_get_block_group_info(struct list_head *groups_list, |
2854 | struct btrfs_ioctl_space_info *space) | 2877 | struct btrfs_ioctl_space_info *space) |
2855 | { | 2878 | { |
2856 | struct btrfs_block_group_cache *block_group; | 2879 | struct btrfs_block_group_cache *block_group; |
2857 | 2880 | ||
@@ -2959,8 +2982,8 @@ long btrfs_ioctl_space_info(struct btrfs_root *root, void __user *arg) | |||
2959 | down_read(&info->groups_sem); | 2982 | down_read(&info->groups_sem); |
2960 | for (c = 0; c < BTRFS_NR_RAID_TYPES; c++) { | 2983 | for (c = 0; c < BTRFS_NR_RAID_TYPES; c++) { |
2961 | if (!list_empty(&info->block_groups[c])) { | 2984 | if (!list_empty(&info->block_groups[c])) { |
2962 | get_block_group_info(&info->block_groups[c], | 2985 | btrfs_get_block_group_info( |
2963 | &space); | 2986 | &info->block_groups[c], &space); |
2964 | memcpy(dest, &space, sizeof(space)); | 2987 | memcpy(dest, &space, sizeof(space)); |
2965 | dest++; | 2988 | dest++; |
2966 | space_args.total_spaces++; | 2989 | space_args.total_spaces++; |
@@ -3208,11 +3231,9 @@ static long btrfs_ioctl_logical_to_ino(struct btrfs_root *root, | |||
3208 | { | 3231 | { |
3209 | int ret = 0; | 3232 | int ret = 0; |
3210 | int size; | 3233 | int size; |
3211 | u64 extent_item_pos; | ||
3212 | struct btrfs_ioctl_logical_ino_args *loi; | 3234 | struct btrfs_ioctl_logical_ino_args *loi; |
3213 | struct btrfs_data_container *inodes = NULL; | 3235 | struct btrfs_data_container *inodes = NULL; |
3214 | struct btrfs_path *path = NULL; | 3236 | struct btrfs_path *path = NULL; |
3215 | struct btrfs_key key; | ||
3216 | 3237 | ||
3217 | if (!capable(CAP_SYS_ADMIN)) | 3238 | if (!capable(CAP_SYS_ADMIN)) |
3218 | return -EPERM; | 3239 | return -EPERM; |
@@ -3230,7 +3251,7 @@ static long btrfs_ioctl_logical_to_ino(struct btrfs_root *root, | |||
3230 | goto out; | 3251 | goto out; |
3231 | } | 3252 | } |
3232 | 3253 | ||
3233 | size = min_t(u32, loi->size, 4096); | 3254 | size = min_t(u32, loi->size, 64 * 1024); |
3234 | inodes = init_data_container(size); | 3255 | inodes = init_data_container(size); |
3235 | if (IS_ERR(inodes)) { | 3256 | if (IS_ERR(inodes)) { |
3236 | ret = PTR_ERR(inodes); | 3257 | ret = PTR_ERR(inodes); |
@@ -3238,22 +3259,13 @@ static long btrfs_ioctl_logical_to_ino(struct btrfs_root *root, | |||
3238 | goto out; | 3259 | goto out; |
3239 | } | 3260 | } |
3240 | 3261 | ||
3241 | ret = extent_from_logical(root->fs_info, loi->logical, path, &key); | 3262 | ret = iterate_inodes_from_logical(loi->logical, root->fs_info, path, |
3242 | btrfs_release_path(path); | 3263 | build_ino_list, inodes); |
3243 | 3264 | if (ret == -EINVAL) | |
3244 | if (ret & BTRFS_EXTENT_FLAG_TREE_BLOCK) | ||
3245 | ret = -ENOENT; | 3265 | ret = -ENOENT; |
3246 | if (ret < 0) | 3266 | if (ret < 0) |
3247 | goto out; | 3267 | goto out; |
3248 | 3268 | ||
3249 | extent_item_pos = loi->logical - key.objectid; | ||
3250 | ret = iterate_extent_inodes(root->fs_info, key.objectid, | ||
3251 | extent_item_pos, 0, build_ino_list, | ||
3252 | inodes); | ||
3253 | |||
3254 | if (ret < 0) | ||
3255 | goto out; | ||
3256 | |||
3257 | ret = copy_to_user((void *)(unsigned long)loi->inodes, | 3269 | ret = copy_to_user((void *)(unsigned long)loi->inodes, |
3258 | (void *)(unsigned long)inodes, size); | 3270 | (void *)(unsigned long)inodes, size); |
3259 | if (ret) | 3271 | if (ret) |
@@ -3261,7 +3273,7 @@ static long btrfs_ioctl_logical_to_ino(struct btrfs_root *root, | |||
3261 | 3273 | ||
3262 | out: | 3274 | out: |
3263 | btrfs_free_path(path); | 3275 | btrfs_free_path(path); |
3264 | kfree(inodes); | 3276 | vfree(inodes); |
3265 | kfree(loi); | 3277 | kfree(loi); |
3266 | 3278 | ||
3267 | return ret; | 3279 | return ret; |