aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/backref.c
diff options
context:
space:
mode:
authorJan Schmidt <list.btrfs@jan-o-sch.net>2012-05-15 11:55:51 -0400
committerJan Schmidt <list.btrfs@jan-o-sch.net>2012-05-26 06:17:51 -0400
commitd5c88b735fdf2ef796bb937396dd58dac84e8407 (patch)
tree791a9d9f670bacfd153680f9ef992f40099734bd /fs/btrfs/backref.c
parentdadcaf78b51e239d93f5ec9aac736de99081ee74 (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.c185
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 @@
30struct __prelim_ref { 30struct __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
40static int __add_prelim_ref(struct list_head *head, u64 root_id, 79static 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
291static 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 */
313static 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 */
257static int __merge_refs(struct list_head *head, int mode) 352static 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 */
300static int __add_delayed_refs(struct btrfs_delayed_ref_head *head, u64 seq, 396static 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 */
397static int __add_inline_refs(struct btrfs_fs_info *fs_info, 491static 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 */
499static int __add_keyed_refs(struct btrfs_fs_info *fs_info, 590static 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;