aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ctree.c
diff options
context:
space:
mode:
authorJosef Bacik <jbacik@fusionio.com>2012-10-11 16:54:30 -0400
committerChris Mason <chris.mason@fusionio.com>2012-12-16 20:46:24 -0500
commit70c8a91ce21b83ccd2d9e7c968775430ead4353d (patch)
treedc1e83734b08836fc278ae2d763c5d75cc3d4de0 /fs/btrfs/ctree.c
parentd6393786cd40f67709324bc4f08d7e4b911153fe (diff)
Btrfs: log changed inodes based on the extent map tree
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>
Diffstat (limited to 'fs/btrfs/ctree.c')
-rw-r--r--fs/btrfs/ctree.c133
1 files changed, 133 insertions, 0 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 0c5c28ff794f..e8b32641ea90 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -5490,6 +5490,139 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
5490 return btrfs_next_old_leaf(root, path, 0); 5490 return btrfs_next_old_leaf(root, path, 0);
5491} 5491}
5492 5492
5493/* Release the path up to but not including the given level */
5494static void btrfs_release_level(struct btrfs_path *path, int level)
5495{
5496 int i;
5497
5498 for (i = 0; i < level; i++) {
5499 path->slots[i] = 0;
5500 if (!path->nodes[i])
5501 continue;
5502 if (path->locks[i]) {
5503 btrfs_tree_unlock_rw(path->nodes[i], path->locks[i]);
5504 path->locks[i] = 0;
5505 }
5506 free_extent_buffer(path->nodes[i]);
5507 path->nodes[i] = NULL;
5508 }
5509}
5510
5511/*
5512 * This function assumes 2 things
5513 *
5514 * 1) You are using path->keep_locks
5515 * 2) You are not inserting items.
5516 *
5517 * If either of these are not true do not use this function. If you need a next
5518 * leaf with either of these not being true then this function can be easily
5519 * adapted to do that, but at the moment these are the limitations.
5520 */
5521int btrfs_next_leaf_write(struct btrfs_trans_handle *trans,
5522 struct btrfs_root *root, struct btrfs_path *path,
5523 int del)
5524{
5525 struct extent_buffer *b;
5526 struct btrfs_key key;
5527 u32 nritems;
5528 int level = 1;
5529 int slot;
5530 int ret = 1;
5531 int write_lock_level = BTRFS_MAX_LEVEL;
5532 int ins_len = del ? -1 : 0;
5533
5534 WARN_ON(!(path->keep_locks || path->really_keep_locks));
5535
5536 nritems = btrfs_header_nritems(path->nodes[0]);
5537 btrfs_item_key_to_cpu(path->nodes[0], &key, nritems - 1);
5538
5539 while (path->nodes[level]) {
5540 nritems = btrfs_header_nritems(path->nodes[level]);
5541 if (!(path->locks[level] & BTRFS_WRITE_LOCK)) {
5542search:
5543 btrfs_release_path(path);
5544 ret = btrfs_search_slot(trans, root, &key, path,
5545 ins_len, 1);
5546 if (ret < 0)
5547 goto out;
5548 level = 1;
5549 continue;
5550 }
5551
5552 if (path->slots[level] >= nritems - 1) {
5553 level++;
5554 continue;
5555 }
5556
5557 btrfs_release_level(path, level);
5558 break;
5559 }
5560
5561 if (!path->nodes[level]) {
5562 ret = 1;
5563 goto out;
5564 }
5565
5566 path->slots[level]++;
5567 b = path->nodes[level];
5568
5569 while (b) {
5570 level = btrfs_header_level(b);
5571
5572 if (!should_cow_block(trans, root, b))
5573 goto cow_done;
5574
5575 btrfs_set_path_blocking(path);
5576 ret = btrfs_cow_block(trans, root, b,
5577 path->nodes[level + 1],
5578 path->slots[level + 1], &b);
5579 if (ret)
5580 goto out;
5581cow_done:
5582 path->nodes[level] = b;
5583 btrfs_clear_path_blocking(path, NULL, 0);
5584 if (level != 0) {
5585 ret = setup_nodes_for_search(trans, root, path, b,
5586 level, ins_len,
5587 &write_lock_level);
5588 if (ret == -EAGAIN)
5589 goto search;
5590 if (ret)
5591 goto out;
5592
5593 b = path->nodes[level];
5594 slot = path->slots[level];
5595
5596 ret = read_block_for_search(trans, root, path,
5597 &b, level, slot, &key, 0);
5598 if (ret == -EAGAIN)
5599 goto search;
5600 if (ret)
5601 goto out;
5602 level = btrfs_header_level(b);
5603 if (!btrfs_try_tree_write_lock(b)) {
5604 btrfs_set_path_blocking(path);
5605 btrfs_tree_lock(b);
5606 btrfs_clear_path_blocking(path, b,
5607 BTRFS_WRITE_LOCK);
5608 }
5609 path->locks[level] = BTRFS_WRITE_LOCK;
5610 path->nodes[level] = b;
5611 path->slots[level] = 0;
5612 } else {
5613 path->slots[level] = 0;
5614 ret = 0;
5615 break;
5616 }
5617 }
5618
5619out:
5620 if (ret)
5621 btrfs_release_path(path);
5622
5623 return ret;
5624}
5625
5493int btrfs_next_old_leaf(struct btrfs_root *root, struct btrfs_path *path, 5626int btrfs_next_old_leaf(struct btrfs_root *root, struct btrfs_path *path,
5494 u64 time_seq) 5627 u64 time_seq)
5495{ 5628{