diff options
-rw-r--r-- | fs/btrfs/backref.c | 9 | ||||
-rw-r--r-- | fs/btrfs/delayed-ref.c | 156 | ||||
-rw-r--r-- | fs/btrfs/delayed-ref.h | 18 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 8 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 46 |
5 files changed, 114 insertions, 123 deletions
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c index a3316f1707e6..49bc5a41c1f8 100644 --- a/fs/btrfs/backref.c +++ b/fs/btrfs/backref.c | |||
@@ -574,8 +574,8 @@ static int __add_delayed_refs(struct btrfs_delayed_ref_head *head, u64 seq, | |||
574 | struct list_head *prefs, u64 *total_refs, | 574 | struct list_head *prefs, u64 *total_refs, |
575 | u64 inum) | 575 | u64 inum) |
576 | { | 576 | { |
577 | struct btrfs_delayed_ref_node *node; | ||
577 | struct btrfs_delayed_extent_op *extent_op = head->extent_op; | 578 | struct btrfs_delayed_extent_op *extent_op = head->extent_op; |
578 | struct rb_node *n = &head->node.rb_node; | ||
579 | struct btrfs_key key; | 579 | struct btrfs_key key; |
580 | struct btrfs_key op_key = {0}; | 580 | struct btrfs_key op_key = {0}; |
581 | int sgn; | 581 | int sgn; |
@@ -585,12 +585,7 @@ static int __add_delayed_refs(struct btrfs_delayed_ref_head *head, u64 seq, | |||
585 | btrfs_disk_key_to_cpu(&op_key, &extent_op->key); | 585 | btrfs_disk_key_to_cpu(&op_key, &extent_op->key); |
586 | 586 | ||
587 | spin_lock(&head->lock); | 587 | spin_lock(&head->lock); |
588 | n = rb_first(&head->ref_root); | 588 | list_for_each_entry(node, &head->ref_list, list) { |
589 | while (n) { | ||
590 | struct btrfs_delayed_ref_node *node; | ||
591 | node = rb_entry(n, struct btrfs_delayed_ref_node, | ||
592 | rb_node); | ||
593 | n = rb_next(n); | ||
594 | if (node->seq > seq) | 589 | if (node->seq > seq) |
595 | continue; | 590 | continue; |
596 | 591 | ||
diff --git a/fs/btrfs/delayed-ref.c b/fs/btrfs/delayed-ref.c index 8f8ed7d20bac..4dbc31636d14 100644 --- a/fs/btrfs/delayed-ref.c +++ b/fs/btrfs/delayed-ref.c | |||
@@ -268,7 +268,7 @@ static inline void drop_delayed_ref(struct btrfs_trans_handle *trans, | |||
268 | rb_erase(&head->href_node, &delayed_refs->href_root); | 268 | rb_erase(&head->href_node, &delayed_refs->href_root); |
269 | } else { | 269 | } else { |
270 | assert_spin_locked(&head->lock); | 270 | assert_spin_locked(&head->lock); |
271 | rb_erase(&ref->rb_node, &head->ref_root); | 271 | list_del(&ref->list); |
272 | } | 272 | } |
273 | ref->in_tree = 0; | 273 | ref->in_tree = 0; |
274 | btrfs_put_delayed_ref(ref); | 274 | btrfs_put_delayed_ref(ref); |
@@ -328,48 +328,6 @@ static int merge_ref(struct btrfs_trans_handle *trans, | |||
328 | return done; | 328 | return done; |
329 | } | 329 | } |
330 | 330 | ||
331 | void btrfs_merge_delayed_refs(struct btrfs_trans_handle *trans, | ||
332 | struct btrfs_fs_info *fs_info, | ||
333 | struct btrfs_delayed_ref_root *delayed_refs, | ||
334 | struct btrfs_delayed_ref_head *head) | ||
335 | { | ||
336 | struct rb_node *node; | ||
337 | u64 seq = 0; | ||
338 | |||
339 | assert_spin_locked(&head->lock); | ||
340 | /* | ||
341 | * We don't have too much refs to merge in the case of delayed data | ||
342 | * refs. | ||
343 | */ | ||
344 | if (head->is_data) | ||
345 | return; | ||
346 | |||
347 | spin_lock(&fs_info->tree_mod_seq_lock); | ||
348 | if (!list_empty(&fs_info->tree_mod_seq_list)) { | ||
349 | struct seq_list *elem; | ||
350 | |||
351 | elem = list_first_entry(&fs_info->tree_mod_seq_list, | ||
352 | struct seq_list, list); | ||
353 | seq = elem->seq; | ||
354 | } | ||
355 | spin_unlock(&fs_info->tree_mod_seq_lock); | ||
356 | |||
357 | node = rb_first(&head->ref_root); | ||
358 | while (node) { | ||
359 | struct btrfs_delayed_ref_node *ref; | ||
360 | |||
361 | ref = rb_entry(node, struct btrfs_delayed_ref_node, | ||
362 | rb_node); | ||
363 | /* We can't merge refs that are outside of our seq count */ | ||
364 | if (seq && ref->seq >= seq) | ||
365 | break; | ||
366 | if (merge_ref(trans, delayed_refs, head, ref, seq)) | ||
367 | node = rb_first(&head->ref_root); | ||
368 | else | ||
369 | node = rb_next(&ref->rb_node); | ||
370 | } | ||
371 | } | ||
372 | |||
373 | int btrfs_check_delayed_seq(struct btrfs_fs_info *fs_info, | 331 | int btrfs_check_delayed_seq(struct btrfs_fs_info *fs_info, |
374 | struct btrfs_delayed_ref_root *delayed_refs, | 332 | struct btrfs_delayed_ref_root *delayed_refs, |
375 | u64 seq) | 333 | u64 seq) |
@@ -485,6 +443,74 @@ update_existing_ref(struct btrfs_trans_handle *trans, | |||
485 | } | 443 | } |
486 | 444 | ||
487 | /* | 445 | /* |
446 | * Helper to insert the ref_node to the tail or merge with tail. | ||
447 | * | ||
448 | * Return 0 for insert. | ||
449 | * Return >0 for merge. | ||
450 | */ | ||
451 | static int | ||
452 | add_delayed_ref_tail_merge(struct btrfs_trans_handle *trans, | ||
453 | struct btrfs_delayed_ref_root *root, | ||
454 | struct btrfs_delayed_ref_head *href, | ||
455 | struct btrfs_delayed_ref_node *ref) | ||
456 | { | ||
457 | struct btrfs_delayed_ref_node *exist; | ||
458 | int mod; | ||
459 | int ret = 0; | ||
460 | |||
461 | spin_lock(&href->lock); | ||
462 | /* Check whether we can merge the tail node with ref */ | ||
463 | if (list_empty(&href->ref_list)) | ||
464 | goto add_tail; | ||
465 | exist = list_entry(href->ref_list.prev, struct btrfs_delayed_ref_node, | ||
466 | list); | ||
467 | /* No need to compare bytenr nor is_head */ | ||
468 | if (exist->type != ref->type || exist->no_quota != ref->no_quota || | ||
469 | exist->seq != ref->seq) | ||
470 | goto add_tail; | ||
471 | |||
472 | if ((exist->type == BTRFS_TREE_BLOCK_REF_KEY || | ||
473 | exist->type == BTRFS_SHARED_BLOCK_REF_KEY) && | ||
474 | comp_tree_refs(btrfs_delayed_node_to_tree_ref(exist), | ||
475 | btrfs_delayed_node_to_tree_ref(ref), | ||
476 | ref->type)) | ||
477 | goto add_tail; | ||
478 | if ((exist->type == BTRFS_EXTENT_DATA_REF_KEY || | ||
479 | exist->type == BTRFS_SHARED_DATA_REF_KEY) && | ||
480 | comp_data_refs(btrfs_delayed_node_to_data_ref(exist), | ||
481 | btrfs_delayed_node_to_data_ref(ref))) | ||
482 | goto add_tail; | ||
483 | |||
484 | /* Now we are sure we can merge */ | ||
485 | ret = 1; | ||
486 | if (exist->action == ref->action) { | ||
487 | mod = ref->ref_mod; | ||
488 | } else { | ||
489 | /* Need to change action */ | ||
490 | if (exist->ref_mod < ref->ref_mod) { | ||
491 | exist->action = ref->action; | ||
492 | mod = -exist->ref_mod; | ||
493 | exist->ref_mod = ref->ref_mod; | ||
494 | } else | ||
495 | mod = -ref->ref_mod; | ||
496 | } | ||
497 | exist->ref_mod += mod; | ||
498 | |||
499 | /* remove existing tail if its ref_mod is zero */ | ||
500 | if (exist->ref_mod == 0) | ||
501 | drop_delayed_ref(trans, root, href, exist); | ||
502 | spin_unlock(&href->lock); | ||
503 | return ret; | ||
504 | |||
505 | add_tail: | ||
506 | list_add_tail(&ref->list, &href->ref_list); | ||
507 | atomic_inc(&root->num_entries); | ||
508 | trans->delayed_ref_updates++; | ||
509 | spin_unlock(&href->lock); | ||
510 | return ret; | ||
511 | } | ||
512 | |||
513 | /* | ||
488 | * helper function to update the accounting in the head ref | 514 | * helper function to update the accounting in the head ref |
489 | * existing and update must have the same bytenr | 515 | * existing and update must have the same bytenr |
490 | */ | 516 | */ |
@@ -618,7 +644,7 @@ add_delayed_ref_head(struct btrfs_fs_info *fs_info, | |||
618 | head_ref = btrfs_delayed_node_to_head(ref); | 644 | head_ref = btrfs_delayed_node_to_head(ref); |
619 | head_ref->must_insert_reserved = must_insert_reserved; | 645 | head_ref->must_insert_reserved = must_insert_reserved; |
620 | head_ref->is_data = is_data; | 646 | head_ref->is_data = is_data; |
621 | head_ref->ref_root = RB_ROOT; | 647 | INIT_LIST_HEAD(&head_ref->ref_list); |
622 | head_ref->processing = 0; | 648 | head_ref->processing = 0; |
623 | head_ref->total_ref_mod = count_mod; | 649 | head_ref->total_ref_mod = count_mod; |
624 | 650 | ||
@@ -659,10 +685,10 @@ add_delayed_tree_ref(struct btrfs_fs_info *fs_info, | |||
659 | u64 num_bytes, u64 parent, u64 ref_root, int level, | 685 | u64 num_bytes, u64 parent, u64 ref_root, int level, |
660 | int action, int no_quota) | 686 | int action, int no_quota) |
661 | { | 687 | { |
662 | struct btrfs_delayed_ref_node *existing; | ||
663 | struct btrfs_delayed_tree_ref *full_ref; | 688 | struct btrfs_delayed_tree_ref *full_ref; |
664 | struct btrfs_delayed_ref_root *delayed_refs; | 689 | struct btrfs_delayed_ref_root *delayed_refs; |
665 | u64 seq = 0; | 690 | u64 seq = 0; |
691 | int ret; | ||
666 | 692 | ||
667 | if (action == BTRFS_ADD_DELAYED_EXTENT) | 693 | if (action == BTRFS_ADD_DELAYED_EXTENT) |
668 | action = BTRFS_ADD_DELAYED_REF; | 694 | action = BTRFS_ADD_DELAYED_REF; |
@@ -693,21 +719,14 @@ add_delayed_tree_ref(struct btrfs_fs_info *fs_info, | |||
693 | 719 | ||
694 | trace_add_delayed_tree_ref(ref, full_ref, action); | 720 | trace_add_delayed_tree_ref(ref, full_ref, action); |
695 | 721 | ||
696 | spin_lock(&head_ref->lock); | 722 | ret = add_delayed_ref_tail_merge(trans, delayed_refs, head_ref, ref); |
697 | existing = tree_insert(&head_ref->ref_root, &ref->rb_node); | 723 | |
698 | if (existing) { | 724 | /* |
699 | update_existing_ref(trans, delayed_refs, head_ref, existing, | 725 | * XXX: memory should be freed at the same level allocated. |
700 | ref); | 726 | * But bad practice is anywhere... Follow it now. Need cleanup. |
701 | /* | 727 | */ |
702 | * we've updated the existing ref, free the newly | 728 | if (ret > 0) |
703 | * allocated ref | ||
704 | */ | ||
705 | kmem_cache_free(btrfs_delayed_tree_ref_cachep, full_ref); | 729 | kmem_cache_free(btrfs_delayed_tree_ref_cachep, full_ref); |
706 | } else { | ||
707 | atomic_inc(&delayed_refs->num_entries); | ||
708 | trans->delayed_ref_updates++; | ||
709 | } | ||
710 | spin_unlock(&head_ref->lock); | ||
711 | } | 730 | } |
712 | 731 | ||
713 | /* | 732 | /* |
@@ -721,10 +740,10 @@ add_delayed_data_ref(struct btrfs_fs_info *fs_info, | |||
721 | u64 num_bytes, u64 parent, u64 ref_root, u64 owner, | 740 | u64 num_bytes, u64 parent, u64 ref_root, u64 owner, |
722 | u64 offset, int action, int no_quota) | 741 | u64 offset, int action, int no_quota) |
723 | { | 742 | { |
724 | struct btrfs_delayed_ref_node *existing; | ||
725 | struct btrfs_delayed_data_ref *full_ref; | 743 | struct btrfs_delayed_data_ref *full_ref; |
726 | struct btrfs_delayed_ref_root *delayed_refs; | 744 | struct btrfs_delayed_ref_root *delayed_refs; |
727 | u64 seq = 0; | 745 | u64 seq = 0; |
746 | int ret; | ||
728 | 747 | ||
729 | if (action == BTRFS_ADD_DELAYED_EXTENT) | 748 | if (action == BTRFS_ADD_DELAYED_EXTENT) |
730 | action = BTRFS_ADD_DELAYED_REF; | 749 | action = BTRFS_ADD_DELAYED_REF; |
@@ -758,21 +777,10 @@ add_delayed_data_ref(struct btrfs_fs_info *fs_info, | |||
758 | 777 | ||
759 | trace_add_delayed_data_ref(ref, full_ref, action); | 778 | trace_add_delayed_data_ref(ref, full_ref, action); |
760 | 779 | ||
761 | spin_lock(&head_ref->lock); | 780 | ret = add_delayed_ref_tail_merge(trans, delayed_refs, head_ref, ref); |
762 | existing = tree_insert(&head_ref->ref_root, &ref->rb_node); | 781 | |
763 | if (existing) { | 782 | if (ret > 0) |
764 | update_existing_ref(trans, delayed_refs, head_ref, existing, | ||
765 | ref); | ||
766 | /* | ||
767 | * we've updated the existing ref, free the newly | ||
768 | * allocated ref | ||
769 | */ | ||
770 | kmem_cache_free(btrfs_delayed_data_ref_cachep, full_ref); | 783 | kmem_cache_free(btrfs_delayed_data_ref_cachep, full_ref); |
771 | } else { | ||
772 | atomic_inc(&delayed_refs->num_entries); | ||
773 | trans->delayed_ref_updates++; | ||
774 | } | ||
775 | spin_unlock(&head_ref->lock); | ||
776 | } | 784 | } |
777 | 785 | ||
778 | /* | 786 | /* |
diff --git a/fs/btrfs/delayed-ref.h b/fs/btrfs/delayed-ref.h index 5eb0892396d0..362ca57cfeb7 100644 --- a/fs/btrfs/delayed-ref.h +++ b/fs/btrfs/delayed-ref.h | |||
@@ -24,9 +24,25 @@ | |||
24 | #define BTRFS_ADD_DELAYED_EXTENT 3 /* record a full extent allocation */ | 24 | #define BTRFS_ADD_DELAYED_EXTENT 3 /* record a full extent allocation */ |
25 | #define BTRFS_UPDATE_DELAYED_HEAD 4 /* not changing ref count on head ref */ | 25 | #define BTRFS_UPDATE_DELAYED_HEAD 4 /* not changing ref count on head ref */ |
26 | 26 | ||
27 | /* | ||
28 | * XXX: Qu: I really hate the design that ref_head and tree/data ref shares the | ||
29 | * same ref_node structure. | ||
30 | * Ref_head is in a higher logic level than tree/data ref, and duplicated | ||
31 | * bytenr/num_bytes in ref_node is really a waste or memory, they should be | ||
32 | * referred from ref_head. | ||
33 | * This gets more disgusting after we use list to store tree/data ref in | ||
34 | * ref_head. Must clean this mess up later. | ||
35 | */ | ||
27 | struct btrfs_delayed_ref_node { | 36 | struct btrfs_delayed_ref_node { |
37 | /* | ||
38 | * ref_head use rb tree, stored in ref_root->href. | ||
39 | * indexed by bytenr | ||
40 | */ | ||
28 | struct rb_node rb_node; | 41 | struct rb_node rb_node; |
29 | 42 | ||
43 | /*data/tree ref use list, stored in ref_head->ref_list. */ | ||
44 | struct list_head list; | ||
45 | |||
30 | /* the starting bytenr of the extent */ | 46 | /* the starting bytenr of the extent */ |
31 | u64 bytenr; | 47 | u64 bytenr; |
32 | 48 | ||
@@ -83,7 +99,7 @@ struct btrfs_delayed_ref_head { | |||
83 | struct mutex mutex; | 99 | struct mutex mutex; |
84 | 100 | ||
85 | spinlock_t lock; | 101 | spinlock_t lock; |
86 | struct rb_root ref_root; | 102 | struct list_head ref_list; |
87 | 103 | ||
88 | struct rb_node href_node; | 104 | struct rb_node href_node; |
89 | 105 | ||
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 7f8377871283..695363ae1c28 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -4062,6 +4062,7 @@ static int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans, | |||
4062 | 4062 | ||
4063 | while ((node = rb_first(&delayed_refs->href_root)) != NULL) { | 4063 | while ((node = rb_first(&delayed_refs->href_root)) != NULL) { |
4064 | struct btrfs_delayed_ref_head *head; | 4064 | struct btrfs_delayed_ref_head *head; |
4065 | struct btrfs_delayed_ref_node *tmp; | ||
4065 | bool pin_bytes = false; | 4066 | bool pin_bytes = false; |
4066 | 4067 | ||
4067 | head = rb_entry(node, struct btrfs_delayed_ref_head, | 4068 | head = rb_entry(node, struct btrfs_delayed_ref_head, |
@@ -4077,11 +4078,10 @@ static int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans, | |||
4077 | continue; | 4078 | continue; |
4078 | } | 4079 | } |
4079 | spin_lock(&head->lock); | 4080 | spin_lock(&head->lock); |
4080 | while ((node = rb_first(&head->ref_root)) != NULL) { | 4081 | list_for_each_entry_safe_reverse(ref, tmp, &head->ref_list, |
4081 | ref = rb_entry(node, struct btrfs_delayed_ref_node, | 4082 | list) { |
4082 | rb_node); | ||
4083 | ref->in_tree = 0; | 4083 | ref->in_tree = 0; |
4084 | rb_erase(&ref->rb_node, &head->ref_root); | 4084 | list_del(&ref->list); |
4085 | atomic_dec(&delayed_refs->num_entries); | 4085 | atomic_dec(&delayed_refs->num_entries); |
4086 | btrfs_put_delayed_ref(ref); | 4086 | btrfs_put_delayed_ref(ref); |
4087 | } | 4087 | } |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 4eefabcc838f..adf0eedde502 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -2323,28 +2323,14 @@ static int run_one_delayed_ref(struct btrfs_trans_handle *trans, | |||
2323 | return ret; | 2323 | return ret; |
2324 | } | 2324 | } |
2325 | 2325 | ||
2326 | static noinline struct btrfs_delayed_ref_node * | 2326 | static inline struct btrfs_delayed_ref_node * |
2327 | select_delayed_ref(struct btrfs_delayed_ref_head *head) | 2327 | select_delayed_ref(struct btrfs_delayed_ref_head *head) |
2328 | { | 2328 | { |
2329 | struct rb_node *node; | 2329 | if (list_empty(&head->ref_list)) |
2330 | struct btrfs_delayed_ref_node *ref, *last = NULL;; | 2330 | return NULL; |
2331 | 2331 | ||
2332 | /* | 2332 | return list_entry(head->ref_list.next, struct btrfs_delayed_ref_node, |
2333 | * select delayed ref of type BTRFS_ADD_DELAYED_REF first. | 2333 | list); |
2334 | * this prevents ref count from going down to zero when | ||
2335 | * there still are pending delayed ref. | ||
2336 | */ | ||
2337 | node = rb_first(&head->ref_root); | ||
2338 | while (node) { | ||
2339 | ref = rb_entry(node, struct btrfs_delayed_ref_node, | ||
2340 | rb_node); | ||
2341 | if (ref->action == BTRFS_ADD_DELAYED_REF) | ||
2342 | return ref; | ||
2343 | else if (last == NULL) | ||
2344 | last = ref; | ||
2345 | node = rb_next(node); | ||
2346 | } | ||
2347 | return last; | ||
2348 | } | 2334 | } |
2349 | 2335 | ||
2350 | /* | 2336 | /* |
@@ -2396,16 +2382,7 @@ static noinline int __btrfs_run_delayed_refs(struct btrfs_trans_handle *trans, | |||
2396 | } | 2382 | } |
2397 | } | 2383 | } |
2398 | 2384 | ||
2399 | /* | ||
2400 | * We need to try and merge add/drops of the same ref since we | ||
2401 | * can run into issues with relocate dropping the implicit ref | ||
2402 | * and then it being added back again before the drop can | ||
2403 | * finish. If we merged anything we need to re-loop so we can | ||
2404 | * get a good ref. | ||
2405 | */ | ||
2406 | spin_lock(&locked_ref->lock); | 2385 | spin_lock(&locked_ref->lock); |
2407 | btrfs_merge_delayed_refs(trans, fs_info, delayed_refs, | ||
2408 | locked_ref); | ||
2409 | 2386 | ||
2410 | /* | 2387 | /* |
2411 | * locked_ref is the head node, so we have to go one | 2388 | * locked_ref is the head node, so we have to go one |
@@ -2482,7 +2459,7 @@ static noinline int __btrfs_run_delayed_refs(struct btrfs_trans_handle *trans, | |||
2482 | spin_unlock(&locked_ref->lock); | 2459 | spin_unlock(&locked_ref->lock); |
2483 | spin_lock(&delayed_refs->lock); | 2460 | spin_lock(&delayed_refs->lock); |
2484 | spin_lock(&locked_ref->lock); | 2461 | spin_lock(&locked_ref->lock); |
2485 | if (rb_first(&locked_ref->ref_root) || | 2462 | if (!list_empty(&locked_ref->ref_list) || |
2486 | locked_ref->extent_op) { | 2463 | locked_ref->extent_op) { |
2487 | spin_unlock(&locked_ref->lock); | 2464 | spin_unlock(&locked_ref->lock); |
2488 | spin_unlock(&delayed_refs->lock); | 2465 | spin_unlock(&delayed_refs->lock); |
@@ -2496,7 +2473,7 @@ static noinline int __btrfs_run_delayed_refs(struct btrfs_trans_handle *trans, | |||
2496 | } else { | 2473 | } else { |
2497 | actual_count++; | 2474 | actual_count++; |
2498 | ref->in_tree = 0; | 2475 | ref->in_tree = 0; |
2499 | rb_erase(&ref->rb_node, &locked_ref->ref_root); | 2476 | list_del(&ref->list); |
2500 | } | 2477 | } |
2501 | atomic_dec(&delayed_refs->num_entries); | 2478 | atomic_dec(&delayed_refs->num_entries); |
2502 | 2479 | ||
@@ -2905,7 +2882,6 @@ static noinline int check_delayed_ref(struct btrfs_trans_handle *trans, | |||
2905 | struct btrfs_delayed_ref_node *ref; | 2882 | struct btrfs_delayed_ref_node *ref; |
2906 | struct btrfs_delayed_data_ref *data_ref; | 2883 | struct btrfs_delayed_data_ref *data_ref; |
2907 | struct btrfs_delayed_ref_root *delayed_refs; | 2884 | struct btrfs_delayed_ref_root *delayed_refs; |
2908 | struct rb_node *node; | ||
2909 | int ret = 0; | 2885 | int ret = 0; |
2910 | 2886 | ||
2911 | delayed_refs = &trans->transaction->delayed_refs; | 2887 | delayed_refs = &trans->transaction->delayed_refs; |
@@ -2934,11 +2910,7 @@ static noinline int check_delayed_ref(struct btrfs_trans_handle *trans, | |||
2934 | spin_unlock(&delayed_refs->lock); | 2910 | spin_unlock(&delayed_refs->lock); |
2935 | 2911 | ||
2936 | spin_lock(&head->lock); | 2912 | spin_lock(&head->lock); |
2937 | node = rb_first(&head->ref_root); | 2913 | list_for_each_entry(ref, &head->ref_list, list) { |
2938 | while (node) { | ||
2939 | ref = rb_entry(node, struct btrfs_delayed_ref_node, rb_node); | ||
2940 | node = rb_next(node); | ||
2941 | |||
2942 | /* If it's a shared ref we know a cross reference exists */ | 2914 | /* If it's a shared ref we know a cross reference exists */ |
2943 | if (ref->type != BTRFS_EXTENT_DATA_REF_KEY) { | 2915 | if (ref->type != BTRFS_EXTENT_DATA_REF_KEY) { |
2944 | ret = 1; | 2916 | ret = 1; |
@@ -6448,7 +6420,7 @@ static noinline int check_ref_cleanup(struct btrfs_trans_handle *trans, | |||
6448 | goto out_delayed_unlock; | 6420 | goto out_delayed_unlock; |
6449 | 6421 | ||
6450 | spin_lock(&head->lock); | 6422 | spin_lock(&head->lock); |
6451 | if (rb_first(&head->ref_root)) | 6423 | if (!list_empty(&head->ref_list)) |
6452 | goto out; | 6424 | goto out; |
6453 | 6425 | ||
6454 | if (head->extent_op) { | 6426 | if (head->extent_op) { |