aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
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
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')
-rw-r--r--fs/btrfs/ctree.c133
-rw-r--r--fs/btrfs/ctree.h3
-rw-r--r--fs/btrfs/extent_map.c20
-rw-r--r--fs/btrfs/file.c2
-rw-r--r--fs/btrfs/inode.c85
-rw-r--r--fs/btrfs/tree-log.c338
-rw-r--r--fs/btrfs/volumes.c1
7 files changed, 372 insertions, 210 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{
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 9ed452f5d062..55aff6764bb9 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -3187,6 +3187,9 @@ static inline int btrfs_insert_empty_item(struct btrfs_trans_handle *trans,
3187} 3187}
3188 3188
3189int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path); 3189int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path);
3190int btrfs_next_leaf_write(struct btrfs_trans_handle *trans,
3191 struct btrfs_root *root, struct btrfs_path *path,
3192 int del);
3190int btrfs_next_old_leaf(struct btrfs_root *root, struct btrfs_path *path, 3193int btrfs_next_old_leaf(struct btrfs_root *root, struct btrfs_path *path,
3191 u64 time_seq); 3194 u64 time_seq);
3192static inline int btrfs_next_old_item(struct btrfs_root *root, 3195static inline int btrfs_next_old_item(struct btrfs_root *root,
diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c
index 85ae2b6fe03b..fff2c28497b6 100644
--- a/fs/btrfs/extent_map.c
+++ b/fs/btrfs/extent_map.c
@@ -49,7 +49,7 @@ void extent_map_tree_init(struct extent_map_tree *tree)
49struct extent_map *alloc_extent_map(void) 49struct extent_map *alloc_extent_map(void)
50{ 50{
51 struct extent_map *em; 51 struct extent_map *em;
52 em = kmem_cache_alloc(extent_map_cache, GFP_NOFS); 52 em = kmem_cache_zalloc(extent_map_cache, GFP_NOFS);
53 if (!em) 53 if (!em)
54 return NULL; 54 return NULL;
55 em->in_tree = 0; 55 em->in_tree = 0;
@@ -198,16 +198,15 @@ static void try_merge_map(struct extent_map_tree *tree, struct extent_map *em)
198 merge = rb_entry(rb, struct extent_map, rb_node); 198 merge = rb_entry(rb, struct extent_map, rb_node);
199 if (rb && mergable_maps(merge, em)) { 199 if (rb && mergable_maps(merge, em)) {
200 em->start = merge->start; 200 em->start = merge->start;
201 em->orig_start = merge->orig_start;
201 em->len += merge->len; 202 em->len += merge->len;
202 em->block_len += merge->block_len; 203 em->block_len += merge->block_len;
203 em->block_start = merge->block_start; 204 em->block_start = merge->block_start;
204 merge->in_tree = 0; 205 merge->in_tree = 0;
205 if (merge->generation > em->generation) { 206 em->mod_len = (em->mod_len + em->mod_start) - merge->mod_start;
206 em->mod_start = em->start; 207 em->mod_start = merge->mod_start;
207 em->mod_len = em->len; 208 em->generation = max(em->generation, merge->generation);
208 em->generation = merge->generation; 209 list_move(&em->list, &tree->modified_extents);
209 list_move(&em->list, &tree->modified_extents);
210 }
211 210
212 list_del_init(&merge->list); 211 list_del_init(&merge->list);
213 rb_erase(&merge->rb_node, &tree->map); 212 rb_erase(&merge->rb_node, &tree->map);
@@ -223,11 +222,8 @@ static void try_merge_map(struct extent_map_tree *tree, struct extent_map *em)
223 em->block_len += merge->len; 222 em->block_len += merge->len;
224 rb_erase(&merge->rb_node, &tree->map); 223 rb_erase(&merge->rb_node, &tree->map);
225 merge->in_tree = 0; 224 merge->in_tree = 0;
226 if (merge->generation > em->generation) { 225 em->mod_len = (merge->mod_start + merge->mod_len) - em->mod_start;
227 em->mod_len = em->len; 226 em->generation = max(em->generation, merge->generation);
228 em->generation = merge->generation;
229 list_move(&em->list, &tree->modified_extents);
230 }
231 list_del_init(&merge->list); 227 list_del_init(&merge->list);
232 free_extent_map(merge); 228 free_extent_map(merge);
233 } 229 }
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 6810145f4e97..c56088ece500 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -621,7 +621,7 @@ void btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end,
621 } else { 621 } else {
622 split->block_len = split->len; 622 split->block_len = split->len;
623 split->block_start = em->block_start + diff; 623 split->block_start = em->block_start + diff;
624 split->orig_start = split->start; 624 split->orig_start = em->orig_start;
625 } 625 }
626 626
627 ret = add_extent_mapping(em_tree, split); 627 ret = add_extent_mapping(em_tree, split);
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 73e6833dcc21..355a297e7988 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -95,6 +95,10 @@ static noinline int cow_file_range(struct inode *inode,
95 struct page *locked_page, 95 struct page *locked_page,
96 u64 start, u64 end, int *page_started, 96 u64 start, u64 end, int *page_started,
97 unsigned long *nr_written, int unlock); 97 unsigned long *nr_written, int unlock);
98static struct extent_map *create_pinned_em(struct inode *inode, u64 start,
99 u64 len, u64 orig_start,
100 u64 block_start, u64 block_len,
101 u64 orig_block_len, int type);
98 102
99static int btrfs_init_inode_security(struct btrfs_trans_handle *trans, 103static int btrfs_init_inode_security(struct btrfs_trans_handle *trans,
100 struct inode *inode, struct inode *dir, 104 struct inode *inode, struct inode *dir,
@@ -704,10 +708,14 @@ retry:
704 em->compress_type = async_extent->compress_type; 708 em->compress_type = async_extent->compress_type;
705 set_bit(EXTENT_FLAG_PINNED, &em->flags); 709 set_bit(EXTENT_FLAG_PINNED, &em->flags);
706 set_bit(EXTENT_FLAG_COMPRESSED, &em->flags); 710 set_bit(EXTENT_FLAG_COMPRESSED, &em->flags);
711 em->generation = -1;
707 712
708 while (1) { 713 while (1) {
709 write_lock(&em_tree->lock); 714 write_lock(&em_tree->lock);
710 ret = add_extent_mapping(em_tree, em); 715 ret = add_extent_mapping(em_tree, em);
716 if (!ret)
717 list_move(&em->list,
718 &em_tree->modified_extents);
711 write_unlock(&em_tree->lock); 719 write_unlock(&em_tree->lock);
712 if (ret != -EEXIST) { 720 if (ret != -EEXIST) {
713 free_extent_map(em); 721 free_extent_map(em);
@@ -890,10 +898,14 @@ static noinline int __cow_file_range(struct btrfs_trans_handle *trans,
890 em->orig_block_len = ins.offset; 898 em->orig_block_len = ins.offset;
891 em->bdev = root->fs_info->fs_devices->latest_bdev; 899 em->bdev = root->fs_info->fs_devices->latest_bdev;
892 set_bit(EXTENT_FLAG_PINNED, &em->flags); 900 set_bit(EXTENT_FLAG_PINNED, &em->flags);
901 em->generation = -1;
893 902
894 while (1) { 903 while (1) {
895 write_lock(&em_tree->lock); 904 write_lock(&em_tree->lock);
896 ret = add_extent_mapping(em_tree, em); 905 ret = add_extent_mapping(em_tree, em);
906 if (!ret)
907 list_move(&em->list,
908 &em_tree->modified_extents);
897 write_unlock(&em_tree->lock); 909 write_unlock(&em_tree->lock);
898 if (ret != -EEXIST) { 910 if (ret != -EEXIST) {
899 free_extent_map(em); 911 free_extent_map(em);
@@ -1320,7 +1332,7 @@ out_check:
1320 em = alloc_extent_map(); 1332 em = alloc_extent_map();
1321 BUG_ON(!em); /* -ENOMEM */ 1333 BUG_ON(!em); /* -ENOMEM */
1322 em->start = cur_offset; 1334 em->start = cur_offset;
1323 em->orig_start = em->start; 1335 em->orig_start = found_key.offset - extent_offset;
1324 em->len = num_bytes; 1336 em->len = num_bytes;
1325 em->block_len = num_bytes; 1337 em->block_len = num_bytes;
1326 em->block_start = disk_bytenr; 1338 em->block_start = disk_bytenr;
@@ -1328,9 +1340,13 @@ out_check:
1328 em->bdev = root->fs_info->fs_devices->latest_bdev; 1340 em->bdev = root->fs_info->fs_devices->latest_bdev;
1329 set_bit(EXTENT_FLAG_PINNED, &em->flags); 1341 set_bit(EXTENT_FLAG_PINNED, &em->flags);
1330 set_bit(EXTENT_FLAG_FILLING, &em->flags); 1342 set_bit(EXTENT_FLAG_FILLING, &em->flags);
1343 em->generation = -1;
1331 while (1) { 1344 while (1) {
1332 write_lock(&em_tree->lock); 1345 write_lock(&em_tree->lock);
1333 ret = add_extent_mapping(em_tree, em); 1346 ret = add_extent_mapping(em_tree, em);
1347 if (!ret)
1348 list_move(&em->list,
1349 &em_tree->modified_extents);
1334 write_unlock(&em_tree->lock); 1350 write_unlock(&em_tree->lock);
1335 if (ret != -EEXIST) { 1351 if (ret != -EEXIST) {
1336 free_extent_map(em); 1352 free_extent_map(em);
@@ -5371,6 +5387,7 @@ again:
5371 if (start + len <= found_key.offset) 5387 if (start + len <= found_key.offset)
5372 goto not_found; 5388 goto not_found;
5373 em->start = start; 5389 em->start = start;
5390 em->orig_start = start;
5374 em->len = found_key.offset - start; 5391 em->len = found_key.offset - start;
5375 goto not_found_em; 5392 goto not_found_em;
5376 } 5393 }
@@ -5423,7 +5440,7 @@ again:
5423 em->len = (copy_size + root->sectorsize - 1) & 5440 em->len = (copy_size + root->sectorsize - 1) &
5424 ~((u64)root->sectorsize - 1); 5441 ~((u64)root->sectorsize - 1);
5425 em->orig_block_len = em->len; 5442 em->orig_block_len = em->len;
5426 em->orig_start = EXTENT_MAP_INLINE; 5443 em->orig_start = em->start;
5427 if (compress_type) { 5444 if (compress_type) {
5428 set_bit(EXTENT_FLAG_COMPRESSED, &em->flags); 5445 set_bit(EXTENT_FLAG_COMPRESSED, &em->flags);
5429 em->compress_type = compress_type; 5446 em->compress_type = compress_type;
@@ -5476,6 +5493,7 @@ again:
5476 } 5493 }
5477not_found: 5494not_found:
5478 em->start = start; 5495 em->start = start;
5496 em->orig_start = start;
5479 em->len = len; 5497 em->len = len;
5480not_found_em: 5498not_found_em:
5481 em->block_start = EXTENT_MAP_HOLE; 5499 em->block_start = EXTENT_MAP_HOLE;
@@ -5677,30 +5695,14 @@ out:
5677} 5695}
5678 5696
5679static struct extent_map *btrfs_new_extent_direct(struct inode *inode, 5697static struct extent_map *btrfs_new_extent_direct(struct inode *inode,
5680 struct extent_map *em,
5681 u64 start, u64 len) 5698 u64 start, u64 len)
5682{ 5699{
5683 struct btrfs_root *root = BTRFS_I(inode)->root; 5700 struct btrfs_root *root = BTRFS_I(inode)->root;
5684 struct btrfs_trans_handle *trans; 5701 struct btrfs_trans_handle *trans;
5685 struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; 5702 struct extent_map *em;
5686 struct btrfs_key ins; 5703 struct btrfs_key ins;
5687 u64 alloc_hint; 5704 u64 alloc_hint;
5688 int ret; 5705 int ret;
5689 bool insert = false;
5690
5691 /*
5692 * Ok if the extent map we looked up is a hole and is for the exact
5693 * range we want, there is no reason to allocate a new one, however if
5694 * it is not right then we need to free this one and drop the cache for
5695 * our range.
5696 */
5697 if (em->block_start != EXTENT_MAP_HOLE || em->start != start ||
5698 em->len != len) {
5699 free_extent_map(em);
5700 em = NULL;
5701 insert = true;
5702 btrfs_drop_extent_cache(inode, start, start + len - 1, 0);
5703 }
5704 5706
5705 trans = btrfs_join_transaction(root); 5707 trans = btrfs_join_transaction(root);
5706 if (IS_ERR(trans)) 5708 if (IS_ERR(trans))
@@ -5716,38 +5718,10 @@ static struct extent_map *btrfs_new_extent_direct(struct inode *inode,
5716 goto out; 5718 goto out;
5717 } 5719 }
5718 5720
5719 if (!em) { 5721 em = create_pinned_em(inode, start, ins.offset, start, ins.objectid,
5720 em = alloc_extent_map(); 5722 ins.offset, ins.offset, 0);
5721 if (!em) { 5723 if (IS_ERR(em))
5722 em = ERR_PTR(-ENOMEM); 5724 goto out;
5723 goto out;
5724 }
5725 }
5726
5727 em->start = start;
5728 em->orig_start = em->start;
5729 em->len = ins.offset;
5730
5731 em->block_start = ins.objectid;
5732 em->block_len = ins.offset;
5733 em->orig_block_len = ins.offset;
5734 em->bdev = root->fs_info->fs_devices->latest_bdev;
5735
5736 /*
5737 * We need to do this because if we're using the original em we searched
5738 * for, we could have EXTENT_FLAG_VACANCY set, and we don't want that.
5739 */
5740 em->flags = 0;
5741 set_bit(EXTENT_FLAG_PINNED, &em->flags);
5742
5743 while (insert) {
5744 write_lock(&em_tree->lock);
5745 ret = add_extent_mapping(em_tree, em);
5746 write_unlock(&em_tree->lock);
5747 if (ret != -EEXIST)
5748 break;
5749 btrfs_drop_extent_cache(inode, start, start + em->len - 1, 0);
5750 }
5751 5725
5752 ret = btrfs_add_ordered_extent_dio(inode, start, ins.objectid, 5726 ret = btrfs_add_ordered_extent_dio(inode, start, ins.objectid,
5753 ins.offset, ins.offset, 0); 5727 ins.offset, ins.offset, 0);
@@ -5943,6 +5917,7 @@ static struct extent_map *create_pinned_em(struct inode *inode, u64 start,
5943 em->block_start = block_start; 5917 em->block_start = block_start;
5944 em->bdev = root->fs_info->fs_devices->latest_bdev; 5918 em->bdev = root->fs_info->fs_devices->latest_bdev;
5945 em->orig_block_len = orig_block_len; 5919 em->orig_block_len = orig_block_len;
5920 em->generation = -1;
5946 set_bit(EXTENT_FLAG_PINNED, &em->flags); 5921 set_bit(EXTENT_FLAG_PINNED, &em->flags);
5947 if (type == BTRFS_ORDERED_PREALLOC) 5922 if (type == BTRFS_ORDERED_PREALLOC)
5948 set_bit(EXTENT_FLAG_FILLING, &em->flags); 5923 set_bit(EXTENT_FLAG_FILLING, &em->flags);
@@ -5952,6 +5927,9 @@ static struct extent_map *create_pinned_em(struct inode *inode, u64 start,
5952 em->start + em->len - 1, 0); 5927 em->start + em->len - 1, 0);
5953 write_lock(&em_tree->lock); 5928 write_lock(&em_tree->lock);
5954 ret = add_extent_mapping(em_tree, em); 5929 ret = add_extent_mapping(em_tree, em);
5930 if (!ret)
5931 list_move(&em->list,
5932 &em_tree->modified_extents);
5955 write_unlock(&em_tree->lock); 5933 write_unlock(&em_tree->lock);
5956 } while (ret == -EEXIST); 5934 } while (ret == -EEXIST);
5957 5935
@@ -6078,7 +6056,7 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock,
6078 goto must_cow; 6056 goto must_cow;
6079 6057
6080 if (can_nocow_odirect(trans, inode, start, len) == 1) { 6058 if (can_nocow_odirect(trans, inode, start, len) == 1) {
6081 u64 orig_start = em->start; 6059 u64 orig_start = em->orig_start;
6082 u64 orig_block_len = em->orig_block_len; 6060 u64 orig_block_len = em->orig_block_len;
6083 6061
6084 if (type == BTRFS_ORDERED_PREALLOC) { 6062 if (type == BTRFS_ORDERED_PREALLOC) {
@@ -6110,7 +6088,8 @@ must_cow:
6110 * it above 6088 * it above
6111 */ 6089 */
6112 len = bh_result->b_size; 6090 len = bh_result->b_size;
6113 em = btrfs_new_extent_direct(inode, em, start, len); 6091 free_extent_map(em);
6092 em = btrfs_new_extent_direct(inode, start, len);
6114 if (IS_ERR(em)) { 6093 if (IS_ERR(em)) {
6115 ret = PTR_ERR(em); 6094 ret = PTR_ERR(em);
6116 goto unlock_err; 6095 goto unlock_err;
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index ab7168ee618f..72444811d275 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -3150,145 +3150,220 @@ static int extent_cmp(void *priv, struct list_head *a, struct list_head *b)
3150 return 0; 3150 return 0;
3151} 3151}
3152 3152
3153struct log_args { 3153static int drop_adjacent_extents(struct btrfs_trans_handle *trans,
3154 struct extent_buffer *src; 3154 struct btrfs_root *root, struct inode *inode,
3155 u64 next_offset; 3155 struct extent_map *em,
3156 int start_slot; 3156 struct btrfs_path *path)
3157 int nr; 3157{
3158}; 3158 struct btrfs_file_extent_item *fi;
3159 struct extent_buffer *leaf;
3160 struct btrfs_key key, new_key;
3161 struct btrfs_map_token token;
3162 u64 extent_end;
3163 u64 extent_offset = 0;
3164 int extent_type;
3165 int del_slot = 0;
3166 int del_nr = 0;
3167 int ret = 0;
3168
3169 while (1) {
3170 btrfs_init_map_token(&token);
3171 leaf = path->nodes[0];
3172 path->slots[0]++;
3173 if (path->slots[0] >= btrfs_header_nritems(leaf)) {
3174 if (del_nr) {
3175 ret = btrfs_del_items(trans, root, path,
3176 del_slot, del_nr);
3177 if (ret)
3178 return ret;
3179 del_nr = 0;
3180 }
3181
3182 ret = btrfs_next_leaf_write(trans, root, path, 1);
3183 if (ret < 0)
3184 return ret;
3185 if (ret > 0)
3186 return 0;
3187 leaf = path->nodes[0];
3188 }
3189
3190 btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
3191 if (key.objectid != btrfs_ino(inode) ||
3192 key.type != BTRFS_EXTENT_DATA_KEY ||
3193 key.offset >= em->start + em->len)
3194 break;
3195
3196 fi = btrfs_item_ptr(leaf, path->slots[0],
3197 struct btrfs_file_extent_item);
3198 extent_type = btrfs_token_file_extent_type(leaf, fi, &token);
3199 if (extent_type == BTRFS_FILE_EXTENT_REG ||
3200 extent_type == BTRFS_FILE_EXTENT_PREALLOC) {
3201 extent_offset = btrfs_token_file_extent_offset(leaf,
3202 fi, &token);
3203 extent_end = key.offset +
3204 btrfs_token_file_extent_num_bytes(leaf, fi,
3205 &token);
3206 } else if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
3207 extent_end = key.offset +
3208 btrfs_file_extent_inline_len(leaf, fi);
3209 } else {
3210 BUG();
3211 }
3212
3213 if (extent_end <= em->len + em->start) {
3214 if (!del_nr) {
3215 del_slot = path->slots[0];
3216 }
3217 del_nr++;
3218 continue;
3219 }
3220
3221 /*
3222 * Ok so we'll ignore previous items if we log a new extent,
3223 * which can lead to overlapping extents, so if we have an
3224 * existing extent we want to adjust we _have_ to check the next
3225 * guy to make sure we even need this extent anymore, this keeps
3226 * us from panicing in set_item_key_safe.
3227 */
3228 if (path->slots[0] < btrfs_header_nritems(leaf) - 1) {
3229 struct btrfs_key tmp_key;
3230
3231 btrfs_item_key_to_cpu(leaf, &tmp_key,
3232 path->slots[0] + 1);
3233 if (tmp_key.objectid == btrfs_ino(inode) &&
3234 tmp_key.type == BTRFS_EXTENT_DATA_KEY &&
3235 tmp_key.offset <= em->start + em->len) {
3236 if (!del_nr)
3237 del_slot = path->slots[0];
3238 del_nr++;
3239 continue;
3240 }
3241 }
3242
3243 BUG_ON(extent_type == BTRFS_FILE_EXTENT_INLINE);
3244 memcpy(&new_key, &key, sizeof(new_key));
3245 new_key.offset = em->start + em->len;
3246 btrfs_set_item_key_safe(trans, root, path, &new_key);
3247 extent_offset += em->start + em->len - key.offset;
3248 btrfs_set_token_file_extent_offset(leaf, fi, extent_offset,
3249 &token);
3250 btrfs_set_token_file_extent_num_bytes(leaf, fi, extent_end -
3251 (em->start + em->len),
3252 &token);
3253 btrfs_mark_buffer_dirty(leaf);
3254 }
3255
3256 if (del_nr)
3257 ret = btrfs_del_items(trans, root, path, del_slot, del_nr);
3258
3259 return ret;
3260}
3159 3261
3160static int log_one_extent(struct btrfs_trans_handle *trans, 3262static int log_one_extent(struct btrfs_trans_handle *trans,
3161 struct inode *inode, struct btrfs_root *root, 3263 struct inode *inode, struct btrfs_root *root,
3162 struct extent_map *em, struct btrfs_path *path, 3264 struct extent_map *em, struct btrfs_path *path)
3163 struct btrfs_path *dst_path, struct log_args *args)
3164{ 3265{
3165 struct btrfs_root *log = root->log_root; 3266 struct btrfs_root *log = root->log_root;
3267 struct btrfs_file_extent_item *fi;
3268 struct extent_buffer *leaf;
3269 struct list_head ordered_sums;
3166 struct btrfs_key key; 3270 struct btrfs_key key;
3167 u64 start = em->mod_start; 3271 u64 csum_offset = em->mod_start - em->start;
3168 u64 search_start = start; 3272 u64 csum_len = em->mod_len;
3169 u64 len = em->mod_len; 3273 u64 extent_offset = em->start - em->orig_start;
3170 u64 num_bytes; 3274 u64 block_len;
3171 int nritems;
3172 int ret; 3275 int ret;
3276 bool skip_csum = BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM;
3173 3277
3174 if (BTRFS_I(inode)->logged_trans == trans->transid) { 3278 INIT_LIST_HEAD(&ordered_sums);
3175 ret = __btrfs_drop_extents(trans, log, inode, dst_path, start, 3279 key.objectid = btrfs_ino(inode);
3176 start + len, NULL, 0); 3280 key.type = BTRFS_EXTENT_DATA_KEY;
3177 if (ret) 3281 key.offset = em->start;
3178 return ret; 3282 path->really_keep_locks = 1;
3283
3284 ret = btrfs_insert_empty_item(trans, log, path, &key, sizeof(*fi));
3285 if (ret && ret != -EEXIST) {
3286 path->really_keep_locks = 0;
3287 return ret;
3288 }
3289 leaf = path->nodes[0];
3290 fi = btrfs_item_ptr(leaf, path->slots[0],
3291 struct btrfs_file_extent_item);
3292 btrfs_set_file_extent_generation(leaf, fi, em->generation);
3293 if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags)) {
3294 skip_csum = true;
3295 btrfs_set_file_extent_type(leaf, fi,
3296 BTRFS_FILE_EXTENT_PREALLOC);
3297 } else {
3298 btrfs_set_file_extent_type(leaf, fi, BTRFS_FILE_EXTENT_REG);
3299 if (em->block_start == 0)
3300 skip_csum = true;
3301 }
3302
3303 block_len = max(em->block_len, em->orig_block_len);
3304 if (em->compress_type != BTRFS_COMPRESS_NONE) {
3305 btrfs_set_file_extent_disk_bytenr(leaf, fi, em->block_start);
3306 btrfs_set_file_extent_disk_num_bytes(leaf, fi, block_len);
3307 } else if (em->block_start < EXTENT_MAP_LAST_BYTE) {
3308 btrfs_set_file_extent_disk_bytenr(leaf, fi,
3309 em->block_start -
3310 extent_offset);
3311 btrfs_set_file_extent_disk_num_bytes(leaf, fi, block_len);
3312 } else {
3313 btrfs_set_file_extent_disk_bytenr(leaf, fi, 0);
3314 btrfs_set_file_extent_disk_num_bytes(leaf, fi, 0);
3179 } 3315 }
3180 3316
3181 while (len) { 3317 btrfs_set_file_extent_offset(leaf, fi, em->start - em->orig_start);
3182 if (args->nr) 3318 btrfs_set_file_extent_num_bytes(leaf, fi, em->len);
3183 goto next_slot; 3319 btrfs_set_file_extent_ram_bytes(leaf, fi, em->len);
3184again: 3320 btrfs_set_file_extent_compression(leaf, fi, em->compress_type);
3185 key.objectid = btrfs_ino(inode); 3321 btrfs_set_file_extent_encryption(leaf, fi, 0);
3186 key.type = BTRFS_EXTENT_DATA_KEY; 3322 btrfs_set_file_extent_other_encoding(leaf, fi, 0);
3187 key.offset = search_start; 3323 btrfs_mark_buffer_dirty(leaf);
3188
3189 ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
3190 if (ret < 0)
3191 return ret;
3192
3193 if (ret) {
3194 /*
3195 * A rare case were we can have an em for a section of a
3196 * larger extent so we need to make sure that this em
3197 * falls within the extent we've found. If not we just
3198 * bail and go back to ye-olde way of doing things but
3199 * it happens often enough in testing that we need to do
3200 * this dance to make sure.
3201 */
3202 do {
3203 if (path->slots[0] == 0) {
3204 btrfs_release_path(path);
3205 if (search_start == 0)
3206 return -ENOENT;
3207 search_start--;
3208 goto again;
3209 }
3210 3324
3211 path->slots[0]--; 3325 /*
3212 btrfs_item_key_to_cpu(path->nodes[0], &key, 3326 * Have to check the extent to the right of us to make sure it doesn't
3213 path->slots[0]); 3327 * fall in our current range. We're ok if the previous extent is in our
3214 if (key.objectid != btrfs_ino(inode) || 3328 * range since the recovery stuff will run us in key order and thus just
3215 key.type != BTRFS_EXTENT_DATA_KEY) { 3329 * drop the part we overwrote.
3216 btrfs_release_path(path); 3330 */
3217 return -ENOENT; 3331 ret = drop_adjacent_extents(trans, log, inode, em, path);
3218 } 3332 btrfs_release_path(path);
3219 } while (key.offset > start); 3333 path->really_keep_locks = 0;
3334 if (ret) {
3335 return ret;
3336 }
3220 3337
3221 num_bytes = btrfs_file_extent_length(path); 3338 if (skip_csum)
3222 if (key.offset + num_bytes <= start) { 3339 return 0;
3223 btrfs_release_path(path);
3224 return -ENOENT;
3225 }
3226 }
3227 args->src = path->nodes[0];
3228next_slot:
3229 btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]);
3230 num_bytes = btrfs_file_extent_length(path);
3231 if (args->nr &&
3232 args->start_slot + args->nr == path->slots[0]) {
3233 args->nr++;
3234 } else if (args->nr) {
3235 ret = copy_items(trans, inode, dst_path, args->src,
3236 args->start_slot, args->nr,
3237 LOG_INODE_ALL);
3238 if (ret)
3239 return ret;
3240 args->nr = 1;
3241 args->start_slot = path->slots[0];
3242 } else if (!args->nr) {
3243 args->nr = 1;
3244 args->start_slot = path->slots[0];
3245 }
3246 nritems = btrfs_header_nritems(path->nodes[0]);
3247 path->slots[0]++;
3248 if (len < num_bytes) {
3249 /* I _think_ this is ok, envision we write to a
3250 * preallocated space that is adjacent to a previously
3251 * written preallocated space that gets merged when we
3252 * mark this preallocated space written. If we do not
3253 * have the adjacent extent in cache then when we copy
3254 * this extent it could end up being larger than our EM
3255 * thinks it is, which is a-ok, so just set len to 0.
3256 */
3257 len = 0;
3258 } else {
3259 len -= num_bytes;
3260 }
3261 start = key.offset + num_bytes;
3262 args->next_offset = start;
3263 search_start = start;
3264 3340
3265 if (path->slots[0] < nritems) { 3341 /* block start is already adjusted for the file extent offset. */
3266 if (len) 3342 ret = btrfs_lookup_csums_range(log->fs_info->csum_root,
3267 goto next_slot; 3343 em->block_start + csum_offset,
3268 break; 3344 em->block_start + csum_offset +
3269 } 3345 csum_len - 1, &ordered_sums, 0);
3346 if (ret)
3347 return ret;
3270 3348
3271 if (args->nr) { 3349 while (!list_empty(&ordered_sums)) {
3272 ret = copy_items(trans, inode, dst_path, args->src, 3350 struct btrfs_ordered_sum *sums = list_entry(ordered_sums.next,
3273 args->start_slot, args->nr, 3351 struct btrfs_ordered_sum,
3274 LOG_INODE_ALL); 3352 list);
3275 if (ret) 3353 if (!ret)
3276 return ret; 3354 ret = btrfs_csum_file_blocks(trans, log, sums);
3277 args->nr = 0; 3355 list_del(&sums->list);
3278 btrfs_release_path(path); 3356 kfree(sums);
3279 }
3280 } 3357 }
3281 3358
3282 return 0; 3359 return ret;
3283} 3360}
3284 3361
3285static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans, 3362static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans,
3286 struct btrfs_root *root, 3363 struct btrfs_root *root,
3287 struct inode *inode, 3364 struct inode *inode,
3288 struct btrfs_path *path, 3365 struct btrfs_path *path)
3289 struct btrfs_path *dst_path)
3290{ 3366{
3291 struct log_args args;
3292 struct extent_map *em, *n; 3367 struct extent_map *em, *n;
3293 struct list_head extents; 3368 struct list_head extents;
3294 struct extent_map_tree *tree = &BTRFS_I(inode)->extent_tree; 3369 struct extent_map_tree *tree = &BTRFS_I(inode)->extent_tree;
@@ -3297,8 +3372,6 @@ static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans,
3297 3372
3298 INIT_LIST_HEAD(&extents); 3373 INIT_LIST_HEAD(&extents);
3299 3374
3300 memset(&args, 0, sizeof(args));
3301
3302 write_lock(&tree->lock); 3375 write_lock(&tree->lock);
3303 test_gen = root->fs_info->last_trans_committed; 3376 test_gen = root->fs_info->last_trans_committed;
3304 3377
@@ -3331,34 +3404,13 @@ static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans,
3331 3404
3332 write_unlock(&tree->lock); 3405 write_unlock(&tree->lock);
3333 3406
3334 /* 3407 ret = log_one_extent(trans, inode, root, em, path);
3335 * If the previous EM and the last extent we left off on aren't
3336 * sequential then we need to copy the items we have and redo
3337 * our search
3338 */
3339 if (args.nr && em->mod_start != args.next_offset) {
3340 ret = copy_items(trans, inode, dst_path, args.src,
3341 args.start_slot, args.nr,
3342 LOG_INODE_ALL);
3343 if (ret) {
3344 free_extent_map(em);
3345 write_lock(&tree->lock);
3346 continue;
3347 }
3348 btrfs_release_path(path);
3349 args.nr = 0;
3350 }
3351
3352 ret = log_one_extent(trans, inode, root, em, path, dst_path, &args);
3353 free_extent_map(em); 3408 free_extent_map(em);
3354 write_lock(&tree->lock); 3409 write_lock(&tree->lock);
3355 } 3410 }
3356 WARN_ON(!list_empty(&extents)); 3411 WARN_ON(!list_empty(&extents));
3357 write_unlock(&tree->lock); 3412 write_unlock(&tree->lock);
3358 3413
3359 if (!ret && args.nr)
3360 ret = copy_items(trans, inode, dst_path, args.src,
3361 args.start_slot, args.nr, LOG_INODE_ALL);
3362 btrfs_release_path(path); 3414 btrfs_release_path(path);
3363 return ret; 3415 return ret;
3364} 3416}
@@ -3551,10 +3603,8 @@ next_slot:
3551 3603
3552log_extents: 3604log_extents:
3553 if (fast_search) { 3605 if (fast_search) {
3554 btrfs_release_path(path);
3555 btrfs_release_path(dst_path); 3606 btrfs_release_path(dst_path);
3556 ret = btrfs_log_changed_extents(trans, root, inode, path, 3607 ret = btrfs_log_changed_extents(trans, root, inode, dst_path);
3557 dst_path);
3558 if (ret) { 3608 if (ret) {
3559 err = ret; 3609 err = ret;
3560 goto out_unlock; 3610 goto out_unlock;
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 886f4ba0f71d..d79b5b620e94 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -4983,6 +4983,7 @@ static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key,
4983 em->bdev = (struct block_device *)map; 4983 em->bdev = (struct block_device *)map;
4984 em->start = logical; 4984 em->start = logical;
4985 em->len = length; 4985 em->len = length;
4986 em->orig_start = 0;
4986 em->block_start = 0; 4987 em->block_start = 0;
4987 em->block_len = em->len; 4988 em->block_len = em->len;
4988 4989