Commit 8445f61cad927b6efffdd4e042a51a783ff8853f

Authored by Jan Schmidt
1 parent 5d9e75c41d

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

... ... @@ -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 }
... ... @@ -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,