diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/tree-log.c | 35 |
1 files changed, 11 insertions, 24 deletions
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index f9425e33e358..c50271ad3157 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c | |||
@@ -799,12 +799,12 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans, | |||
799 | struct inode *dir; | 799 | struct inode *dir; |
800 | int ret; | 800 | int ret; |
801 | struct btrfs_inode_ref *ref; | 801 | struct btrfs_inode_ref *ref; |
802 | struct btrfs_dir_item *di; | ||
803 | struct inode *inode; | 802 | struct inode *inode; |
804 | char *name; | 803 | char *name; |
805 | int namelen; | 804 | int namelen; |
806 | unsigned long ref_ptr; | 805 | unsigned long ref_ptr; |
807 | unsigned long ref_end; | 806 | unsigned long ref_end; |
807 | int search_done = 0; | ||
808 | 808 | ||
809 | /* | 809 | /* |
810 | * it is possible that we didn't log all the parent directories | 810 | * it is possible that we didn't log all the parent directories |
@@ -845,7 +845,10 @@ again: | |||
845 | * existing back reference, and we don't want to create | 845 | * existing back reference, and we don't want to create |
846 | * dangling pointers in the directory. | 846 | * dangling pointers in the directory. |
847 | */ | 847 | */ |
848 | conflict_again: | 848 | |
849 | if (search_done) | ||
850 | goto insert; | ||
851 | |||
849 | ret = btrfs_search_slot(NULL, root, key, path, 0, 0); | 852 | ret = btrfs_search_slot(NULL, root, key, path, 0, 0); |
850 | if (ret == 0) { | 853 | if (ret == 0) { |
851 | char *victim_name; | 854 | char *victim_name; |
@@ -886,37 +889,21 @@ conflict_again: | |||
886 | ret = btrfs_unlink_inode(trans, root, dir, | 889 | ret = btrfs_unlink_inode(trans, root, dir, |
887 | inode, victim_name, | 890 | inode, victim_name, |
888 | victim_name_len); | 891 | victim_name_len); |
889 | kfree(victim_name); | ||
890 | btrfs_release_path(root, path); | ||
891 | goto conflict_again; | ||
892 | } | 892 | } |
893 | kfree(victim_name); | 893 | kfree(victim_name); |
894 | ptr = (unsigned long)(victim_ref + 1) + victim_name_len; | 894 | ptr = (unsigned long)(victim_ref + 1) + victim_name_len; |
895 | } | 895 | } |
896 | BUG_ON(ret); | 896 | BUG_ON(ret); |
897 | } | ||
898 | btrfs_release_path(root, path); | ||
899 | |||
900 | /* look for a conflicting sequence number */ | ||
901 | di = btrfs_lookup_dir_index_item(trans, root, path, dir->i_ino, | ||
902 | btrfs_inode_ref_index(eb, ref), | ||
903 | name, namelen, 0); | ||
904 | if (di && !IS_ERR(di)) { | ||
905 | ret = drop_one_dir_item(trans, root, path, dir, di); | ||
906 | BUG_ON(ret); | ||
907 | } | ||
908 | btrfs_release_path(root, path); | ||
909 | 897 | ||
910 | 898 | /* | |
911 | /* look for a conflicting name */ | 899 | * NOTE: we have searched root tree and checked the |
912 | di = btrfs_lookup_dir_item(trans, root, path, dir->i_ino, | 900 | * coresponding ref, it does not need to check again. |
913 | name, namelen, 0); | 901 | */ |
914 | if (di && !IS_ERR(di)) { | 902 | search_done = 1; |
915 | ret = drop_one_dir_item(trans, root, path, dir, di); | ||
916 | BUG_ON(ret); | ||
917 | } | 903 | } |
918 | btrfs_release_path(root, path); | 904 | btrfs_release_path(root, path); |
919 | 905 | ||
906 | insert: | ||
920 | /* insert our name */ | 907 | /* insert our name */ |
921 | ret = btrfs_add_link(trans, dir, inode, name, namelen, 0, | 908 | ret = btrfs_add_link(trans, dir, inode, name, namelen, 0, |
922 | btrfs_inode_ref_index(eb, ref)); | 909 | btrfs_inode_ref_index(eb, ref)); |