diff options
author | Jan Schmidt <list.btrfs@jan-o-sch.net> | 2012-05-15 11:55:51 -0400 |
---|---|---|
committer | Jan Schmidt <list.btrfs@jan-o-sch.net> | 2012-05-26 06:17:51 -0400 |
commit | d5c88b735fdf2ef796bb937396dd58dac84e8407 (patch) | |
tree | 791a9d9f670bacfd153680f9ef992f40099734bd /fs/btrfs/backref.c | |
parent | dadcaf78b51e239d93f5ec9aac736de99081ee74 (diff) |
Btrfs: bugfix: ignore the wrong key for indirect tree block backrefs
The key we store with a tree block backref is only a hint. It is set when
the ref is created and can remain correct for a long time. As the tree is
rebalanced, however, eventually the key no longer points to the correct
destination.
With this patch, we change find_parent_nodes to no longer add keys unless it
knows for sure they're correct (e.g. because they're for an extent data
backref). Then when we later encounter a backref ref with no parent and no
key set, we grab the block and take the first key from the block itself.
Signed-off-by: Jan Schmidt <list.btrfs@jan-o-sch.net>
Diffstat (limited to 'fs/btrfs/backref.c')
-rw-r--r-- | fs/btrfs/backref.c | 185 |
1 files changed, 135 insertions, 50 deletions
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c index c69a846999bf..366978c5cdd3 100644 --- a/fs/btrfs/backref.c +++ b/fs/btrfs/backref.c | |||
@@ -30,16 +30,55 @@ | |||
30 | struct __prelim_ref { | 30 | struct __prelim_ref { |
31 | struct list_head list; | 31 | struct list_head list; |
32 | u64 root_id; | 32 | u64 root_id; |
33 | struct btrfs_key key; | 33 | struct btrfs_key key_for_search; |
34 | int level; | 34 | int level; |
35 | int count; | 35 | int count; |
36 | u64 parent; | 36 | u64 parent; |
37 | u64 wanted_disk_byte; | 37 | u64 wanted_disk_byte; |
38 | }; | 38 | }; |
39 | 39 | ||
40 | /* | ||
41 | * the rules for all callers of this function are: | ||
42 | * - obtaining the parent is the goal | ||
43 | * - if you add a key, you must know that it is a correct key | ||
44 | * - if you cannot add the parent or a correct key, then we will look into the | ||
45 | * block later to set a correct key | ||
46 | * | ||
47 | * delayed refs | ||
48 | * ============ | ||
49 | * backref type | shared | indirect | shared | indirect | ||
50 | * information | tree | tree | data | data | ||
51 | * --------------------+--------+----------+--------+---------- | ||
52 | * parent logical | y | - | - | - | ||
53 | * key to resolve | - | y | y | y | ||
54 | * tree block logical | - | - | - | - | ||
55 | * root for resolving | y | y | y | y | ||
56 | * | ||
57 | * - column 1: we've the parent -> done | ||
58 | * - column 2, 3, 4: we use the key to find the parent | ||
59 | * | ||
60 | * on disk refs (inline or keyed) | ||
61 | * ============================== | ||
62 | * backref type | shared | indirect | shared | indirect | ||
63 | * information | tree | tree | data | data | ||
64 | * --------------------+--------+----------+--------+---------- | ||
65 | * parent logical | y | - | y | - | ||
66 | * key to resolve | - | - | - | y | ||
67 | * tree block logical | y | y | y | y | ||
68 | * root for resolving | - | y | y | y | ||
69 | * | ||
70 | * - column 1, 3: we've the parent -> done | ||
71 | * - column 2: we take the first key from the block to find the parent | ||
72 | * (see __add_missing_keys) | ||
73 | * - column 4: we use the key to find the parent | ||
74 | * | ||
75 | * additional information that's available but not required to find the parent | ||
76 | * block might help in merging entries to gain some speed. | ||
77 | */ | ||
78 | |||
40 | static int __add_prelim_ref(struct list_head *head, u64 root_id, | 79 | static int __add_prelim_ref(struct list_head *head, u64 root_id, |
41 | struct btrfs_key *key, int level, u64 parent, | 80 | struct btrfs_key *key, int level, |
42 | u64 wanted_disk_byte, int count) | 81 | u64 parent, u64 wanted_disk_byte, int count) |
43 | { | 82 | { |
44 | struct __prelim_ref *ref; | 83 | struct __prelim_ref *ref; |
45 | 84 | ||
@@ -50,9 +89,9 @@ static int __add_prelim_ref(struct list_head *head, u64 root_id, | |||
50 | 89 | ||
51 | ref->root_id = root_id; | 90 | ref->root_id = root_id; |
52 | if (key) | 91 | if (key) |
53 | ref->key = *key; | 92 | ref->key_for_search = *key; |
54 | else | 93 | else |
55 | memset(&ref->key, 0, sizeof(ref->key)); | 94 | memset(&ref->key_for_search, 0, sizeof(ref->key_for_search)); |
56 | 95 | ||
57 | ref->level = level; | 96 | ref->level = level; |
58 | ref->count = count; | 97 | ref->count = count; |
@@ -152,12 +191,13 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info, | |||
152 | goto out; | 191 | goto out; |
153 | 192 | ||
154 | path->lowest_level = level; | 193 | path->lowest_level = level; |
155 | ret = btrfs_search_slot(NULL, root, &ref->key, path, 0, 0); | 194 | ret = btrfs_search_slot(NULL, root, &ref->key_for_search, path, 0, 0); |
156 | pr_debug("search slot in root %llu (level %d, ref count %d) returned " | 195 | pr_debug("search slot in root %llu (level %d, ref count %d) returned " |
157 | "%d for key (%llu %u %llu)\n", | 196 | "%d for key (%llu %u %llu)\n", |
158 | (unsigned long long)ref->root_id, level, ref->count, ret, | 197 | (unsigned long long)ref->root_id, level, ref->count, ret, |
159 | (unsigned long long)ref->key.objectid, ref->key.type, | 198 | (unsigned long long)ref->key_for_search.objectid, |
160 | (unsigned long long)ref->key.offset); | 199 | ref->key_for_search.type, |
200 | (unsigned long long)ref->key_for_search.offset); | ||
161 | if (ret < 0) | 201 | if (ret < 0) |
162 | goto out; | 202 | goto out; |
163 | 203 | ||
@@ -248,10 +288,65 @@ static int __resolve_indirect_refs(struct btrfs_fs_info *fs_info, | |||
248 | return ret; | 288 | return ret; |
249 | } | 289 | } |
250 | 290 | ||
291 | static inline int ref_for_same_block(struct __prelim_ref *ref1, | ||
292 | struct __prelim_ref *ref2) | ||
293 | { | ||
294 | if (ref1->level != ref2->level) | ||
295 | return 0; | ||
296 | if (ref1->root_id != ref2->root_id) | ||
297 | return 0; | ||
298 | if (ref1->key_for_search.type != ref2->key_for_search.type) | ||
299 | return 0; | ||
300 | if (ref1->key_for_search.objectid != ref2->key_for_search.objectid) | ||
301 | return 0; | ||
302 | if (ref1->key_for_search.offset != ref2->key_for_search.offset) | ||
303 | return 0; | ||
304 | if (ref1->parent != ref2->parent) | ||
305 | return 0; | ||
306 | |||
307 | return 1; | ||
308 | } | ||
309 | |||
310 | /* | ||
311 | * read tree blocks and add keys where required. | ||
312 | */ | ||
313 | static int __add_missing_keys(struct btrfs_fs_info *fs_info, | ||
314 | struct list_head *head) | ||
315 | { | ||
316 | struct list_head *pos; | ||
317 | struct extent_buffer *eb; | ||
318 | |||
319 | list_for_each(pos, head) { | ||
320 | struct __prelim_ref *ref; | ||
321 | ref = list_entry(pos, struct __prelim_ref, list); | ||
322 | |||
323 | if (ref->parent) | ||
324 | continue; | ||
325 | if (ref->key_for_search.type) | ||
326 | continue; | ||
327 | BUG_ON(!ref->wanted_disk_byte); | ||
328 | eb = read_tree_block(fs_info->tree_root, ref->wanted_disk_byte, | ||
329 | fs_info->tree_root->leafsize, 0); | ||
330 | BUG_ON(!eb); | ||
331 | btrfs_tree_read_lock(eb); | ||
332 | if (btrfs_header_level(eb) == 0) | ||
333 | btrfs_item_key_to_cpu(eb, &ref->key_for_search, 0); | ||
334 | else | ||
335 | btrfs_node_key_to_cpu(eb, &ref->key_for_search, 0); | ||
336 | btrfs_tree_read_unlock(eb); | ||
337 | free_extent_buffer(eb); | ||
338 | } | ||
339 | return 0; | ||
340 | } | ||
341 | |||
251 | /* | 342 | /* |
252 | * merge two lists of backrefs and adjust counts accordingly | 343 | * merge two lists of backrefs and adjust counts accordingly |
253 | * | 344 | * |
254 | * mode = 1: merge identical keys, if key is set | 345 | * mode = 1: merge identical keys, if key is set |
346 | * FIXME: if we add more keys in __add_prelim_ref, we can merge more here. | ||
347 | * additionally, we could even add a key range for the blocks we | ||
348 | * looked into to merge even more (-> replace unresolved refs by those | ||
349 | * having a parent). | ||
255 | * mode = 2: merge identical parents | 350 | * mode = 2: merge identical parents |
256 | */ | 351 | */ |
257 | static int __merge_refs(struct list_head *head, int mode) | 352 | static int __merge_refs(struct list_head *head, int mode) |
@@ -265,20 +360,21 @@ static int __merge_refs(struct list_head *head, int mode) | |||
265 | 360 | ||
266 | ref1 = list_entry(pos1, struct __prelim_ref, list); | 361 | ref1 = list_entry(pos1, struct __prelim_ref, list); |
267 | 362 | ||
268 | if (mode == 1 && ref1->key.type == 0) | ||
269 | continue; | ||
270 | for (pos2 = pos1->next, n2 = pos2->next; pos2 != head; | 363 | for (pos2 = pos1->next, n2 = pos2->next; pos2 != head; |
271 | pos2 = n2, n2 = pos2->next) { | 364 | pos2 = n2, n2 = pos2->next) { |
272 | struct __prelim_ref *ref2; | 365 | struct __prelim_ref *ref2; |
366 | struct __prelim_ref *xchg; | ||
273 | 367 | ||
274 | ref2 = list_entry(pos2, struct __prelim_ref, list); | 368 | ref2 = list_entry(pos2, struct __prelim_ref, list); |
275 | 369 | ||
276 | if (mode == 1) { | 370 | if (mode == 1) { |
277 | if (memcmp(&ref1->key, &ref2->key, | 371 | if (!ref_for_same_block(ref1, ref2)) |
278 | sizeof(ref1->key)) || | ||
279 | ref1->level != ref2->level || | ||
280 | ref1->root_id != ref2->root_id) | ||
281 | continue; | 372 | continue; |
373 | if (!ref1->parent && ref2->parent) { | ||
374 | xchg = ref1; | ||
375 | ref1 = ref2; | ||
376 | ref2 = xchg; | ||
377 | } | ||
282 | ref1->count += ref2->count; | 378 | ref1->count += ref2->count; |
283 | } else { | 379 | } else { |
284 | if (ref1->parent != ref2->parent) | 380 | if (ref1->parent != ref2->parent) |
@@ -298,16 +394,17 @@ static int __merge_refs(struct list_head *head, int mode) | |||
298 | * smaller or equal that seq to the list | 394 | * smaller or equal that seq to the list |
299 | */ | 395 | */ |
300 | static int __add_delayed_refs(struct btrfs_delayed_ref_head *head, u64 seq, | 396 | static int __add_delayed_refs(struct btrfs_delayed_ref_head *head, u64 seq, |
301 | struct btrfs_key *info_key, | ||
302 | struct list_head *prefs) | 397 | struct list_head *prefs) |
303 | { | 398 | { |
304 | struct btrfs_delayed_extent_op *extent_op = head->extent_op; | 399 | struct btrfs_delayed_extent_op *extent_op = head->extent_op; |
305 | struct rb_node *n = &head->node.rb_node; | 400 | struct rb_node *n = &head->node.rb_node; |
401 | struct btrfs_key key; | ||
402 | struct btrfs_key op_key = {0}; | ||
306 | int sgn; | 403 | int sgn; |
307 | int ret = 0; | 404 | int ret = 0; |
308 | 405 | ||
309 | if (extent_op && extent_op->update_key) | 406 | if (extent_op && extent_op->update_key) |
310 | btrfs_disk_key_to_cpu(info_key, &extent_op->key); | 407 | btrfs_disk_key_to_cpu(&op_key, &extent_op->key); |
311 | 408 | ||
312 | while ((n = rb_prev(n))) { | 409 | while ((n = rb_prev(n))) { |
313 | struct btrfs_delayed_ref_node *node; | 410 | struct btrfs_delayed_ref_node *node; |
@@ -339,7 +436,7 @@ static int __add_delayed_refs(struct btrfs_delayed_ref_head *head, u64 seq, | |||
339 | struct btrfs_delayed_tree_ref *ref; | 436 | struct btrfs_delayed_tree_ref *ref; |
340 | 437 | ||
341 | ref = btrfs_delayed_node_to_tree_ref(node); | 438 | ref = btrfs_delayed_node_to_tree_ref(node); |
342 | ret = __add_prelim_ref(prefs, ref->root, info_key, | 439 | ret = __add_prelim_ref(prefs, ref->root, &op_key, |
343 | ref->level + 1, 0, node->bytenr, | 440 | ref->level + 1, 0, node->bytenr, |
344 | node->ref_mod * sgn); | 441 | node->ref_mod * sgn); |
345 | break; | 442 | break; |
@@ -348,7 +445,7 @@ static int __add_delayed_refs(struct btrfs_delayed_ref_head *head, u64 seq, | |||
348 | struct btrfs_delayed_tree_ref *ref; | 445 | struct btrfs_delayed_tree_ref *ref; |
349 | 446 | ||
350 | ref = btrfs_delayed_node_to_tree_ref(node); | 447 | ref = btrfs_delayed_node_to_tree_ref(node); |
351 | ret = __add_prelim_ref(prefs, ref->root, info_key, | 448 | ret = __add_prelim_ref(prefs, ref->root, NULL, |
352 | ref->level + 1, ref->parent, | 449 | ref->level + 1, ref->parent, |
353 | node->bytenr, | 450 | node->bytenr, |
354 | node->ref_mod * sgn); | 451 | node->ref_mod * sgn); |
@@ -356,8 +453,6 @@ static int __add_delayed_refs(struct btrfs_delayed_ref_head *head, u64 seq, | |||
356 | } | 453 | } |
357 | case BTRFS_EXTENT_DATA_REF_KEY: { | 454 | case BTRFS_EXTENT_DATA_REF_KEY: { |
358 | struct btrfs_delayed_data_ref *ref; | 455 | struct btrfs_delayed_data_ref *ref; |
359 | struct btrfs_key key; | ||
360 | |||
361 | ref = btrfs_delayed_node_to_data_ref(node); | 456 | ref = btrfs_delayed_node_to_data_ref(node); |
362 | 457 | ||
363 | key.objectid = ref->objectid; | 458 | key.objectid = ref->objectid; |
@@ -370,7 +465,6 @@ static int __add_delayed_refs(struct btrfs_delayed_ref_head *head, u64 seq, | |||
370 | } | 465 | } |
371 | case BTRFS_SHARED_DATA_REF_KEY: { | 466 | case BTRFS_SHARED_DATA_REF_KEY: { |
372 | struct btrfs_delayed_data_ref *ref; | 467 | struct btrfs_delayed_data_ref *ref; |
373 | struct btrfs_key key; | ||
374 | 468 | ||
375 | ref = btrfs_delayed_node_to_data_ref(node); | 469 | ref = btrfs_delayed_node_to_data_ref(node); |
376 | 470 | ||
@@ -396,8 +490,7 @@ static int __add_delayed_refs(struct btrfs_delayed_ref_head *head, u64 seq, | |||
396 | */ | 490 | */ |
397 | static int __add_inline_refs(struct btrfs_fs_info *fs_info, | 491 | static int __add_inline_refs(struct btrfs_fs_info *fs_info, |
398 | struct btrfs_path *path, u64 bytenr, | 492 | struct btrfs_path *path, u64 bytenr, |
399 | struct btrfs_key *info_key, int *info_level, | 493 | int *info_level, struct list_head *prefs) |
400 | struct list_head *prefs) | ||
401 | { | 494 | { |
402 | int ret = 0; | 495 | int ret = 0; |
403 | int slot; | 496 | int slot; |
@@ -426,12 +519,9 @@ static int __add_inline_refs(struct btrfs_fs_info *fs_info, | |||
426 | 519 | ||
427 | if (flags & BTRFS_EXTENT_FLAG_TREE_BLOCK) { | 520 | if (flags & BTRFS_EXTENT_FLAG_TREE_BLOCK) { |
428 | struct btrfs_tree_block_info *info; | 521 | struct btrfs_tree_block_info *info; |
429 | struct btrfs_disk_key disk_key; | ||
430 | 522 | ||
431 | info = (struct btrfs_tree_block_info *)ptr; | 523 | info = (struct btrfs_tree_block_info *)ptr; |
432 | *info_level = btrfs_tree_block_level(leaf, info); | 524 | *info_level = btrfs_tree_block_level(leaf, info); |
433 | btrfs_tree_block_key(leaf, info, &disk_key); | ||
434 | btrfs_disk_key_to_cpu(info_key, &disk_key); | ||
435 | ptr += sizeof(struct btrfs_tree_block_info); | 525 | ptr += sizeof(struct btrfs_tree_block_info); |
436 | BUG_ON(ptr > end); | 526 | BUG_ON(ptr > end); |
437 | } else { | 527 | } else { |
@@ -449,7 +539,7 @@ static int __add_inline_refs(struct btrfs_fs_info *fs_info, | |||
449 | 539 | ||
450 | switch (type) { | 540 | switch (type) { |
451 | case BTRFS_SHARED_BLOCK_REF_KEY: | 541 | case BTRFS_SHARED_BLOCK_REF_KEY: |
452 | ret = __add_prelim_ref(prefs, 0, info_key, | 542 | ret = __add_prelim_ref(prefs, 0, NULL, |
453 | *info_level + 1, offset, | 543 | *info_level + 1, offset, |
454 | bytenr, 1); | 544 | bytenr, 1); |
455 | break; | 545 | break; |
@@ -464,8 +554,9 @@ static int __add_inline_refs(struct btrfs_fs_info *fs_info, | |||
464 | break; | 554 | break; |
465 | } | 555 | } |
466 | case BTRFS_TREE_BLOCK_REF_KEY: | 556 | case BTRFS_TREE_BLOCK_REF_KEY: |
467 | ret = __add_prelim_ref(prefs, offset, info_key, | 557 | ret = __add_prelim_ref(prefs, offset, NULL, |
468 | *info_level + 1, 0, bytenr, 1); | 558 | *info_level + 1, 0, |
559 | bytenr, 1); | ||
469 | break; | 560 | break; |
470 | case BTRFS_EXTENT_DATA_REF_KEY: { | 561 | case BTRFS_EXTENT_DATA_REF_KEY: { |
471 | struct btrfs_extent_data_ref *dref; | 562 | struct btrfs_extent_data_ref *dref; |
@@ -479,8 +570,8 @@ static int __add_inline_refs(struct btrfs_fs_info *fs_info, | |||
479 | key.type = BTRFS_EXTENT_DATA_KEY; | 570 | key.type = BTRFS_EXTENT_DATA_KEY; |
480 | key.offset = btrfs_extent_data_ref_offset(leaf, dref); | 571 | key.offset = btrfs_extent_data_ref_offset(leaf, dref); |
481 | root = btrfs_extent_data_ref_root(leaf, dref); | 572 | root = btrfs_extent_data_ref_root(leaf, dref); |
482 | ret = __add_prelim_ref(prefs, root, &key, 0, 0, bytenr, | 573 | ret = __add_prelim_ref(prefs, root, &key, 0, 0, |
483 | count); | 574 | bytenr, count); |
484 | break; | 575 | break; |
485 | } | 576 | } |
486 | default: | 577 | default: |
@@ -498,8 +589,7 @@ static int __add_inline_refs(struct btrfs_fs_info *fs_info, | |||
498 | */ | 589 | */ |
499 | static int __add_keyed_refs(struct btrfs_fs_info *fs_info, | 590 | static int __add_keyed_refs(struct btrfs_fs_info *fs_info, |
500 | struct btrfs_path *path, u64 bytenr, | 591 | struct btrfs_path *path, u64 bytenr, |
501 | struct btrfs_key *info_key, int info_level, | 592 | int info_level, struct list_head *prefs) |
502 | struct list_head *prefs) | ||
503 | { | 593 | { |
504 | struct btrfs_root *extent_root = fs_info->extent_root; | 594 | struct btrfs_root *extent_root = fs_info->extent_root; |
505 | int ret; | 595 | int ret; |
@@ -529,7 +619,7 @@ static int __add_keyed_refs(struct btrfs_fs_info *fs_info, | |||
529 | 619 | ||
530 | switch (key.type) { | 620 | switch (key.type) { |
531 | case BTRFS_SHARED_BLOCK_REF_KEY: | 621 | case BTRFS_SHARED_BLOCK_REF_KEY: |
532 | ret = __add_prelim_ref(prefs, 0, info_key, | 622 | ret = __add_prelim_ref(prefs, 0, NULL, |
533 | info_level + 1, key.offset, | 623 | info_level + 1, key.offset, |
534 | bytenr, 1); | 624 | bytenr, 1); |
535 | break; | 625 | break; |
@@ -545,8 +635,9 @@ static int __add_keyed_refs(struct btrfs_fs_info *fs_info, | |||
545 | break; | 635 | break; |
546 | } | 636 | } |
547 | case BTRFS_TREE_BLOCK_REF_KEY: | 637 | case BTRFS_TREE_BLOCK_REF_KEY: |
548 | ret = __add_prelim_ref(prefs, key.offset, info_key, | 638 | ret = __add_prelim_ref(prefs, key.offset, NULL, |
549 | info_level + 1, 0, bytenr, 1); | 639 | info_level + 1, 0, |
640 | bytenr, 1); | ||
550 | break; | 641 | break; |
551 | case BTRFS_EXTENT_DATA_REF_KEY: { | 642 | case BTRFS_EXTENT_DATA_REF_KEY: { |
552 | struct btrfs_extent_data_ref *dref; | 643 | struct btrfs_extent_data_ref *dref; |
@@ -562,7 +653,7 @@ static int __add_keyed_refs(struct btrfs_fs_info *fs_info, | |||
562 | key.offset = btrfs_extent_data_ref_offset(leaf, dref); | 653 | key.offset = btrfs_extent_data_ref_offset(leaf, dref); |
563 | root = btrfs_extent_data_ref_root(leaf, dref); | 654 | root = btrfs_extent_data_ref_root(leaf, dref); |
564 | ret = __add_prelim_ref(prefs, root, &key, 0, 0, | 655 | ret = __add_prelim_ref(prefs, root, &key, 0, 0, |
565 | bytenr, count); | 656 | bytenr, count); |
566 | break; | 657 | break; |
567 | } | 658 | } |
568 | default: | 659 | default: |
@@ -588,7 +679,6 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans, | |||
588 | { | 679 | { |
589 | struct btrfs_key key; | 680 | struct btrfs_key key; |
590 | struct btrfs_path *path; | 681 | struct btrfs_path *path; |
591 | struct btrfs_key info_key = { 0 }; | ||
592 | struct btrfs_delayed_ref_root *delayed_refs = NULL; | 682 | struct btrfs_delayed_ref_root *delayed_refs = NULL; |
593 | struct btrfs_delayed_ref_head *head; | 683 | struct btrfs_delayed_ref_head *head; |
594 | int info_level = 0; | 684 | int info_level = 0; |
@@ -647,8 +737,7 @@ again: | |||
647 | btrfs_put_delayed_ref(&head->node); | 737 | btrfs_put_delayed_ref(&head->node); |
648 | goto again; | 738 | goto again; |
649 | } | 739 | } |
650 | ret = __add_delayed_refs(head, seq, &info_key, | 740 | ret = __add_delayed_refs(head, seq, &prefs_delayed); |
651 | &prefs_delayed); | ||
652 | if (ret) { | 741 | if (ret) { |
653 | spin_unlock(&delayed_refs->lock); | 742 | spin_unlock(&delayed_refs->lock); |
654 | goto out; | 743 | goto out; |
@@ -668,10 +757,10 @@ again: | |||
668 | if (key.objectid == bytenr && | 757 | if (key.objectid == bytenr && |
669 | key.type == BTRFS_EXTENT_ITEM_KEY) { | 758 | key.type == BTRFS_EXTENT_ITEM_KEY) { |
670 | ret = __add_inline_refs(fs_info, path, bytenr, | 759 | ret = __add_inline_refs(fs_info, path, bytenr, |
671 | &info_key, &info_level, &prefs); | 760 | &info_level, &prefs); |
672 | if (ret) | 761 | if (ret) |
673 | goto out; | 762 | goto out; |
674 | ret = __add_keyed_refs(fs_info, path, bytenr, &info_key, | 763 | ret = __add_keyed_refs(fs_info, path, bytenr, |
675 | info_level, &prefs); | 764 | info_level, &prefs); |
676 | if (ret) | 765 | if (ret) |
677 | goto out; | 766 | goto out; |
@@ -679,16 +768,12 @@ again: | |||
679 | } | 768 | } |
680 | btrfs_release_path(path); | 769 | btrfs_release_path(path); |
681 | 770 | ||
682 | /* | ||
683 | * when adding the delayed refs above, the info_key might not have | ||
684 | * been known yet. Go over the list and replace the missing keys | ||
685 | */ | ||
686 | list_for_each_entry(ref, &prefs_delayed, list) { | ||
687 | if ((ref->key.offset | ref->key.type | ref->key.objectid) == 0) | ||
688 | memcpy(&ref->key, &info_key, sizeof(ref->key)); | ||
689 | } | ||
690 | list_splice_init(&prefs_delayed, &prefs); | 771 | list_splice_init(&prefs_delayed, &prefs); |
691 | 772 | ||
773 | ret = __add_missing_keys(fs_info, &prefs); | ||
774 | if (ret) | ||
775 | goto out; | ||
776 | |||
692 | ret = __merge_refs(&prefs, 1); | 777 | ret = __merge_refs(&prefs, 1); |
693 | if (ret) | 778 | if (ret) |
694 | goto out; | 779 | goto out; |