Skip to content

Commit

Permalink
Btrfs: use the tree modification log for backref resolving
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Jan Schmidt committed May 30, 2012
1 parent 5d9e75c commit 8445f61
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 17 deletions.
43 changes: 27 additions & 16 deletions fs/btrfs/backref.c
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ static int add_all_parents(struct btrfs_root *root, struct btrfs_path *path,
*/
static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info,
int search_commit_root,
u64 time_seq,
struct __prelim_ref *ref,
struct ulist *parents,
const u64 *extent_item_pos)
Expand Down Expand Up @@ -266,7 +267,7 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info,
goto out;

path->lowest_level = level;
ret = btrfs_search_slot(NULL, root, &ref->key_for_search, path, 0, 0);
ret = btrfs_search_old_slot(root, &ref->key_for_search, path, time_seq);
pr_debug("search slot in root %llu (level %d, ref count %d) returned "
"%d for key (%llu %u %llu)\n",
(unsigned long long)ref->root_id, level, ref->count, ret,
Expand Down Expand Up @@ -305,7 +306,7 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info,
* resolve all indirect backrefs from the list
*/
static int __resolve_indirect_refs(struct btrfs_fs_info *fs_info,
int search_commit_root,
int search_commit_root, u64 time_seq,
struct list_head *head,
const u64 *extent_item_pos)
{
Expand Down Expand Up @@ -333,7 +334,8 @@ static int __resolve_indirect_refs(struct btrfs_fs_info *fs_info,
if (ref->count == 0)
continue;
err = __resolve_indirect_ref(fs_info, search_commit_root,
ref, parents, extent_item_pos);
time_seq, ref, parents,
extent_item_pos);
if (err) {
if (ret == 0)
ret = err;
Expand Down Expand Up @@ -750,7 +752,8 @@ static int __add_keyed_refs(struct btrfs_fs_info *fs_info,
*/
static int find_parent_nodes(struct btrfs_trans_handle *trans,
struct btrfs_fs_info *fs_info, u64 bytenr,
u64 seq, struct ulist *refs, struct ulist *roots,
u64 delayed_ref_seq, u64 time_seq,
struct ulist *refs, struct ulist *roots,
const u64 *extent_item_pos)
{
struct btrfs_key key;
Expand Down Expand Up @@ -813,7 +816,8 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans,
btrfs_put_delayed_ref(&head->node);
goto again;
}
ret = __add_delayed_refs(head, seq, &prefs_delayed);
ret = __add_delayed_refs(head, delayed_ref_seq,
&prefs_delayed);
if (ret) {
spin_unlock(&delayed_refs->lock);
goto out;
Expand Down Expand Up @@ -854,8 +858,8 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans,
if (ret)
goto out;

ret = __resolve_indirect_refs(fs_info, search_commit_root, &prefs,
extent_item_pos);
ret = __resolve_indirect_refs(fs_info, search_commit_root, time_seq,
&prefs, extent_item_pos);
if (ret)
goto out;

Expand Down Expand Up @@ -945,7 +949,8 @@ static void free_leaf_list(struct ulist *blocks)
*/
static int btrfs_find_all_leafs(struct btrfs_trans_handle *trans,
struct btrfs_fs_info *fs_info, u64 bytenr,
u64 seq, struct ulist **leafs,
u64 delayed_ref_seq, u64 time_seq,
struct ulist **leafs,
const u64 *extent_item_pos)
{
struct ulist *tmp;
Expand All @@ -960,8 +965,8 @@ static int btrfs_find_all_leafs(struct btrfs_trans_handle *trans,
return -ENOMEM;
}

ret = find_parent_nodes(trans, fs_info, bytenr, seq, *leafs, tmp,
extent_item_pos);
ret = find_parent_nodes(trans, fs_info, bytenr, delayed_ref_seq,
time_seq, *leafs, tmp, extent_item_pos);
ulist_free(tmp);

if (ret < 0 && ret != -ENOENT) {
Expand All @@ -987,7 +992,8 @@ static int btrfs_find_all_leafs(struct btrfs_trans_handle *trans,
*/
int btrfs_find_all_roots(struct btrfs_trans_handle *trans,
struct btrfs_fs_info *fs_info, u64 bytenr,
u64 seq, struct ulist **roots)
u64 delayed_ref_seq, u64 time_seq,
struct ulist **roots)
{
struct ulist *tmp;
struct ulist_node *node = NULL;
Expand All @@ -1005,8 +1011,8 @@ int btrfs_find_all_roots(struct btrfs_trans_handle *trans,

ULIST_ITER_INIT(&uiter);
while (1) {
ret = find_parent_nodes(trans, fs_info, bytenr, seq,
tmp, *roots, NULL);
ret = find_parent_nodes(trans, fs_info, bytenr, delayed_ref_seq,
time_seq, tmp, *roots, NULL);
if (ret < 0 && ret != -ENOENT) {
ulist_free(tmp);
ulist_free(*roots);
Expand Down Expand Up @@ -1338,7 +1344,8 @@ int iterate_extent_inodes(struct btrfs_fs_info *fs_info,
struct ulist *roots = NULL;
struct ulist_node *ref_node = NULL;
struct ulist_node *root_node = NULL;
struct seq_list seq_elem;
struct seq_list seq_elem = {};
struct seq_list tree_mod_seq_elem = {};
struct ulist_iterator ref_uiter;
struct ulist_iterator root_uiter;
struct btrfs_delayed_ref_root *delayed_refs = NULL;
Expand All @@ -1357,17 +1364,20 @@ int iterate_extent_inodes(struct btrfs_fs_info *fs_info,
spin_lock(&delayed_refs->lock);
btrfs_get_delayed_seq(delayed_refs, &seq_elem);
spin_unlock(&delayed_refs->lock);
btrfs_get_tree_mod_seq(fs_info, &tree_mod_seq_elem);
}

ret = btrfs_find_all_leafs(trans, fs_info, extent_item_objectid,
seq_elem.seq, &refs, &extent_item_pos);
seq_elem.seq, tree_mod_seq_elem.seq, &refs,
&extent_item_pos);
if (ret)
goto out;

ULIST_ITER_INIT(&ref_uiter);
while (!ret && (ref_node = ulist_next(refs, &ref_uiter))) {
ret = btrfs_find_all_roots(trans, fs_info, ref_node->val,
seq_elem.seq, &roots);
seq_elem.seq,
tree_mod_seq_elem.seq, &roots);
if (ret)
break;
ULIST_ITER_INIT(&root_uiter);
Expand All @@ -1388,6 +1398,7 @@ int iterate_extent_inodes(struct btrfs_fs_info *fs_info,
ulist_free(roots);
out:
if (!search_commit_root) {
btrfs_put_tree_mod_seq(fs_info, &tree_mod_seq_elem);
btrfs_put_delayed_seq(delayed_refs, &seq_elem);
btrfs_end_transaction(trans, fs_info->extent_root);
}
Expand Down
3 changes: 2 additions & 1 deletion fs/btrfs/backref.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ int paths_from_inode(u64 inum, struct inode_fs_paths *ipath);

int btrfs_find_all_roots(struct btrfs_trans_handle *trans,
struct btrfs_fs_info *fs_info, u64 bytenr,
u64 seq, struct ulist **roots);
u64 delayed_ref_seq, u64 time_seq,
struct ulist **roots);

struct btrfs_data_container *init_data_container(u32 total_bytes);
struct inode_fs_paths *init_ipath(s32 total_bytes, struct btrfs_root *fs_root,
Expand Down

0 comments on commit 8445f61

Please sign in to comment.