diff options
author | Jan Schmidt <list.btrfs@jan-o-sch.net> | 2012-08-17 17:04:41 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@fusionio.com> | 2012-10-08 20:09:02 -0400 |
commit | 5a1d7843ca4b3a9009bea87f85ad33854b910aea (patch) | |
tree | 37622948b54f5123c8b816a21f7f76a202f74710 /fs/btrfs/tree-log.c | |
parent | 0aa4a17d8232e7d8a42763b53bb9943bc0484b18 (diff) |
btrfs: improved readablity for add_inode_ref
Moved part of the code into a sub function and replaced most of the gotos
by ifs, hoping that it will be easier to read now.
Signed-off-by: Jan Schmidt <list.btrfs@jan-o-sch.net>
Signed-off-by: Mark Fasheh <mfasheh@suse.de>
Diffstat (limited to 'fs/btrfs/tree-log.c')
-rw-r--r-- | fs/btrfs/tree-log.c | 178 |
1 files changed, 97 insertions, 81 deletions
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index e0ef92f91d66..15dae589e59f 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c | |||
@@ -785,76 +785,18 @@ out: | |||
785 | return match; | 785 | return match; |
786 | } | 786 | } |
787 | 787 | ||
788 | 788 | static inline int __add_inode_ref(struct btrfs_trans_handle *trans, | |
789 | /* | ||
790 | * replay one inode back reference item found in the log tree. | ||
791 | * eb, slot and key refer to the buffer and key found in the log tree. | ||
792 | * root is the destination we are replaying into, and path is for temp | ||
793 | * use by this function. (it should be released on return). | ||
794 | */ | ||
795 | static noinline int add_inode_ref(struct btrfs_trans_handle *trans, | ||
796 | struct btrfs_root *root, | 789 | struct btrfs_root *root, |
797 | struct btrfs_root *log, | ||
798 | struct btrfs_path *path, | 790 | struct btrfs_path *path, |
799 | struct extent_buffer *eb, int slot, | 791 | struct btrfs_root *log_root, |
800 | struct btrfs_key *key) | 792 | struct inode *dir, struct inode *inode, |
793 | struct btrfs_key *key, | ||
794 | struct extent_buffer *eb, | ||
795 | struct btrfs_inode_ref *ref, | ||
796 | char *name, int namelen, int *search_done) | ||
801 | { | 797 | { |
802 | struct btrfs_inode_ref *ref; | ||
803 | struct btrfs_dir_item *di; | ||
804 | struct inode *dir; | ||
805 | struct inode *inode; | ||
806 | unsigned long ref_ptr; | ||
807 | unsigned long ref_end; | ||
808 | char *name; | ||
809 | int namelen; | ||
810 | int ret; | 798 | int ret; |
811 | int search_done = 0; | 799 | struct btrfs_dir_item *di; |
812 | |||
813 | /* | ||
814 | * it is possible that we didn't log all the parent directories | ||
815 | * for a given inode. If we don't find the dir, just don't | ||
816 | * copy the back ref in. The link count fixup code will take | ||
817 | * care of the rest | ||
818 | */ | ||
819 | dir = read_one_inode(root, key->offset); | ||
820 | if (!dir) | ||
821 | return -ENOENT; | ||
822 | |||
823 | inode = read_one_inode(root, key->objectid); | ||
824 | if (!inode) { | ||
825 | iput(dir); | ||
826 | return -EIO; | ||
827 | } | ||
828 | |||
829 | ref_ptr = btrfs_item_ptr_offset(eb, slot); | ||
830 | ref_end = ref_ptr + btrfs_item_size_nr(eb, slot); | ||
831 | |||
832 | again: | ||
833 | ref = (struct btrfs_inode_ref *)ref_ptr; | ||
834 | |||
835 | namelen = btrfs_inode_ref_name_len(eb, ref); | ||
836 | name = kmalloc(namelen, GFP_NOFS); | ||
837 | BUG_ON(!name); | ||
838 | |||
839 | read_extent_buffer(eb, name, (unsigned long)(ref + 1), namelen); | ||
840 | |||
841 | /* if we already have a perfect match, we're done */ | ||
842 | if (inode_in_dir(root, path, btrfs_ino(dir), btrfs_ino(inode), | ||
843 | btrfs_inode_ref_index(eb, ref), | ||
844 | name, namelen)) { | ||
845 | goto out; | ||
846 | } | ||
847 | |||
848 | /* | ||
849 | * look for a conflicting back reference in the metadata. | ||
850 | * if we find one we have to unlink that name of the file | ||
851 | * before we add our new link. Later on, we overwrite any | ||
852 | * existing back reference, and we don't want to create | ||
853 | * dangling pointers in the directory. | ||
854 | */ | ||
855 | |||
856 | if (search_done) | ||
857 | goto insert; | ||
858 | 800 | ||
859 | ret = btrfs_search_slot(NULL, root, key, path, 0, 0); | 801 | ret = btrfs_search_slot(NULL, root, key, path, 0, 0); |
860 | if (ret == 0) { | 802 | if (ret == 0) { |
@@ -869,7 +811,7 @@ again: | |||
869 | * if so, just jump out, we're done | 811 | * if so, just jump out, we're done |
870 | */ | 812 | */ |
871 | if (key->objectid == key->offset) | 813 | if (key->objectid == key->offset) |
872 | goto out_nowrite; | 814 | return 1; |
873 | 815 | ||
874 | /* check all the names in this back reference to see | 816 | /* check all the names in this back reference to see |
875 | * if they are in the log. if so, we allow them to stay | 817 | * if they are in the log. if so, we allow them to stay |
@@ -888,7 +830,7 @@ again: | |||
888 | (unsigned long)(victim_ref + 1), | 830 | (unsigned long)(victim_ref + 1), |
889 | victim_name_len); | 831 | victim_name_len); |
890 | 832 | ||
891 | if (!backref_in_log(log, key, victim_name, | 833 | if (!backref_in_log(log_root, key, victim_name, |
892 | victim_name_len)) { | 834 | victim_name_len)) { |
893 | btrfs_inc_nlink(inode); | 835 | btrfs_inc_nlink(inode); |
894 | btrfs_release_path(path); | 836 | btrfs_release_path(path); |
@@ -907,7 +849,7 @@ again: | |||
907 | * NOTE: we have searched root tree and checked the | 849 | * NOTE: we have searched root tree and checked the |
908 | * coresponding ref, it does not need to check again. | 850 | * coresponding ref, it does not need to check again. |
909 | */ | 851 | */ |
910 | search_done = 1; | 852 | *search_done = 1; |
911 | } | 853 | } |
912 | btrfs_release_path(path); | 854 | btrfs_release_path(path); |
913 | 855 | ||
@@ -930,25 +872,99 @@ again: | |||
930 | } | 872 | } |
931 | btrfs_release_path(path); | 873 | btrfs_release_path(path); |
932 | 874 | ||
933 | insert: | 875 | return 0; |
934 | /* insert our name */ | 876 | } |
935 | ret = btrfs_add_link(trans, dir, inode, name, namelen, 0, | 877 | |
936 | btrfs_inode_ref_index(eb, ref)); | 878 | /* |
937 | BUG_ON(ret); | 879 | * replay one inode back reference item found in the log tree. |
880 | * eb, slot and key refer to the buffer and key found in the log tree. | ||
881 | * root is the destination we are replaying into, and path is for temp | ||
882 | * use by this function. (it should be released on return). | ||
883 | */ | ||
884 | static noinline int add_inode_ref(struct btrfs_trans_handle *trans, | ||
885 | struct btrfs_root *root, | ||
886 | struct btrfs_root *log, | ||
887 | struct btrfs_path *path, | ||
888 | struct extent_buffer *eb, int slot, | ||
889 | struct btrfs_key *key) | ||
890 | { | ||
891 | struct btrfs_inode_ref *ref; | ||
892 | struct inode *dir; | ||
893 | struct inode *inode; | ||
894 | unsigned long ref_ptr; | ||
895 | unsigned long ref_end; | ||
896 | char *name; | ||
897 | int namelen; | ||
898 | int ret; | ||
899 | int search_done = 0; | ||
900 | |||
901 | /* | ||
902 | * it is possible that we didn't log all the parent directories | ||
903 | * for a given inode. If we don't find the dir, just don't | ||
904 | * copy the back ref in. The link count fixup code will take | ||
905 | * care of the rest | ||
906 | */ | ||
907 | dir = read_one_inode(root, key->offset); | ||
908 | if (!dir) | ||
909 | return -ENOENT; | ||
938 | 910 | ||
939 | btrfs_update_inode(trans, root, inode); | 911 | inode = read_one_inode(root, key->objectid); |
912 | if (!inode) { | ||
913 | iput(dir); | ||
914 | return -EIO; | ||
915 | } | ||
940 | 916 | ||
941 | out: | 917 | ref_ptr = btrfs_item_ptr_offset(eb, slot); |
942 | ref_ptr = (unsigned long)(ref + 1) + namelen; | 918 | ref_end = ref_ptr + btrfs_item_size_nr(eb, slot); |
943 | kfree(name); | 919 | |
944 | if (ref_ptr < ref_end) | 920 | while (ref_ptr < ref_end) { |
945 | goto again; | 921 | ref = (struct btrfs_inode_ref *)ref_ptr; |
922 | |||
923 | namelen = btrfs_inode_ref_name_len(eb, ref); | ||
924 | name = kmalloc(namelen, GFP_NOFS); | ||
925 | BUG_ON(!name); | ||
926 | |||
927 | read_extent_buffer(eb, name, (unsigned long)(ref + 1), namelen); | ||
928 | |||
929 | /* if we already have a perfect match, we're done */ | ||
930 | if (!inode_in_dir(root, path, btrfs_ino(dir), btrfs_ino(inode), | ||
931 | btrfs_inode_ref_index(eb, ref), | ||
932 | name, namelen)) { | ||
933 | /* | ||
934 | * look for a conflicting back reference in the | ||
935 | * metadata. if we find one we have to unlink that name | ||
936 | * of the file before we add our new link. Later on, we | ||
937 | * overwrite any existing back reference, and we don't | ||
938 | * want to create dangling pointers in the directory. | ||
939 | */ | ||
940 | |||
941 | if (!search_done) { | ||
942 | ret = __add_inode_ref(trans, root, path, log, | ||
943 | dir, inode, key, eb, ref, | ||
944 | name, namelen, | ||
945 | &search_done); | ||
946 | if (ret == 1) | ||
947 | goto out; | ||
948 | BUG_ON(ret); | ||
949 | } | ||
950 | |||
951 | /* insert our name */ | ||
952 | ret = btrfs_add_link(trans, dir, inode, name, namelen, | ||
953 | 0, btrfs_inode_ref_index(eb, ref)); | ||
954 | BUG_ON(ret); | ||
955 | |||
956 | btrfs_update_inode(trans, root, inode); | ||
957 | } | ||
958 | |||
959 | ref_ptr = (unsigned long)(ref + 1) + namelen; | ||
960 | kfree(name); | ||
961 | } | ||
946 | 962 | ||
947 | /* finally write the back reference in the inode */ | 963 | /* finally write the back reference in the inode */ |
948 | ret = overwrite_item(trans, root, path, eb, slot, key); | 964 | ret = overwrite_item(trans, root, path, eb, slot, key); |
949 | BUG_ON(ret); | 965 | BUG_ON(ret); |
950 | 966 | ||
951 | out_nowrite: | 967 | out: |
952 | btrfs_release_path(path); | 968 | btrfs_release_path(path); |
953 | iput(dir); | 969 | iput(dir); |
954 | iput(inode); | 970 | iput(inode); |