@@ -1094,6 +1094,73 @@ static int unlink_refs_not_in_log(struct btrfs_trans_handle *trans,
1094
1094
return 0 ;
1095
1095
}
1096
1096
1097
+ static int unlink_extrefs_not_in_log (struct btrfs_trans_handle * trans ,
1098
+ struct btrfs_path * path ,
1099
+ struct btrfs_root * root ,
1100
+ struct btrfs_root * log_root ,
1101
+ struct btrfs_key * search_key ,
1102
+ struct btrfs_inode * inode ,
1103
+ u64 inode_objectid ,
1104
+ u64 parent_objectid )
1105
+ {
1106
+ struct extent_buffer * leaf = path -> nodes [0 ];
1107
+ const unsigned long base = btrfs_item_ptr_offset (leaf , path -> slots [0 ]);
1108
+ const u32 item_size = btrfs_item_size (leaf , path -> slots [0 ]);
1109
+ u32 cur_offset = 0 ;
1110
+
1111
+ while (cur_offset < item_size ) {
1112
+ struct btrfs_inode_extref * extref ;
1113
+ struct btrfs_inode * victim_parent ;
1114
+ struct fscrypt_str victim_name ;
1115
+ int ret ;
1116
+
1117
+ extref = (struct btrfs_inode_extref * )(base + cur_offset );
1118
+ victim_name .len = btrfs_inode_extref_name_len (leaf , extref );
1119
+
1120
+ if (btrfs_inode_extref_parent (leaf , extref ) != parent_objectid )
1121
+ goto next ;
1122
+
1123
+ ret = read_alloc_one_name (leaf , & extref -> name , victim_name .len ,
1124
+ & victim_name );
1125
+ if (ret )
1126
+ return ret ;
1127
+
1128
+ search_key -> objectid = inode_objectid ;
1129
+ search_key -> type = BTRFS_INODE_EXTREF_KEY ;
1130
+ search_key -> offset = btrfs_extref_hash (parent_objectid ,
1131
+ victim_name .name ,
1132
+ victim_name .len );
1133
+ ret = backref_in_log (log_root , search_key , parent_objectid , & victim_name );
1134
+ if (ret ) {
1135
+ kfree (victim_name .name );
1136
+ if (ret < 0 )
1137
+ return ret ;
1138
+ next :
1139
+ cur_offset += victim_name .len + sizeof (* extref );
1140
+ continue ;
1141
+ }
1142
+
1143
+ victim_parent = btrfs_iget_logging (parent_objectid , root );
1144
+ if (IS_ERR (victim_parent )) {
1145
+ kfree (victim_name .name );
1146
+ return PTR_ERR (victim_parent );
1147
+ }
1148
+
1149
+ inc_nlink (& inode -> vfs_inode );
1150
+ btrfs_release_path (path );
1151
+
1152
+ ret = unlink_inode_for_log_replay (trans , victim_parent , inode ,
1153
+ & victim_name );
1154
+ iput (& victim_parent -> vfs_inode );
1155
+ kfree (victim_name .name );
1156
+ if (ret )
1157
+ return ret ;
1158
+ return - EAGAIN ;
1159
+ }
1160
+
1161
+ return 0 ;
1162
+ }
1163
+
1097
1164
static inline int __add_inode_ref (struct btrfs_trans_handle * trans ,
1098
1165
struct btrfs_root * root ,
1099
1166
struct btrfs_path * path ,
@@ -1104,7 +1171,6 @@ static inline int __add_inode_ref(struct btrfs_trans_handle *trans,
1104
1171
u64 ref_index , struct fscrypt_str * name )
1105
1172
{
1106
1173
int ret ;
1107
- struct extent_buffer * leaf ;
1108
1174
struct btrfs_dir_item * di ;
1109
1175
struct btrfs_key search_key ;
1110
1176
struct btrfs_inode_extref * extref ;
@@ -1139,62 +1205,13 @@ static inline int __add_inode_ref(struct btrfs_trans_handle *trans,
1139
1205
if (IS_ERR (extref )) {
1140
1206
return PTR_ERR (extref );
1141
1207
} else if (extref ) {
1142
- u32 item_size ;
1143
- u32 cur_offset = 0 ;
1144
- unsigned long base ;
1145
- struct btrfs_inode * victim_parent ;
1146
-
1147
- leaf = path -> nodes [0 ];
1148
-
1149
- item_size = btrfs_item_size (leaf , path -> slots [0 ]);
1150
- base = btrfs_item_ptr_offset (leaf , path -> slots [0 ]);
1151
-
1152
- while (cur_offset < item_size ) {
1153
- struct fscrypt_str victim_name ;
1154
-
1155
- extref = (struct btrfs_inode_extref * )(base + cur_offset );
1156
- victim_name .len = btrfs_inode_extref_name_len (leaf , extref );
1157
-
1158
- if (btrfs_inode_extref_parent (leaf , extref ) != parent_objectid )
1159
- goto next ;
1160
-
1161
- ret = read_alloc_one_name (leaf , & extref -> name ,
1162
- victim_name .len , & victim_name );
1163
- if (ret )
1164
- return ret ;
1165
-
1166
- search_key .objectid = inode_objectid ;
1167
- search_key .type = BTRFS_INODE_EXTREF_KEY ;
1168
- search_key .offset = btrfs_extref_hash (parent_objectid ,
1169
- victim_name .name ,
1170
- victim_name .len );
1171
- ret = backref_in_log (log_root , & search_key ,
1172
- parent_objectid , & victim_name );
1173
- if (ret < 0 ) {
1174
- kfree (victim_name .name );
1175
- return ret ;
1176
- } else if (!ret ) {
1177
- victim_parent = btrfs_iget_logging (parent_objectid , root );
1178
- if (IS_ERR (victim_parent )) {
1179
- ret = PTR_ERR (victim_parent );
1180
- } else {
1181
- inc_nlink (& inode -> vfs_inode );
1182
- btrfs_release_path (path );
1183
-
1184
- ret = unlink_inode_for_log_replay (trans ,
1185
- victim_parent ,
1186
- inode , & victim_name );
1187
- iput (& victim_parent -> vfs_inode );
1188
- }
1189
- kfree (victim_name .name );
1190
- if (ret )
1191
- return ret ;
1192
- goto again ;
1193
- }
1194
- kfree (victim_name .name );
1195
- next :
1196
- cur_offset += victim_name .len + sizeof (* extref );
1197
- }
1208
+ ret = unlink_extrefs_not_in_log (trans , path , root , log_root ,
1209
+ & search_key , inode ,
1210
+ inode_objectid , parent_objectid );
1211
+ if (ret == - EAGAIN )
1212
+ goto again ;
1213
+ else if (ret )
1214
+ return ret ;
1198
1215
}
1199
1216
btrfs_release_path (path );
1200
1217
0 commit comments