@@ -1041,6 +1041,59 @@ static noinline int backref_in_log(struct btrfs_root *log,
1041
1041
return ret ;
1042
1042
}
1043
1043
1044
+ static int unlink_refs_not_in_log (struct btrfs_trans_handle * trans ,
1045
+ struct btrfs_path * path ,
1046
+ struct btrfs_root * log_root ,
1047
+ struct btrfs_key * search_key ,
1048
+ struct btrfs_inode * dir ,
1049
+ struct btrfs_inode * inode ,
1050
+ u64 parent_objectid )
1051
+ {
1052
+ struct extent_buffer * leaf = path -> nodes [0 ];
1053
+ unsigned long ptr ;
1054
+ unsigned long ptr_end ;
1055
+
1056
+ /*
1057
+ * Check all the names in this back reference to see if thet are in the
1058
+ * log. If so, we allow them to stay otherwise they must be unlinked as
1059
+ * a conflict.
1060
+ */
1061
+ ptr = btrfs_item_ptr_offset (leaf , path -> slots [0 ]);
1062
+ ptr_end = ptr + btrfs_item_size (leaf , path -> slots [0 ]);
1063
+ while (ptr < ptr_end ) {
1064
+ struct fscrypt_str victim_name ;
1065
+ struct btrfs_inode_ref * victim_ref ;
1066
+ int ret ;
1067
+
1068
+ victim_ref = (struct btrfs_inode_ref * )ptr ;
1069
+ ret = read_alloc_one_name (leaf , (victim_ref + 1 ),
1070
+ btrfs_inode_ref_name_len (leaf , victim_ref ),
1071
+ & victim_name );
1072
+ if (ret )
1073
+ return ret ;
1074
+
1075
+ ret = backref_in_log (log_root , search_key , parent_objectid , & victim_name );
1076
+ if (ret ) {
1077
+ kfree (victim_name .name );
1078
+ if (ret < 0 )
1079
+ return ret ;
1080
+ ptr = (unsigned long )(victim_ref + 1 ) + victim_name .len ;
1081
+ continue ;
1082
+ }
1083
+
1084
+ inc_nlink (& inode -> vfs_inode );
1085
+ btrfs_release_path (path );
1086
+
1087
+ ret = unlink_inode_for_log_replay (trans , dir , inode , & victim_name );
1088
+ kfree (victim_name .name );
1089
+ if (ret )
1090
+ return ret ;
1091
+ return - EAGAIN ;
1092
+ }
1093
+
1094
+ return 0 ;
1095
+ }
1096
+
1044
1097
static inline int __add_inode_ref (struct btrfs_trans_handle * trans ,
1045
1098
struct btrfs_root * root ,
1046
1099
struct btrfs_path * path ,
@@ -1065,54 +1118,19 @@ static inline int __add_inode_ref(struct btrfs_trans_handle *trans,
1065
1118
if (ret < 0 ) {
1066
1119
return ret ;
1067
1120
} else if (ret == 0 ) {
1068
- struct btrfs_inode_ref * victim_ref ;
1069
- unsigned long ptr ;
1070
- unsigned long ptr_end ;
1071
-
1072
- leaf = path -> nodes [0 ];
1073
-
1074
- /* are we trying to overwrite a back ref for the root directory
1075
- * if so, just jump out, we're done
1121
+ /*
1122
+ * Are we trying to overwrite a back ref for the root directory?
1123
+ * If so, we're done.
1076
1124
*/
1077
1125
if (search_key .objectid == search_key .offset )
1078
1126
return 1 ;
1079
1127
1080
- /* check all the names in this back reference to see
1081
- * if they are in the log. if so, we allow them to stay
1082
- * otherwise they must be unlinked as a conflict
1083
- */
1084
- ptr = btrfs_item_ptr_offset (leaf , path -> slots [0 ]);
1085
- ptr_end = ptr + btrfs_item_size (leaf , path -> slots [0 ]);
1086
- while (ptr < ptr_end ) {
1087
- struct fscrypt_str victim_name ;
1088
-
1089
- victim_ref = (struct btrfs_inode_ref * )ptr ;
1090
- ret = read_alloc_one_name (leaf , (victim_ref + 1 ),
1091
- btrfs_inode_ref_name_len (leaf , victim_ref ),
1092
- & victim_name );
1093
- if (ret )
1094
- return ret ;
1095
-
1096
- ret = backref_in_log (log_root , & search_key ,
1097
- parent_objectid , & victim_name );
1098
- if (ret < 0 ) {
1099
- kfree (victim_name .name );
1100
- return ret ;
1101
- } else if (!ret ) {
1102
- inc_nlink (& inode -> vfs_inode );
1103
- btrfs_release_path (path );
1104
-
1105
- ret = unlink_inode_for_log_replay (trans , dir , inode ,
1106
- & victim_name );
1107
- kfree (victim_name .name );
1108
- if (ret )
1109
- return ret ;
1110
- goto again ;
1111
- }
1112
- kfree (victim_name .name );
1113
-
1114
- ptr = (unsigned long )(victim_ref + 1 ) + victim_name .len ;
1115
- }
1128
+ ret = unlink_refs_not_in_log (trans , path , log_root , & search_key ,
1129
+ dir , inode , parent_objectid );
1130
+ if (ret == - EAGAIN )
1131
+ goto again ;
1132
+ else if (ret )
1133
+ return ret ;
1116
1134
}
1117
1135
btrfs_release_path (path );
1118
1136
0 commit comments