aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorFilipe David Borba Manana <fdmanana@gmail.com>2014-01-13 14:35:01 -0500
committerChris Mason <clm@fb.com>2014-01-28 16:20:35 -0500
commite4355f34ef9fc75a93875fd075137ef2ea378883 (patch)
tree01b9bcb875745c6439f708d20d53eed6b0c3d277 /fs
parent1a4319cc3c495d5b6b8e41f4d4c73b950d54c2be (diff)
Btrfs: faster file extent item search in clone ioctl
When we are looking for file extent items that intersect the cloning range, for each one that falls completely outside the range, don't release the path and do another full tree search - just move on to the next slot and copy the file extent item into our buffer only if the item intersects the cloning range. Signed-off-by: Filipe David Borba Manana <fdmanana@gmail.com> Signed-off-by: Josef Bacik <jbacik@fb.com> Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/ioctl.c23
1 files changed, 14 insertions, 9 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 5ed5bd001084..829999dafd93 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -2905,12 +2905,14 @@ static int btrfs_clone(struct inode *src, struct inode *inode,
2905 * note the key will change type as we walk through the 2905 * note the key will change type as we walk through the
2906 * tree. 2906 * tree.
2907 */ 2907 */
2908 path->leave_spinning = 1;
2908 ret = btrfs_search_slot(NULL, BTRFS_I(src)->root, &key, path, 2909 ret = btrfs_search_slot(NULL, BTRFS_I(src)->root, &key, path,
2909 0, 0); 2910 0, 0);
2910 if (ret < 0) 2911 if (ret < 0)
2911 goto out; 2912 goto out;
2912 2913
2913 nritems = btrfs_header_nritems(path->nodes[0]); 2914 nritems = btrfs_header_nritems(path->nodes[0]);
2915process_slot:
2914 if (path->slots[0] >= nritems) { 2916 if (path->slots[0] >= nritems) {
2915 ret = btrfs_next_leaf(BTRFS_I(src)->root, path); 2917 ret = btrfs_next_leaf(BTRFS_I(src)->root, path);
2916 if (ret < 0) 2918 if (ret < 0)
@@ -2937,11 +2939,6 @@ static int btrfs_clone(struct inode *src, struct inode *inode,
2937 u8 comp; 2939 u8 comp;
2938 u64 endoff; 2940 u64 endoff;
2939 2941
2940 size = btrfs_item_size_nr(leaf, slot);
2941 read_extent_buffer(leaf, buf,
2942 btrfs_item_ptr_offset(leaf, slot),
2943 size);
2944
2945 extent = btrfs_item_ptr(leaf, slot, 2942 extent = btrfs_item_ptr(leaf, slot,
2946 struct btrfs_file_extent_item); 2943 struct btrfs_file_extent_item);
2947 comp = btrfs_file_extent_compression(leaf, extent); 2944 comp = btrfs_file_extent_compression(leaf, extent);
@@ -2960,11 +2957,20 @@ static int btrfs_clone(struct inode *src, struct inode *inode,
2960 datal = btrfs_file_extent_ram_bytes(leaf, 2957 datal = btrfs_file_extent_ram_bytes(leaf,
2961 extent); 2958 extent);
2962 } 2959 }
2963 btrfs_release_path(path);
2964 2960
2965 if (key.offset + datal <= off || 2961 if (key.offset + datal <= off ||
2966 key.offset >= off + len - 1) 2962 key.offset >= off + len - 1) {
2967 goto next; 2963 path->slots[0]++;
2964 goto process_slot;
2965 }
2966
2967 size = btrfs_item_size_nr(leaf, slot);
2968 read_extent_buffer(leaf, buf,
2969 btrfs_item_ptr_offset(leaf, slot),
2970 size);
2971
2972 btrfs_release_path(path);
2973 path->leave_spinning = 0;
2968 2974
2969 memcpy(&new_key, &key, sizeof(new_key)); 2975 memcpy(&new_key, &key, sizeof(new_key));
2970 new_key.objectid = btrfs_ino(inode); 2976 new_key.objectid = btrfs_ino(inode);
@@ -3135,7 +3141,6 @@ static int btrfs_clone(struct inode *src, struct inode *inode,
3135 } 3141 }
3136 ret = btrfs_end_transaction(trans, root); 3142 ret = btrfs_end_transaction(trans, root);
3137 } 3143 }
3138next:
3139 btrfs_release_path(path); 3144 btrfs_release_path(path);
3140 key.offset++; 3145 key.offset++;
3141 } 3146 }