diff options
author | Jan Schmidt <list.btrfs@jan-o-sch.net> | 2012-05-16 12:36:03 -0400 |
---|---|---|
committer | Jan Schmidt <list.btrfs@jan-o-sch.net> | 2012-05-30 09:17:34 -0400 |
commit | 8445f61cad927b6efffdd4e042a51a783ff8853f (patch) | |
tree | 4f3b0c3172376fe73c3a296f47e0f38388015944 /fs/btrfs | |
parent | 5d9e75c41d11ca79b1d1ff6ed17c88c9047d1fea (diff) |
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>
Diffstat (limited to 'fs/btrfs')
-rw-r--r-- | fs/btrfs/backref.c | 43 | ||||
-rw-r--r-- | fs/btrfs/backref.h | 3 |
2 files changed, 29 insertions, 17 deletions
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c index fd13101aafa3..0ac47f2834d1 100644 --- a/fs/btrfs/backref.c +++ b/fs/btrfs/backref.c | |||
@@ -231,6 +231,7 @@ add_parent: | |||
231 | */ | 231 | */ |
232 | static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info, | 232 | static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info, |
233 | int search_commit_root, | 233 | int search_commit_root, |
234 | u64 time_seq, | ||
234 | struct __prelim_ref *ref, | 235 | struct __prelim_ref *ref, |
235 | struct ulist *parents, | 236 | struct ulist *parents, |
236 | const u64 *extent_item_pos) | 237 | const u64 *extent_item_pos) |
@@ -266,7 +267,7 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info, | |||
266 | goto out; | 267 | goto out; |
267 | 268 | ||
268 | path->lowest_level = level; | 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 | pr_debug("search slot in root %llu (level %d, ref count %d) returned " | 271 | pr_debug("search slot in root %llu (level %d, ref count %d) returned " |
271 | "%d for key (%llu %u %llu)\n", | 272 | "%d for key (%llu %u %llu)\n", |
272 | (unsigned long long)ref->root_id, level, ref->count, ret, | 273 | (unsigned long long)ref->root_id, level, ref->count, ret, |
@@ -305,7 +306,7 @@ out: | |||
305 | * resolve all indirect backrefs from the list | 306 | * resolve all indirect backrefs from the list |
306 | */ | 307 | */ |
307 | static int __resolve_indirect_refs(struct btrfs_fs_info *fs_info, | 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 | struct list_head *head, | 310 | struct list_head *head, |
310 | const u64 *extent_item_pos) | 311 | const u64 *extent_item_pos) |
311 | { | 312 | { |
@@ -333,7 +334,8 @@ static int __resolve_indirect_refs(struct btrfs_fs_info *fs_info, | |||
333 | if (ref->count == 0) | 334 | if (ref->count == 0) |
334 | continue; | 335 | continue; |
335 | err = __resolve_indirect_ref(fs_info, search_commit_root, | 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 | if (err) { | 339 | if (err) { |
338 | if (ret == 0) | 340 | if (ret == 0) |
339 | ret = err; | 341 | ret = err; |
@@ -750,7 +752,8 @@ static int __add_keyed_refs(struct btrfs_fs_info *fs_info, | |||
750 | */ | 752 | */ |
751 | static int find_parent_nodes(struct btrfs_trans_handle *trans, | 753 | static int find_parent_nodes(struct btrfs_trans_handle *trans, |
752 | struct btrfs_fs_info *fs_info, u64 bytenr, | 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 | const u64 *extent_item_pos) | 757 | const u64 *extent_item_pos) |
755 | { | 758 | { |
756 | struct btrfs_key key; | 759 | struct btrfs_key key; |
@@ -813,7 +816,8 @@ again: | |||
813 | btrfs_put_delayed_ref(&head->node); | 816 | btrfs_put_delayed_ref(&head->node); |
814 | goto again; | 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 | if (ret) { | 821 | if (ret) { |
818 | spin_unlock(&delayed_refs->lock); | 822 | spin_unlock(&delayed_refs->lock); |
819 | goto out; | 823 | goto out; |
@@ -854,8 +858,8 @@ again: | |||
854 | if (ret) | 858 | if (ret) |
855 | goto out; | 859 | goto out; |
856 | 860 | ||
857 | ret = __resolve_indirect_refs(fs_info, search_commit_root, &prefs, | 861 | ret = __resolve_indirect_refs(fs_info, search_commit_root, time_seq, |
858 | extent_item_pos); | 862 | &prefs, extent_item_pos); |
859 | if (ret) | 863 | if (ret) |
860 | goto out; | 864 | goto out; |
861 | 865 | ||
@@ -945,7 +949,8 @@ static void free_leaf_list(struct ulist *blocks) | |||
945 | */ | 949 | */ |
946 | static int btrfs_find_all_leafs(struct btrfs_trans_handle *trans, | 950 | static int btrfs_find_all_leafs(struct btrfs_trans_handle *trans, |
947 | struct btrfs_fs_info *fs_info, u64 bytenr, | 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 | const u64 *extent_item_pos) | 954 | const u64 *extent_item_pos) |
950 | { | 955 | { |
951 | struct ulist *tmp; | 956 | struct ulist *tmp; |
@@ -960,8 +965,8 @@ static int btrfs_find_all_leafs(struct btrfs_trans_handle *trans, | |||
960 | return -ENOMEM; | 965 | return -ENOMEM; |
961 | } | 966 | } |
962 | 967 | ||
963 | ret = find_parent_nodes(trans, fs_info, bytenr, seq, *leafs, tmp, | 968 | ret = find_parent_nodes(trans, fs_info, bytenr, delayed_ref_seq, |
964 | extent_item_pos); | 969 | time_seq, *leafs, tmp, extent_item_pos); |
965 | ulist_free(tmp); | 970 | ulist_free(tmp); |
966 | 971 | ||
967 | if (ret < 0 && ret != -ENOENT) { | 972 | if (ret < 0 && ret != -ENOENT) { |
@@ -987,7 +992,8 @@ static int btrfs_find_all_leafs(struct btrfs_trans_handle *trans, | |||
987 | */ | 992 | */ |
988 | int btrfs_find_all_roots(struct btrfs_trans_handle *trans, | 993 | int btrfs_find_all_roots(struct btrfs_trans_handle *trans, |
989 | struct btrfs_fs_info *fs_info, u64 bytenr, | 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 | struct ulist *tmp; | 998 | struct ulist *tmp; |
993 | struct ulist_node *node = NULL; | 999 | struct ulist_node *node = NULL; |
@@ -1005,8 +1011,8 @@ int btrfs_find_all_roots(struct btrfs_trans_handle *trans, | |||
1005 | 1011 | ||
1006 | ULIST_ITER_INIT(&uiter); | 1012 | ULIST_ITER_INIT(&uiter); |
1007 | while (1) { | 1013 | while (1) { |
1008 | ret = find_parent_nodes(trans, fs_info, bytenr, seq, | 1014 | ret = find_parent_nodes(trans, fs_info, bytenr, delayed_ref_seq, |
1009 | tmp, *roots, NULL); | 1015 | time_seq, tmp, *roots, NULL); |
1010 | if (ret < 0 && ret != -ENOENT) { | 1016 | if (ret < 0 && ret != -ENOENT) { |
1011 | ulist_free(tmp); | 1017 | ulist_free(tmp); |
1012 | ulist_free(*roots); | 1018 | ulist_free(*roots); |
@@ -1338,7 +1344,8 @@ int iterate_extent_inodes(struct btrfs_fs_info *fs_info, | |||
1338 | struct ulist *roots = NULL; | 1344 | struct ulist *roots = NULL; |
1339 | struct ulist_node *ref_node = NULL; | 1345 | struct ulist_node *ref_node = NULL; |
1340 | struct ulist_node *root_node = NULL; | 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 | struct ulist_iterator ref_uiter; | 1349 | struct ulist_iterator ref_uiter; |
1343 | struct ulist_iterator root_uiter; | 1350 | struct ulist_iterator root_uiter; |
1344 | struct btrfs_delayed_ref_root *delayed_refs = NULL; | 1351 | struct btrfs_delayed_ref_root *delayed_refs = NULL; |
@@ -1357,17 +1364,20 @@ int iterate_extent_inodes(struct btrfs_fs_info *fs_info, | |||
1357 | spin_lock(&delayed_refs->lock); | 1364 | spin_lock(&delayed_refs->lock); |
1358 | btrfs_get_delayed_seq(delayed_refs, &seq_elem); | 1365 | btrfs_get_delayed_seq(delayed_refs, &seq_elem); |
1359 | spin_unlock(&delayed_refs->lock); | 1366 | spin_unlock(&delayed_refs->lock); |
1367 | btrfs_get_tree_mod_seq(fs_info, &tree_mod_seq_elem); | ||
1360 | } | 1368 | } |
1361 | 1369 | ||
1362 | ret = btrfs_find_all_leafs(trans, fs_info, extent_item_objectid, | 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 | if (ret) | 1373 | if (ret) |
1365 | goto out; | 1374 | goto out; |
1366 | 1375 | ||
1367 | ULIST_ITER_INIT(&ref_uiter); | 1376 | ULIST_ITER_INIT(&ref_uiter); |
1368 | while (!ret && (ref_node = ulist_next(refs, &ref_uiter))) { | 1377 | while (!ret && (ref_node = ulist_next(refs, &ref_uiter))) { |
1369 | ret = btrfs_find_all_roots(trans, fs_info, ref_node->val, | 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 | if (ret) | 1381 | if (ret) |
1372 | break; | 1382 | break; |
1373 | ULIST_ITER_INIT(&root_uiter); | 1383 | ULIST_ITER_INIT(&root_uiter); |
@@ -1388,6 +1398,7 @@ int iterate_extent_inodes(struct btrfs_fs_info *fs_info, | |||
1388 | ulist_free(roots); | 1398 | ulist_free(roots); |
1389 | out: | 1399 | out: |
1390 | if (!search_commit_root) { | 1400 | if (!search_commit_root) { |
1401 | btrfs_put_tree_mod_seq(fs_info, &tree_mod_seq_elem); | ||
1391 | btrfs_put_delayed_seq(delayed_refs, &seq_elem); | 1402 | btrfs_put_delayed_seq(delayed_refs, &seq_elem); |
1392 | btrfs_end_transaction(trans, fs_info->extent_root); | 1403 | btrfs_end_transaction(trans, fs_info->extent_root); |
1393 | } | 1404 | } |
diff --git a/fs/btrfs/backref.h b/fs/btrfs/backref.h index 94ba1b2e733b..c18d8ac7b795 100644 --- a/fs/btrfs/backref.h +++ b/fs/btrfs/backref.h | |||
@@ -58,7 +58,8 @@ int paths_from_inode(u64 inum, struct inode_fs_paths *ipath); | |||
58 | 58 | ||
59 | int btrfs_find_all_roots(struct btrfs_trans_handle *trans, | 59 | int btrfs_find_all_roots(struct btrfs_trans_handle *trans, |
60 | struct btrfs_fs_info *fs_info, u64 bytenr, | 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 | struct btrfs_data_container *init_data_container(u32 total_bytes); | 64 | struct btrfs_data_container *init_data_container(u32 total_bytes); |
64 | struct inode_fs_paths *init_ipath(s32 total_bytes, struct btrfs_root *fs_root, | 65 | struct inode_fs_paths *init_ipath(s32 total_bytes, struct btrfs_root *fs_root, |