aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/backref.c
diff options
context:
space:
mode:
authorJosef Bacik <jbacik@fb.com>2014-01-24 14:05:42 -0500
committerChris Mason <clm@fb.com>2014-01-28 16:20:28 -0500
commit7ef81ac86c8a44ab9f4e6e04e1f4c9ea53615b8a (patch)
tree70ea7ddd1d3285530f35568c62d1da3fd88b9099 /fs/btrfs/backref.c
parent3a6d75e846224542151e9ff186cb89df5a6ca2c6 (diff)
Btrfs: only process as many file extents as there are refs
The backref walking code will search down to the key it is looking for and then proceed to walk _all_ of the extents on the file until it hits the end. This is suboptimal with large files, we only need to look for as many extents as we have references for that inode. I have a testcase that creates a randomly written 4 gig file and before this patch it took 6min 30sec to do the initial send, with this patch it takes 2min 30sec to do the intial send. Thanks, Signed-off-by: Josef Bacik <jbacik@fb.com> Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'fs/btrfs/backref.c')
-rw-r--r--fs/btrfs/backref.c17
1 files changed, 9 insertions, 8 deletions
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
index dcf2448c16f1..15384968a84a 100644
--- a/fs/btrfs/backref.c
+++ b/fs/btrfs/backref.c
@@ -209,18 +209,19 @@ static int __add_prelim_ref(struct list_head *head, u64 root_id,
209} 209}
210 210
211static int add_all_parents(struct btrfs_root *root, struct btrfs_path *path, 211static int add_all_parents(struct btrfs_root *root, struct btrfs_path *path,
212 struct ulist *parents, int level, 212 struct ulist *parents, struct __prelim_ref *ref,
213 struct btrfs_key *key_for_search, u64 time_seq, 213 int level, u64 time_seq, const u64 *extent_item_pos)
214 u64 wanted_disk_byte,
215 const u64 *extent_item_pos)
216{ 214{
217 int ret = 0; 215 int ret = 0;
218 int slot; 216 int slot;
219 struct extent_buffer *eb; 217 struct extent_buffer *eb;
220 struct btrfs_key key; 218 struct btrfs_key key;
219 struct btrfs_key *key_for_search = &ref->key_for_search;
221 struct btrfs_file_extent_item *fi; 220 struct btrfs_file_extent_item *fi;
222 struct extent_inode_elem *eie = NULL, *old = NULL; 221 struct extent_inode_elem *eie = NULL, *old = NULL;
223 u64 disk_byte; 222 u64 disk_byte;
223 u64 wanted_disk_byte = ref->wanted_disk_byte;
224 u64 count = 0;
224 225
225 if (level != 0) { 226 if (level != 0) {
226 eb = path->nodes[level]; 227 eb = path->nodes[level];
@@ -238,7 +239,7 @@ static int add_all_parents(struct btrfs_root *root, struct btrfs_path *path,
238 if (path->slots[0] >= btrfs_header_nritems(path->nodes[0])) 239 if (path->slots[0] >= btrfs_header_nritems(path->nodes[0]))
239 ret = btrfs_next_old_leaf(root, path, time_seq); 240 ret = btrfs_next_old_leaf(root, path, time_seq);
240 241
241 while (!ret) { 242 while (!ret && count < ref->count) {
242 eb = path->nodes[0]; 243 eb = path->nodes[0];
243 slot = path->slots[0]; 244 slot = path->slots[0];
244 245
@@ -254,6 +255,7 @@ static int add_all_parents(struct btrfs_root *root, struct btrfs_path *path,
254 if (disk_byte == wanted_disk_byte) { 255 if (disk_byte == wanted_disk_byte) {
255 eie = NULL; 256 eie = NULL;
256 old = NULL; 257 old = NULL;
258 count++;
257 if (extent_item_pos) { 259 if (extent_item_pos) {
258 ret = check_extent_in_eb(&key, eb, fi, 260 ret = check_extent_in_eb(&key, eb, fi,
259 *extent_item_pos, 261 *extent_item_pos,
@@ -334,9 +336,8 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info,
334 eb = path->nodes[level]; 336 eb = path->nodes[level];
335 } 337 }
336 338
337 ret = add_all_parents(root, path, parents, level, &ref->key_for_search, 339 ret = add_all_parents(root, path, parents, ref, level, time_seq,
338 time_seq, ref->wanted_disk_byte, 340 extent_item_pos);
339 extent_item_pos);
340out: 341out:
341 path->lowest_level = 0; 342 path->lowest_level = 0;
342 btrfs_release_path(path); 343 btrfs_release_path(path);