.. | .. |
---|
43 | 43 | * back to the delayed ref action. We hold the ref we are changing in the |
---|
44 | 44 | * action so we can account for the history properly, and we record the root we |
---|
45 | 45 | * were called with since it could be different from ref_root. We also store |
---|
46 | | - * stack traces because thats how I roll. |
---|
| 46 | + * stack traces because that's how I roll. |
---|
47 | 47 | */ |
---|
48 | 48 | struct ref_action { |
---|
49 | 49 | int action; |
---|
.. | .. |
---|
56 | 56 | |
---|
57 | 57 | /* |
---|
58 | 58 | * One of these for every block we reference, it holds the roots and references |
---|
59 | | - * to it as well as all of the ref actions that have occured to it. We never |
---|
| 59 | + * to it as well as all of the ref actions that have occurred to it. We never |
---|
60 | 60 | * free it until we unmount the file system in order to make sure re-allocations |
---|
61 | 61 | * are happening properly. |
---|
62 | 62 | */ |
---|
.. | .. |
---|
205 | 205 | #ifdef CONFIG_STACKTRACE |
---|
206 | 206 | static void __save_stack_trace(struct ref_action *ra) |
---|
207 | 207 | { |
---|
208 | | - struct stack_trace stack_trace; |
---|
209 | | - |
---|
210 | | - stack_trace.max_entries = MAX_TRACE; |
---|
211 | | - stack_trace.nr_entries = 0; |
---|
212 | | - stack_trace.entries = ra->trace; |
---|
213 | | - stack_trace.skip = 2; |
---|
214 | | - save_stack_trace(&stack_trace); |
---|
215 | | - ra->trace_len = stack_trace.nr_entries; |
---|
| 208 | + ra->trace_len = stack_trace_save(ra->trace, MAX_TRACE, 2); |
---|
216 | 209 | } |
---|
217 | 210 | |
---|
218 | 211 | static void __print_stack_trace(struct btrfs_fs_info *fs_info, |
---|
219 | 212 | struct ref_action *ra) |
---|
220 | 213 | { |
---|
221 | | - struct stack_trace trace; |
---|
222 | | - |
---|
223 | 214 | if (ra->trace_len == 0) { |
---|
224 | 215 | btrfs_err(fs_info, " ref-verify: no stacktrace"); |
---|
225 | 216 | return; |
---|
226 | 217 | } |
---|
227 | | - trace.nr_entries = ra->trace_len; |
---|
228 | | - trace.entries = ra->trace; |
---|
229 | | - print_stack_trace(&trace, 2); |
---|
| 218 | + stack_trace_print(ra->trace, ra->trace_len, 2); |
---|
230 | 219 | } |
---|
231 | 220 | #else |
---|
232 | 221 | static void inline __save_stack_trace(struct ref_action *ra) |
---|
.. | .. |
---|
522 | 511 | switch (key.type) { |
---|
523 | 512 | case BTRFS_EXTENT_ITEM_KEY: |
---|
524 | 513 | *num_bytes = key.offset; |
---|
| 514 | + fallthrough; |
---|
525 | 515 | case BTRFS_METADATA_ITEM_KEY: |
---|
526 | 516 | *bytenr = key.objectid; |
---|
527 | 517 | ret = process_extent_item(fs_info, path, &key, i, |
---|
.. | .. |
---|
585 | 575 | return -EIO; |
---|
586 | 576 | } |
---|
587 | 577 | btrfs_tree_read_lock(eb); |
---|
588 | | - btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK); |
---|
| 578 | + btrfs_set_lock_blocking_read(eb); |
---|
589 | 579 | path->nodes[level-1] = eb; |
---|
590 | 580 | path->slots[level-1] = 0; |
---|
591 | 581 | path->locks[level-1] = BTRFS_READ_LOCK_BLOCKING; |
---|
.. | .. |
---|
672 | 662 | |
---|
673 | 663 | /* |
---|
674 | 664 | * btrfs_ref_tree_mod: called when we modify a ref for a bytenr |
---|
675 | | - * @root: the root we are making this modification from. |
---|
676 | | - * @bytenr: the bytenr we are modifying. |
---|
677 | | - * @num_bytes: number of bytes. |
---|
678 | | - * @parent: the parent bytenr. |
---|
679 | | - * @ref_root: the original root owner of the bytenr. |
---|
680 | | - * @owner: level in the case of metadata, inode in the case of data. |
---|
681 | | - * @offset: 0 for metadata, file offset for data. |
---|
682 | | - * @action: the action that we are doing, this is the same as the delayed ref |
---|
683 | | - * action. |
---|
684 | 665 | * |
---|
685 | 666 | * This will add an action item to the given bytenr and do sanity checks to make |
---|
686 | 667 | * sure we haven't messed something up. If we are making a new allocation and |
---|
687 | 668 | * this block entry has history we will delete all previous actions as long as |
---|
688 | 669 | * our sanity checks pass as they are no longer needed. |
---|
689 | 670 | */ |
---|
690 | | -int btrfs_ref_tree_mod(struct btrfs_root *root, u64 bytenr, u64 num_bytes, |
---|
691 | | - u64 parent, u64 ref_root, u64 owner, u64 offset, |
---|
692 | | - int action) |
---|
| 671 | +int btrfs_ref_tree_mod(struct btrfs_fs_info *fs_info, |
---|
| 672 | + struct btrfs_ref *generic_ref) |
---|
693 | 673 | { |
---|
694 | | - struct btrfs_fs_info *fs_info = root->fs_info; |
---|
695 | 674 | struct ref_entry *ref = NULL, *exist; |
---|
696 | 675 | struct ref_action *ra = NULL; |
---|
697 | 676 | struct block_entry *be = NULL; |
---|
698 | 677 | struct root_entry *re = NULL; |
---|
| 678 | + int action = generic_ref->action; |
---|
699 | 679 | int ret = 0; |
---|
700 | | - bool metadata = owner < BTRFS_FIRST_FREE_OBJECTID; |
---|
| 680 | + bool metadata; |
---|
| 681 | + u64 bytenr = generic_ref->bytenr; |
---|
| 682 | + u64 num_bytes = generic_ref->len; |
---|
| 683 | + u64 parent = generic_ref->parent; |
---|
| 684 | + u64 ref_root; |
---|
| 685 | + u64 owner; |
---|
| 686 | + u64 offset; |
---|
701 | 687 | |
---|
702 | | - if (!btrfs_test_opt(root->fs_info, REF_VERIFY)) |
---|
| 688 | + if (!btrfs_test_opt(fs_info, REF_VERIFY)) |
---|
703 | 689 | return 0; |
---|
| 690 | + |
---|
| 691 | + if (generic_ref->type == BTRFS_REF_METADATA) { |
---|
| 692 | + ref_root = generic_ref->tree_ref.root; |
---|
| 693 | + owner = generic_ref->tree_ref.level; |
---|
| 694 | + offset = 0; |
---|
| 695 | + } else { |
---|
| 696 | + ref_root = generic_ref->data_ref.ref_root; |
---|
| 697 | + owner = generic_ref->data_ref.ino; |
---|
| 698 | + offset = generic_ref->data_ref.offset; |
---|
| 699 | + } |
---|
| 700 | + metadata = owner < BTRFS_FIRST_FREE_OBJECTID; |
---|
704 | 701 | |
---|
705 | 702 | ref = kzalloc(sizeof(struct ref_entry), GFP_NOFS); |
---|
706 | 703 | ra = kmalloc(sizeof(struct ref_action), GFP_NOFS); |
---|
.. | .. |
---|
734 | 731 | |
---|
735 | 732 | INIT_LIST_HEAD(&ra->list); |
---|
736 | 733 | ra->action = action; |
---|
737 | | - ra->root = root->objectid; |
---|
| 734 | + ra->root = generic_ref->real_root; |
---|
738 | 735 | |
---|
739 | 736 | /* |
---|
740 | 737 | * This is an allocation, preallocate the block_entry in case we haven't |
---|
.. | .. |
---|
747 | 744 | * is and the new root objectid, so let's not treat the passed |
---|
748 | 745 | * in root as if it really has a ref for this bytenr. |
---|
749 | 746 | */ |
---|
750 | | - be = add_block_entry(root->fs_info, bytenr, num_bytes, ref_root); |
---|
| 747 | + be = add_block_entry(fs_info, bytenr, num_bytes, ref_root); |
---|
751 | 748 | if (IS_ERR(be)) { |
---|
752 | 749 | kfree(ref); |
---|
753 | 750 | kfree(ra); |
---|
.. | .. |
---|
792 | 789 | * one we want to lookup below when we modify the |
---|
793 | 790 | * re->num_refs. |
---|
794 | 791 | */ |
---|
795 | | - ref_root = root->objectid; |
---|
796 | | - re->root_objectid = root->objectid; |
---|
| 792 | + ref_root = generic_ref->real_root; |
---|
| 793 | + re->root_objectid = generic_ref->real_root; |
---|
797 | 794 | re->num_refs = 0; |
---|
798 | 795 | } |
---|
799 | 796 | |
---|
800 | | - spin_lock(&root->fs_info->ref_verify_lock); |
---|
801 | | - be = lookup_block_entry(&root->fs_info->block_tree, bytenr); |
---|
| 797 | + spin_lock(&fs_info->ref_verify_lock); |
---|
| 798 | + be = lookup_block_entry(&fs_info->block_tree, bytenr); |
---|
802 | 799 | if (!be) { |
---|
803 | 800 | btrfs_err(fs_info, |
---|
804 | 801 | "trying to do action %d to bytenr %llu num_bytes %llu but there is no existing entry!", |
---|
805 | 802 | action, (unsigned long long)bytenr, |
---|
806 | 803 | (unsigned long long)num_bytes); |
---|
| 804 | + dump_ref_action(fs_info, ra); |
---|
| 805 | + kfree(ref); |
---|
| 806 | + kfree(ra); |
---|
| 807 | + goto out_unlock; |
---|
| 808 | + } else if (be->num_refs == 0) { |
---|
| 809 | + btrfs_err(fs_info, |
---|
| 810 | + "trying to do action %d for a bytenr that has 0 total references", |
---|
| 811 | + action); |
---|
| 812 | + dump_block_entry(fs_info, be); |
---|
807 | 813 | dump_ref_action(fs_info, ra); |
---|
808 | 814 | kfree(ref); |
---|
809 | 815 | kfree(ra); |
---|
.. | .. |
---|
867 | 873 | * This shouldn't happen because we will add our re |
---|
868 | 874 | * above when we lookup the be with !parent, but just in |
---|
869 | 875 | * case catch this case so we don't panic because I |
---|
870 | | - * didn't thik of some other corner case. |
---|
| 876 | + * didn't think of some other corner case. |
---|
871 | 877 | */ |
---|
872 | 878 | btrfs_err(fs_info, "failed to find root %llu for %llu", |
---|
873 | | - root->objectid, be->bytenr); |
---|
| 879 | + generic_ref->real_root, be->bytenr); |
---|
874 | 880 | dump_block_entry(fs_info, be); |
---|
875 | 881 | dump_ref_action(fs_info, ra); |
---|
876 | 882 | kfree(ra); |
---|
.. | .. |
---|
889 | 895 | list_add_tail(&ra->list, &be->actions); |
---|
890 | 896 | ret = 0; |
---|
891 | 897 | out_unlock: |
---|
892 | | - spin_unlock(&root->fs_info->ref_verify_lock); |
---|
| 898 | + spin_unlock(&fs_info->ref_verify_lock); |
---|
893 | 899 | out: |
---|
894 | 900 | if (ret) |
---|
895 | 901 | btrfs_clear_opt(fs_info->mount_opt, REF_VERIFY); |
---|
.. | .. |
---|
995 | 1001 | return -ENOMEM; |
---|
996 | 1002 | |
---|
997 | 1003 | eb = btrfs_read_lock_root_node(fs_info->extent_root); |
---|
998 | | - btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK); |
---|
| 1004 | + btrfs_set_lock_blocking_read(eb); |
---|
999 | 1005 | level = btrfs_header_level(eb); |
---|
1000 | 1006 | path->nodes[level] = eb; |
---|
1001 | 1007 | path->slots[level] = 0; |
---|