diff options
Diffstat (limited to 'fs/btrfs/ref-verify.c')
-rw-r--r-- | fs/btrfs/ref-verify.c | 68 |
1 files changed, 32 insertions, 36 deletions
diff --git a/fs/btrfs/ref-verify.c b/fs/btrfs/ref-verify.c index d09b6cdb785a..5cec2c6970f2 100644 --- a/fs/btrfs/ref-verify.c +++ b/fs/btrfs/ref-verify.c | |||
@@ -205,28 +205,17 @@ static struct root_entry *lookup_root_entry(struct rb_root *root, u64 objectid) | |||
205 | #ifdef CONFIG_STACKTRACE | 205 | #ifdef CONFIG_STACKTRACE |
206 | static void __save_stack_trace(struct ref_action *ra) | 206 | static void __save_stack_trace(struct ref_action *ra) |
207 | { | 207 | { |
208 | struct stack_trace stack_trace; | 208 | ra->trace_len = stack_trace_save(ra->trace, MAX_TRACE, 2); |
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; | ||
216 | } | 209 | } |
217 | 210 | ||
218 | static void __print_stack_trace(struct btrfs_fs_info *fs_info, | 211 | static void __print_stack_trace(struct btrfs_fs_info *fs_info, |
219 | struct ref_action *ra) | 212 | struct ref_action *ra) |
220 | { | 213 | { |
221 | struct stack_trace trace; | ||
222 | |||
223 | if (ra->trace_len == 0) { | 214 | if (ra->trace_len == 0) { |
224 | btrfs_err(fs_info, " ref-verify: no stacktrace"); | 215 | btrfs_err(fs_info, " ref-verify: no stacktrace"); |
225 | return; | 216 | return; |
226 | } | 217 | } |
227 | trace.nr_entries = ra->trace_len; | 218 | stack_trace_print(ra->trace, ra->trace_len, 2); |
228 | trace.entries = ra->trace; | ||
229 | print_stack_trace(&trace, 2); | ||
230 | } | 219 | } |
231 | #else | 220 | #else |
232 | static void inline __save_stack_trace(struct ref_action *ra) | 221 | static void inline __save_stack_trace(struct ref_action *ra) |
@@ -670,36 +659,43 @@ static void dump_block_entry(struct btrfs_fs_info *fs_info, | |||
670 | 659 | ||
671 | /* | 660 | /* |
672 | * btrfs_ref_tree_mod: called when we modify a ref for a bytenr | 661 | * btrfs_ref_tree_mod: called when we modify a ref for a bytenr |
673 | * @root: the root we are making this modification from. | ||
674 | * @bytenr: the bytenr we are modifying. | ||
675 | * @num_bytes: number of bytes. | ||
676 | * @parent: the parent bytenr. | ||
677 | * @ref_root: the original root owner of the bytenr. | ||
678 | * @owner: level in the case of metadata, inode in the case of data. | ||
679 | * @offset: 0 for metadata, file offset for data. | ||
680 | * @action: the action that we are doing, this is the same as the delayed ref | ||
681 | * action. | ||
682 | * | 662 | * |
683 | * This will add an action item to the given bytenr and do sanity checks to make | 663 | * This will add an action item to the given bytenr and do sanity checks to make |
684 | * sure we haven't messed something up. If we are making a new allocation and | 664 | * sure we haven't messed something up. If we are making a new allocation and |
685 | * this block entry has history we will delete all previous actions as long as | 665 | * this block entry has history we will delete all previous actions as long as |
686 | * our sanity checks pass as they are no longer needed. | 666 | * our sanity checks pass as they are no longer needed. |
687 | */ | 667 | */ |
688 | int btrfs_ref_tree_mod(struct btrfs_root *root, u64 bytenr, u64 num_bytes, | 668 | int btrfs_ref_tree_mod(struct btrfs_fs_info *fs_info, |
689 | u64 parent, u64 ref_root, u64 owner, u64 offset, | 669 | struct btrfs_ref *generic_ref) |
690 | int action) | ||
691 | { | 670 | { |
692 | struct btrfs_fs_info *fs_info = root->fs_info; | ||
693 | struct ref_entry *ref = NULL, *exist; | 671 | struct ref_entry *ref = NULL, *exist; |
694 | struct ref_action *ra = NULL; | 672 | struct ref_action *ra = NULL; |
695 | struct block_entry *be = NULL; | 673 | struct block_entry *be = NULL; |
696 | struct root_entry *re = NULL; | 674 | struct root_entry *re = NULL; |
675 | int action = generic_ref->action; | ||
697 | int ret = 0; | 676 | int ret = 0; |
698 | bool metadata = owner < BTRFS_FIRST_FREE_OBJECTID; | 677 | bool metadata; |
678 | u64 bytenr = generic_ref->bytenr; | ||
679 | u64 num_bytes = generic_ref->len; | ||
680 | u64 parent = generic_ref->parent; | ||
681 | u64 ref_root; | ||
682 | u64 owner; | ||
683 | u64 offset; | ||
699 | 684 | ||
700 | if (!btrfs_test_opt(root->fs_info, REF_VERIFY)) | 685 | if (!btrfs_test_opt(fs_info, REF_VERIFY)) |
701 | return 0; | 686 | return 0; |
702 | 687 | ||
688 | if (generic_ref->type == BTRFS_REF_METADATA) { | ||
689 | ref_root = generic_ref->tree_ref.root; | ||
690 | owner = generic_ref->tree_ref.level; | ||
691 | offset = 0; | ||
692 | } else { | ||
693 | ref_root = generic_ref->data_ref.ref_root; | ||
694 | owner = generic_ref->data_ref.ino; | ||
695 | offset = generic_ref->data_ref.offset; | ||
696 | } | ||
697 | metadata = owner < BTRFS_FIRST_FREE_OBJECTID; | ||
698 | |||
703 | ref = kzalloc(sizeof(struct ref_entry), GFP_NOFS); | 699 | ref = kzalloc(sizeof(struct ref_entry), GFP_NOFS); |
704 | ra = kmalloc(sizeof(struct ref_action), GFP_NOFS); | 700 | ra = kmalloc(sizeof(struct ref_action), GFP_NOFS); |
705 | if (!ra || !ref) { | 701 | if (!ra || !ref) { |
@@ -732,7 +728,7 @@ int btrfs_ref_tree_mod(struct btrfs_root *root, u64 bytenr, u64 num_bytes, | |||
732 | 728 | ||
733 | INIT_LIST_HEAD(&ra->list); | 729 | INIT_LIST_HEAD(&ra->list); |
734 | ra->action = action; | 730 | ra->action = action; |
735 | ra->root = root->root_key.objectid; | 731 | ra->root = generic_ref->real_root; |
736 | 732 | ||
737 | /* | 733 | /* |
738 | * This is an allocation, preallocate the block_entry in case we haven't | 734 | * This is an allocation, preallocate the block_entry in case we haven't |
@@ -745,7 +741,7 @@ int btrfs_ref_tree_mod(struct btrfs_root *root, u64 bytenr, u64 num_bytes, | |||
745 | * is and the new root objectid, so let's not treat the passed | 741 | * is and the new root objectid, so let's not treat the passed |
746 | * in root as if it really has a ref for this bytenr. | 742 | * in root as if it really has a ref for this bytenr. |
747 | */ | 743 | */ |
748 | be = add_block_entry(root->fs_info, bytenr, num_bytes, ref_root); | 744 | be = add_block_entry(fs_info, bytenr, num_bytes, ref_root); |
749 | if (IS_ERR(be)) { | 745 | if (IS_ERR(be)) { |
750 | kfree(ra); | 746 | kfree(ra); |
751 | ret = PTR_ERR(be); | 747 | ret = PTR_ERR(be); |
@@ -787,13 +783,13 @@ int btrfs_ref_tree_mod(struct btrfs_root *root, u64 bytenr, u64 num_bytes, | |||
787 | * one we want to lookup below when we modify the | 783 | * one we want to lookup below when we modify the |
788 | * re->num_refs. | 784 | * re->num_refs. |
789 | */ | 785 | */ |
790 | ref_root = root->root_key.objectid; | 786 | ref_root = generic_ref->real_root; |
791 | re->root_objectid = root->root_key.objectid; | 787 | re->root_objectid = generic_ref->real_root; |
792 | re->num_refs = 0; | 788 | re->num_refs = 0; |
793 | } | 789 | } |
794 | 790 | ||
795 | spin_lock(&root->fs_info->ref_verify_lock); | 791 | spin_lock(&fs_info->ref_verify_lock); |
796 | be = lookup_block_entry(&root->fs_info->block_tree, bytenr); | 792 | be = lookup_block_entry(&fs_info->block_tree, bytenr); |
797 | if (!be) { | 793 | if (!be) { |
798 | btrfs_err(fs_info, | 794 | btrfs_err(fs_info, |
799 | "trying to do action %d to bytenr %llu num_bytes %llu but there is no existing entry!", | 795 | "trying to do action %d to bytenr %llu num_bytes %llu but there is no existing entry!", |
@@ -862,7 +858,7 @@ int btrfs_ref_tree_mod(struct btrfs_root *root, u64 bytenr, u64 num_bytes, | |||
862 | * didn't think of some other corner case. | 858 | * didn't think of some other corner case. |
863 | */ | 859 | */ |
864 | btrfs_err(fs_info, "failed to find root %llu for %llu", | 860 | btrfs_err(fs_info, "failed to find root %llu for %llu", |
865 | root->root_key.objectid, be->bytenr); | 861 | generic_ref->real_root, be->bytenr); |
866 | dump_block_entry(fs_info, be); | 862 | dump_block_entry(fs_info, be); |
867 | dump_ref_action(fs_info, ra); | 863 | dump_ref_action(fs_info, ra); |
868 | kfree(ra); | 864 | kfree(ra); |
@@ -881,7 +877,7 @@ int btrfs_ref_tree_mod(struct btrfs_root *root, u64 bytenr, u64 num_bytes, | |||
881 | list_add_tail(&ra->list, &be->actions); | 877 | list_add_tail(&ra->list, &be->actions); |
882 | ret = 0; | 878 | ret = 0; |
883 | out_unlock: | 879 | out_unlock: |
884 | spin_unlock(&root->fs_info->ref_verify_lock); | 880 | spin_unlock(&fs_info->ref_verify_lock); |
885 | out: | 881 | out: |
886 | if (ret) | 882 | if (ret) |
887 | btrfs_clear_opt(fs_info->mount_opt, REF_VERIFY); | 883 | btrfs_clear_opt(fs_info->mount_opt, REF_VERIFY); |