aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ioctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/ioctl.c')
-rw-r--r--fs/btrfs/ioctl.c100
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;
2716out: 2739out:
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);
2719out_unlock: 2742out_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
2853static void get_block_group_info(struct list_head *groups_list, 2876void 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
3262out: 3274out:
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;