| .. | .. |
|---|
| 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; |
|---|