diff options
Diffstat (limited to 'fs/btrfs/ref-verify.c')
-rw-r--r-- | fs/btrfs/ref-verify.c | 53 |
1 files changed, 30 insertions, 23 deletions
diff --git a/fs/btrfs/ref-verify.c b/fs/btrfs/ref-verify.c index b283d3a6e837..5cec2c6970f2 100644 --- a/fs/btrfs/ref-verify.c +++ b/fs/btrfs/ref-verify.c | |||
@@ -659,36 +659,43 @@ static void dump_block_entry(struct btrfs_fs_info *fs_info, | |||
659 | 659 | ||
660 | /* | 660 | /* |
661 | * 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 |
662 | * @root: the root we are making this modification from. | ||
663 | * @bytenr: the bytenr we are modifying. | ||
664 | * @num_bytes: number of bytes. | ||
665 | * @parent: the parent bytenr. | ||
666 | * @ref_root: the original root owner of the bytenr. | ||
667 | * @owner: level in the case of metadata, inode in the case of data. | ||
668 | * @offset: 0 for metadata, file offset for data. | ||
669 | * @action: the action that we are doing, this is the same as the delayed ref | ||
670 | * action. | ||
671 | * | 662 | * |
672 | * 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 |
673 | * 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 |
674 | * 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 |
675 | * our sanity checks pass as they are no longer needed. | 666 | * our sanity checks pass as they are no longer needed. |
676 | */ | 667 | */ |
677 | 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, |
678 | u64 parent, u64 ref_root, u64 owner, u64 offset, | 669 | struct btrfs_ref *generic_ref) |
679 | int action) | ||
680 | { | 670 | { |
681 | struct btrfs_fs_info *fs_info = root->fs_info; | ||
682 | struct ref_entry *ref = NULL, *exist; | 671 | struct ref_entry *ref = NULL, *exist; |
683 | struct ref_action *ra = NULL; | 672 | struct ref_action *ra = NULL; |
684 | struct block_entry *be = NULL; | 673 | struct block_entry *be = NULL; |
685 | struct root_entry *re = NULL; | 674 | struct root_entry *re = NULL; |
675 | int action = generic_ref->action; | ||
686 | int ret = 0; | 676 | int ret = 0; |
687 | 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; | ||
688 | 684 | ||
689 | if (!btrfs_test_opt(root->fs_info, REF_VERIFY)) | 685 | if (!btrfs_test_opt(fs_info, REF_VERIFY)) |
690 | return 0; | 686 | return 0; |
691 | 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 | |||
692 | ref = kzalloc(sizeof(struct ref_entry), GFP_NOFS); | 699 | ref = kzalloc(sizeof(struct ref_entry), GFP_NOFS); |
693 | ra = kmalloc(sizeof(struct ref_action), GFP_NOFS); | 700 | ra = kmalloc(sizeof(struct ref_action), GFP_NOFS); |
694 | if (!ra || !ref) { | 701 | if (!ra || !ref) { |
@@ -721,7 +728,7 @@ int btrfs_ref_tree_mod(struct btrfs_root *root, u64 bytenr, u64 num_bytes, | |||
721 | 728 | ||
722 | INIT_LIST_HEAD(&ra->list); | 729 | INIT_LIST_HEAD(&ra->list); |
723 | ra->action = action; | 730 | ra->action = action; |
724 | ra->root = root->root_key.objectid; | 731 | ra->root = generic_ref->real_root; |
725 | 732 | ||
726 | /* | 733 | /* |
727 | * 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 |
@@ -734,7 +741,7 @@ int btrfs_ref_tree_mod(struct btrfs_root *root, u64 bytenr, u64 num_bytes, | |||
734 | * 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 |
735 | * 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. |
736 | */ | 743 | */ |
737 | be = add_block_entry(root->fs_info, bytenr, num_bytes, ref_root); | 744 | be = add_block_entry(fs_info, bytenr, num_bytes, ref_root); |
738 | if (IS_ERR(be)) { | 745 | if (IS_ERR(be)) { |
739 | kfree(ra); | 746 | kfree(ra); |
740 | ret = PTR_ERR(be); | 747 | ret = PTR_ERR(be); |
@@ -776,13 +783,13 @@ int btrfs_ref_tree_mod(struct btrfs_root *root, u64 bytenr, u64 num_bytes, | |||
776 | * one we want to lookup below when we modify the | 783 | * one we want to lookup below when we modify the |
777 | * re->num_refs. | 784 | * re->num_refs. |
778 | */ | 785 | */ |
779 | ref_root = root->root_key.objectid; | 786 | ref_root = generic_ref->real_root; |
780 | re->root_objectid = root->root_key.objectid; | 787 | re->root_objectid = generic_ref->real_root; |
781 | re->num_refs = 0; | 788 | re->num_refs = 0; |
782 | } | 789 | } |
783 | 790 | ||
784 | spin_lock(&root->fs_info->ref_verify_lock); | 791 | spin_lock(&fs_info->ref_verify_lock); |
785 | be = lookup_block_entry(&root->fs_info->block_tree, bytenr); | 792 | be = lookup_block_entry(&fs_info->block_tree, bytenr); |
786 | if (!be) { | 793 | if (!be) { |
787 | btrfs_err(fs_info, | 794 | btrfs_err(fs_info, |
788 | "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!", |
@@ -851,7 +858,7 @@ int btrfs_ref_tree_mod(struct btrfs_root *root, u64 bytenr, u64 num_bytes, | |||
851 | * didn't think of some other corner case. | 858 | * didn't think of some other corner case. |
852 | */ | 859 | */ |
853 | btrfs_err(fs_info, "failed to find root %llu for %llu", | 860 | btrfs_err(fs_info, "failed to find root %llu for %llu", |
854 | root->root_key.objectid, be->bytenr); | 861 | generic_ref->real_root, be->bytenr); |
855 | dump_block_entry(fs_info, be); | 862 | dump_block_entry(fs_info, be); |
856 | dump_ref_action(fs_info, ra); | 863 | dump_ref_action(fs_info, ra); |
857 | kfree(ra); | 864 | kfree(ra); |
@@ -870,7 +877,7 @@ int btrfs_ref_tree_mod(struct btrfs_root *root, u64 bytenr, u64 num_bytes, | |||
870 | list_add_tail(&ra->list, &be->actions); | 877 | list_add_tail(&ra->list, &be->actions); |
871 | ret = 0; | 878 | ret = 0; |
872 | out_unlock: | 879 | out_unlock: |
873 | spin_unlock(&root->fs_info->ref_verify_lock); | 880 | spin_unlock(&fs_info->ref_verify_lock); |
874 | out: | 881 | out: |
875 | if (ret) | 882 | if (ret) |
876 | btrfs_clear_opt(fs_info->mount_opt, REF_VERIFY); | 883 | btrfs_clear_opt(fs_info->mount_opt, REF_VERIFY); |