aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorJan Schmidt <list.btrfs@jan-o-sch.net>2012-05-16 12:36:03 -0400
committerJan Schmidt <list.btrfs@jan-o-sch.net>2012-05-30 09:17:34 -0400
commit8445f61cad927b6efffdd4e042a51a783ff8853f (patch)
tree4f3b0c3172376fe73c3a296f47e0f38388015944 /fs/btrfs
parent5d9e75c41d11ca79b1d1ff6ed17c88c9047d1fea (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.c43
-rw-r--r--fs/btrfs/backref.h3
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 */
232static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info, 232static 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 */
307static int __resolve_indirect_refs(struct btrfs_fs_info *fs_info, 308static 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 */
751static int find_parent_nodes(struct btrfs_trans_handle *trans, 753static 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 */
946static int btrfs_find_all_leafs(struct btrfs_trans_handle *trans, 950static 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 */
988int btrfs_find_all_roots(struct btrfs_trans_handle *trans, 993int 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);
1389out: 1399out:
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
59int btrfs_find_all_roots(struct btrfs_trans_handle *trans, 59int 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
63struct btrfs_data_container *init_data_container(u32 total_bytes); 64struct btrfs_data_container *init_data_container(u32 total_bytes);
64struct inode_fs_paths *init_ipath(s32 total_bytes, struct btrfs_root *fs_root, 65struct inode_fs_paths *init_ipath(s32 total_bytes, struct btrfs_root *fs_root,