Skip to content

Commit

Permalink
Btrfs: log changed inodes based on the extent map tree
Browse files Browse the repository at this point in the history
We don't really need to copy extents from the source tree since we have all
of the information already available to us in the extent_map tree.  So
instead just write the extents straight to the log tree and don't bother to
copy the extent items from the source tree.

Signed-off-by: Josef Bacik <jbacik@fusionio.com>
Signed-off-by: Chris Mason <chris.mason@fusionio.com>
  • Loading branch information
Josef Bacik authored and Chris Mason committed Dec 17, 2012
1 parent d639378 commit 70c8a91
Show file tree
Hide file tree
Showing 7 changed files with 372 additions and 210 deletions.
133 changes: 133 additions & 0 deletions fs/btrfs/ctree.c
Original file line number Diff line number Diff line change
Expand Up @@ -5490,6 +5490,139 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
return btrfs_next_old_leaf(root, path, 0);
}

/* Release the path up to but not including the given level */
static void btrfs_release_level(struct btrfs_path *path, int level)
{
int i;

for (i = 0; i < level; i++) {
path->slots[i] = 0;
if (!path->nodes[i])
continue;
if (path->locks[i]) {
btrfs_tree_unlock_rw(path->nodes[i], path->locks[i]);
path->locks[i] = 0;
}
free_extent_buffer(path->nodes[i]);
path->nodes[i] = NULL;
}
}

/*
* This function assumes 2 things
*
* 1) You are using path->keep_locks
* 2) You are not inserting items.
*
* If either of these are not true do not use this function. If you need a next
* leaf with either of these not being true then this function can be easily
* adapted to do that, but at the moment these are the limitations.
*/
int btrfs_next_leaf_write(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct btrfs_path *path,
int del)
{
struct extent_buffer *b;
struct btrfs_key key;
u32 nritems;
int level = 1;
int slot;
int ret = 1;
int write_lock_level = BTRFS_MAX_LEVEL;
int ins_len = del ? -1 : 0;

WARN_ON(!(path->keep_locks || path->really_keep_locks));

nritems = btrfs_header_nritems(path->nodes[0]);
btrfs_item_key_to_cpu(path->nodes[0], &key, nritems - 1);

while (path->nodes[level]) {
nritems = btrfs_header_nritems(path->nodes[level]);
if (!(path->locks[level] & BTRFS_WRITE_LOCK)) {
search:
btrfs_release_path(path);
ret = btrfs_search_slot(trans, root, &key, path,
ins_len, 1);
if (ret < 0)
goto out;
level = 1;
continue;
}

if (path->slots[level] >= nritems - 1) {
level++;
continue;
}

btrfs_release_level(path, level);
break;
}

if (!path->nodes[level]) {
ret = 1;
goto out;
}

path->slots[level]++;
b = path->nodes[level];

while (b) {
level = btrfs_header_level(b);

if (!should_cow_block(trans, root, b))
goto cow_done;

btrfs_set_path_blocking(path);
ret = btrfs_cow_block(trans, root, b,
path->nodes[level + 1],
path->slots[level + 1], &b);
if (ret)
goto out;
cow_done:
path->nodes[level] = b;
btrfs_clear_path_blocking(path, NULL, 0);
if (level != 0) {
ret = setup_nodes_for_search(trans, root, path, b,
level, ins_len,
&write_lock_level);
if (ret == -EAGAIN)
goto search;
if (ret)
goto out;

b = path->nodes[level];
slot = path->slots[level];

ret = read_block_for_search(trans, root, path,
&b, level, slot, &key, 0);
if (ret == -EAGAIN)
goto search;
if (ret)
goto out;
level = btrfs_header_level(b);
if (!btrfs_try_tree_write_lock(b)) {
btrfs_set_path_blocking(path);
btrfs_tree_lock(b);
btrfs_clear_path_blocking(path, b,
BTRFS_WRITE_LOCK);
}
path->locks[level] = BTRFS_WRITE_LOCK;
path->nodes[level] = b;
path->slots[level] = 0;
} else {
path->slots[level] = 0;
ret = 0;
break;
}
}

out:
if (ret)
btrfs_release_path(path);

return ret;
}

int btrfs_next_old_leaf(struct btrfs_root *root, struct btrfs_path *path,
u64 time_seq)
{
Expand Down
3 changes: 3 additions & 0 deletions fs/btrfs/ctree.h
Original file line number Diff line number Diff line change
Expand Up @@ -3187,6 +3187,9 @@ static inline int btrfs_insert_empty_item(struct btrfs_trans_handle *trans,
}

int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path);
int btrfs_next_leaf_write(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct btrfs_path *path,
int del);
int btrfs_next_old_leaf(struct btrfs_root *root, struct btrfs_path *path,
u64 time_seq);
static inline int btrfs_next_old_item(struct btrfs_root *root,
Expand Down
20 changes: 8 additions & 12 deletions fs/btrfs/extent_map.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ void extent_map_tree_init(struct extent_map_tree *tree)
struct extent_map *alloc_extent_map(void)
{
struct extent_map *em;
em = kmem_cache_alloc(extent_map_cache, GFP_NOFS);
em = kmem_cache_zalloc(extent_map_cache, GFP_NOFS);
if (!em)
return NULL;
em->in_tree = 0;
Expand Down Expand Up @@ -198,16 +198,15 @@ static void try_merge_map(struct extent_map_tree *tree, struct extent_map *em)
merge = rb_entry(rb, struct extent_map, rb_node);
if (rb && mergable_maps(merge, em)) {
em->start = merge->start;
em->orig_start = merge->orig_start;
em->len += merge->len;
em->block_len += merge->block_len;
em->block_start = merge->block_start;
merge->in_tree = 0;
if (merge->generation > em->generation) {
em->mod_start = em->start;
em->mod_len = em->len;
em->generation = merge->generation;
list_move(&em->list, &tree->modified_extents);
}
em->mod_len = (em->mod_len + em->mod_start) - merge->mod_start;
em->mod_start = merge->mod_start;
em->generation = max(em->generation, merge->generation);
list_move(&em->list, &tree->modified_extents);

list_del_init(&merge->list);
rb_erase(&merge->rb_node, &tree->map);
Expand All @@ -223,11 +222,8 @@ static void try_merge_map(struct extent_map_tree *tree, struct extent_map *em)
em->block_len += merge->len;
rb_erase(&merge->rb_node, &tree->map);
merge->in_tree = 0;
if (merge->generation > em->generation) {
em->mod_len = em->len;
em->generation = merge->generation;
list_move(&em->list, &tree->modified_extents);
}
em->mod_len = (merge->mod_start + merge->mod_len) - em->mod_start;
em->generation = max(em->generation, merge->generation);
list_del_init(&merge->list);
free_extent_map(merge);
}
Expand Down
2 changes: 1 addition & 1 deletion fs/btrfs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -621,7 +621,7 @@ void btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end,
} else {
split->block_len = split->len;
split->block_start = em->block_start + diff;
split->orig_start = split->start;
split->orig_start = em->orig_start;
}

ret = add_extent_mapping(em_tree, split);
Expand Down
Loading

0 comments on commit 70c8a91

Please sign in to comment.