hc
2024-05-10 cde9070d9970eef1f7ec2360586c802a16230ad8
kernel/fs/btrfs/uuid-tree.c
....@@ -121,12 +121,12 @@
121121 * An item with that type already exists.
122122 * Extend the item and store the new subid at the end.
123123 */
124
- btrfs_extend_item(fs_info, path, sizeof(subid_le));
124
+ btrfs_extend_item(path, sizeof(subid_le));
125125 eb = path->nodes[0];
126126 slot = path->slots[0];
127127 offset = btrfs_item_ptr_offset(eb, slot);
128128 offset += btrfs_item_size_nr(eb, slot) - sizeof(subid_le);
129
- } else if (ret < 0) {
129
+ } else {
130130 btrfs_warn(fs_info,
131131 "insert uuid item failed %d (0x%016llx, 0x%016llx) type %u!",
132132 ret, (unsigned long long)key.objectid,
....@@ -219,7 +219,7 @@
219219 move_src = offset + sizeof(subid);
220220 move_len = item_size - (move_src - btrfs_item_ptr_offset(eb, slot));
221221 memmove_extent_buffer(eb, move_dst, move_src, move_len);
222
- btrfs_truncate_item(fs_info, path, item_size - sizeof(subid), 1);
222
+ btrfs_truncate_item(path, item_size - sizeof(subid), 1);
223223
224224 out:
225225 btrfs_free_path(path);
....@@ -246,9 +246,49 @@
246246 return ret;
247247 }
248248
249
-int btrfs_uuid_tree_iterate(struct btrfs_fs_info *fs_info,
250
- int (*check_func)(struct btrfs_fs_info *, u8 *, u8,
251
- u64))
249
+/*
250
+ * Check if there's an matching subvolume for given UUID
251
+ *
252
+ * Return:
253
+ * 0 check succeeded, the entry is not outdated
254
+ * > 0 if the check failed, the caller should remove the entry
255
+ * < 0 if an error occurred
256
+ */
257
+static int btrfs_check_uuid_tree_entry(struct btrfs_fs_info *fs_info,
258
+ u8 *uuid, u8 type, u64 subvolid)
259
+{
260
+ int ret = 0;
261
+ struct btrfs_root *subvol_root;
262
+
263
+ if (type != BTRFS_UUID_KEY_SUBVOL &&
264
+ type != BTRFS_UUID_KEY_RECEIVED_SUBVOL)
265
+ goto out;
266
+
267
+ subvol_root = btrfs_get_fs_root(fs_info, subvolid, true);
268
+ if (IS_ERR(subvol_root)) {
269
+ ret = PTR_ERR(subvol_root);
270
+ if (ret == -ENOENT)
271
+ ret = 1;
272
+ goto out;
273
+ }
274
+
275
+ switch (type) {
276
+ case BTRFS_UUID_KEY_SUBVOL:
277
+ if (memcmp(uuid, subvol_root->root_item.uuid, BTRFS_UUID_SIZE))
278
+ ret = 1;
279
+ break;
280
+ case BTRFS_UUID_KEY_RECEIVED_SUBVOL:
281
+ if (memcmp(uuid, subvol_root->root_item.received_uuid,
282
+ BTRFS_UUID_SIZE))
283
+ ret = 1;
284
+ break;
285
+ }
286
+ btrfs_put_root(subvol_root);
287
+out:
288
+ return ret;
289
+}
290
+
291
+int btrfs_uuid_tree_iterate(struct btrfs_fs_info *fs_info)
252292 {
253293 struct btrfs_root *root = fs_info->uuid_root;
254294 struct btrfs_key key;
....@@ -278,6 +318,10 @@
278318 }
279319
280320 while (1) {
321
+ if (btrfs_fs_closing(fs_info)) {
322
+ ret = -EINTR;
323
+ goto out;
324
+ }
281325 cond_resched();
282326 leaf = path->nodes[0];
283327 slot = path->slots[0];
....@@ -305,7 +349,8 @@
305349 read_extent_buffer(leaf, &subid_le, offset,
306350 sizeof(subid_le));
307351 subid_cpu = le64_to_cpu(subid_le);
308
- ret = check_func(fs_info, uuid, key.type, subid_cpu);
352
+ ret = btrfs_check_uuid_tree_entry(fs_info, uuid,
353
+ key.type, subid_cpu);
309354 if (ret < 0)
310355 goto out;
311356 if (ret > 0) {