Commit 8445f61cad927b6efffdd4e042a51a783ff8853f
1 parent
5d9e75c41d
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
Btrfs: use the tree modification log for backref resolving
This enables backref resolving on life trees while they are changing. This is a prerequisite for quota groups and just nice to have for everything else. Signed-off-by: Jan Schmidt <list.btrfs@jan-o-sch.net>
Showing 2 changed files with 29 additions and 17 deletions Side-by-side Diff
fs/btrfs/backref.c
... | ... | @@ -231,6 +231,7 @@ |
231 | 231 | */ |
232 | 232 | static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info, |
233 | 233 | int search_commit_root, |
234 | + u64 time_seq, | |
234 | 235 | struct __prelim_ref *ref, |
235 | 236 | struct ulist *parents, |
236 | 237 | const u64 *extent_item_pos) |
... | ... | @@ -266,7 +267,7 @@ |
266 | 267 | goto out; |
267 | 268 | |
268 | 269 | path->lowest_level = level; |
269 | - ret = btrfs_search_slot(NULL, root, &ref->key_for_search, path, 0, 0); | |
270 | + ret = btrfs_search_old_slot(root, &ref->key_for_search, path, time_seq); | |
270 | 271 | pr_debug("search slot in root %llu (level %d, ref count %d) returned " |
271 | 272 | "%d for key (%llu %u %llu)\n", |
272 | 273 | (unsigned long long)ref->root_id, level, ref->count, ret, |
... | ... | @@ -305,7 +306,7 @@ |
305 | 306 | * resolve all indirect backrefs from the list |
306 | 307 | */ |
307 | 308 | static int __resolve_indirect_refs(struct btrfs_fs_info *fs_info, |
308 | - int search_commit_root, | |
309 | + int search_commit_root, u64 time_seq, | |
309 | 310 | struct list_head *head, |
310 | 311 | const u64 *extent_item_pos) |
311 | 312 | { |
... | ... | @@ -333,7 +334,8 @@ |
333 | 334 | if (ref->count == 0) |
334 | 335 | continue; |
335 | 336 | err = __resolve_indirect_ref(fs_info, search_commit_root, |
336 | - ref, parents, extent_item_pos); | |
337 | + time_seq, ref, parents, | |
338 | + extent_item_pos); | |
337 | 339 | if (err) { |
338 | 340 | if (ret == 0) |
339 | 341 | ret = err; |
... | ... | @@ -750,7 +752,8 @@ |
750 | 752 | */ |
751 | 753 | static int find_parent_nodes(struct btrfs_trans_handle *trans, |
752 | 754 | struct btrfs_fs_info *fs_info, u64 bytenr, |
753 | - u64 seq, struct ulist *refs, struct ulist *roots, | |
755 | + u64 delayed_ref_seq, u64 time_seq, | |
756 | + struct ulist *refs, struct ulist *roots, | |
754 | 757 | const u64 *extent_item_pos) |
755 | 758 | { |
756 | 759 | struct btrfs_key key; |
... | ... | @@ -813,7 +816,8 @@ |
813 | 816 | btrfs_put_delayed_ref(&head->node); |
814 | 817 | goto again; |
815 | 818 | } |
816 | - ret = __add_delayed_refs(head, seq, &prefs_delayed); | |
819 | + ret = __add_delayed_refs(head, delayed_ref_seq, | |
820 | + &prefs_delayed); | |
817 | 821 | if (ret) { |
818 | 822 | spin_unlock(&delayed_refs->lock); |
819 | 823 | goto out; |
... | ... | @@ -854,8 +858,8 @@ |
854 | 858 | if (ret) |
855 | 859 | goto out; |
856 | 860 | |
857 | - ret = __resolve_indirect_refs(fs_info, search_commit_root, &prefs, | |
858 | - extent_item_pos); | |
861 | + ret = __resolve_indirect_refs(fs_info, search_commit_root, time_seq, | |
862 | + &prefs, extent_item_pos); | |
859 | 863 | if (ret) |
860 | 864 | goto out; |
861 | 865 | |
... | ... | @@ -945,7 +949,8 @@ |
945 | 949 | */ |
946 | 950 | static int btrfs_find_all_leafs(struct btrfs_trans_handle *trans, |
947 | 951 | struct btrfs_fs_info *fs_info, u64 bytenr, |
948 | - u64 seq, struct ulist **leafs, | |
952 | + u64 delayed_ref_seq, u64 time_seq, | |
953 | + struct ulist **leafs, | |
949 | 954 | const u64 *extent_item_pos) |
950 | 955 | { |
951 | 956 | struct ulist *tmp; |
... | ... | @@ -960,8 +965,8 @@ |
960 | 965 | return -ENOMEM; |
961 | 966 | } |
962 | 967 | |
963 | - ret = find_parent_nodes(trans, fs_info, bytenr, seq, *leafs, tmp, | |
964 | - extent_item_pos); | |
968 | + ret = find_parent_nodes(trans, fs_info, bytenr, delayed_ref_seq, | |
969 | + time_seq, *leafs, tmp, extent_item_pos); | |
965 | 970 | ulist_free(tmp); |
966 | 971 | |
967 | 972 | if (ret < 0 && ret != -ENOENT) { |
... | ... | @@ -987,7 +992,8 @@ |
987 | 992 | */ |
988 | 993 | int btrfs_find_all_roots(struct btrfs_trans_handle *trans, |
989 | 994 | struct btrfs_fs_info *fs_info, u64 bytenr, |
990 | - u64 seq, struct ulist **roots) | |
995 | + u64 delayed_ref_seq, u64 time_seq, | |
996 | + struct ulist **roots) | |
991 | 997 | { |
992 | 998 | struct ulist *tmp; |
993 | 999 | struct ulist_node *node = NULL; |
... | ... | @@ -1005,8 +1011,8 @@ |
1005 | 1011 | |
1006 | 1012 | ULIST_ITER_INIT(&uiter); |
1007 | 1013 | while (1) { |
1008 | - ret = find_parent_nodes(trans, fs_info, bytenr, seq, | |
1009 | - tmp, *roots, NULL); | |
1014 | + ret = find_parent_nodes(trans, fs_info, bytenr, delayed_ref_seq, | |
1015 | + time_seq, tmp, *roots, NULL); | |
1010 | 1016 | if (ret < 0 && ret != -ENOENT) { |
1011 | 1017 | ulist_free(tmp); |
1012 | 1018 | ulist_free(*roots); |
... | ... | @@ -1338,7 +1344,8 @@ |
1338 | 1344 | struct ulist *roots = NULL; |
1339 | 1345 | struct ulist_node *ref_node = NULL; |
1340 | 1346 | struct ulist_node *root_node = NULL; |
1341 | - struct seq_list seq_elem; | |
1347 | + struct seq_list seq_elem = {}; | |
1348 | + struct seq_list tree_mod_seq_elem = {}; | |
1342 | 1349 | struct ulist_iterator ref_uiter; |
1343 | 1350 | struct ulist_iterator root_uiter; |
1344 | 1351 | struct btrfs_delayed_ref_root *delayed_refs = NULL; |
1345 | 1352 | |
1346 | 1353 | |
... | ... | @@ -1357,17 +1364,20 @@ |
1357 | 1364 | spin_lock(&delayed_refs->lock); |
1358 | 1365 | btrfs_get_delayed_seq(delayed_refs, &seq_elem); |
1359 | 1366 | spin_unlock(&delayed_refs->lock); |
1367 | + btrfs_get_tree_mod_seq(fs_info, &tree_mod_seq_elem); | |
1360 | 1368 | } |
1361 | 1369 | |
1362 | 1370 | ret = btrfs_find_all_leafs(trans, fs_info, extent_item_objectid, |
1363 | - seq_elem.seq, &refs, &extent_item_pos); | |
1371 | + seq_elem.seq, tree_mod_seq_elem.seq, &refs, | |
1372 | + &extent_item_pos); | |
1364 | 1373 | if (ret) |
1365 | 1374 | goto out; |
1366 | 1375 | |
1367 | 1376 | ULIST_ITER_INIT(&ref_uiter); |
1368 | 1377 | while (!ret && (ref_node = ulist_next(refs, &ref_uiter))) { |
1369 | 1378 | ret = btrfs_find_all_roots(trans, fs_info, ref_node->val, |
1370 | - seq_elem.seq, &roots); | |
1379 | + seq_elem.seq, | |
1380 | + tree_mod_seq_elem.seq, &roots); | |
1371 | 1381 | if (ret) |
1372 | 1382 | break; |
1373 | 1383 | ULIST_ITER_INIT(&root_uiter); |
... | ... | @@ -1388,6 +1398,7 @@ |
1388 | 1398 | ulist_free(roots); |
1389 | 1399 | out: |
1390 | 1400 | if (!search_commit_root) { |
1401 | + btrfs_put_tree_mod_seq(fs_info, &tree_mod_seq_elem); | |
1391 | 1402 | btrfs_put_delayed_seq(delayed_refs, &seq_elem); |
1392 | 1403 | btrfs_end_transaction(trans, fs_info->extent_root); |
1393 | 1404 | } |
fs/btrfs/backref.h
... | ... | @@ -58,7 +58,8 @@ |
58 | 58 | |
59 | 59 | int btrfs_find_all_roots(struct btrfs_trans_handle *trans, |
60 | 60 | struct btrfs_fs_info *fs_info, u64 bytenr, |
61 | - u64 seq, struct ulist **roots); | |
61 | + u64 delayed_ref_seq, u64 time_seq, | |
62 | + struct ulist **roots); | |
62 | 63 | |
63 | 64 | struct btrfs_data_container *init_data_container(u32 total_bytes); |
64 | 65 | struct inode_fs_paths *init_ipath(s32 total_bytes, struct btrfs_root *fs_root, |