diff options
-rw-r--r-- | fs/btrfs/ctree.c | 133 | ||||
-rw-r--r-- | fs/btrfs/ctree.h | 3 | ||||
-rw-r--r-- | fs/btrfs/extent_map.c | 20 | ||||
-rw-r--r-- | fs/btrfs/file.c | 2 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 85 | ||||
-rw-r--r-- | fs/btrfs/tree-log.c | 338 | ||||
-rw-r--r-- | fs/btrfs/volumes.c | 1 |
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 */ | ||
5494 | static 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 | */ | ||
5521 | int 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)) { | ||
5542 | search: | ||
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; | ||
5581 | cow_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 | |||
5619 | out: | ||
5620 | if (ret) | ||
5621 | btrfs_release_path(path); | ||
5622 | |||
5623 | return ret; | ||
5624 | } | ||
5625 | |||
5493 | int btrfs_next_old_leaf(struct btrfs_root *root, struct btrfs_path *path, | 5626 | int 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 | ||
3189 | int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path); | 3189 | int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path); |
3190 | int btrfs_next_leaf_write(struct btrfs_trans_handle *trans, | ||
3191 | struct btrfs_root *root, struct btrfs_path *path, | ||
3192 | int del); | ||
3190 | int btrfs_next_old_leaf(struct btrfs_root *root, struct btrfs_path *path, | 3193 | int btrfs_next_old_leaf(struct btrfs_root *root, struct btrfs_path *path, |
3191 | u64 time_seq); | 3194 | u64 time_seq); |
3192 | static inline int btrfs_next_old_item(struct btrfs_root *root, | 3195 | static 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) | |||
49 | struct extent_map *alloc_extent_map(void) | 49 | struct 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); |
98 | static 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 | ||
99 | static int btrfs_init_inode_security(struct btrfs_trans_handle *trans, | 103 | static 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 | } |
5477 | not_found: | 5494 | not_found: |
5478 | em->start = start; | 5495 | em->start = start; |
5496 | em->orig_start = start; | ||
5479 | em->len = len; | 5497 | em->len = len; |
5480 | not_found_em: | 5498 | not_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 | ||
5679 | static struct extent_map *btrfs_new_extent_direct(struct inode *inode, | 5697 | static 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 | ||
3153 | struct log_args { | 3153 | static 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 | ||
3160 | static int log_one_extent(struct btrfs_trans_handle *trans, | 3262 | static 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); |
3184 | again: | 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]; | ||
3228 | next_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 | ||
3285 | static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans, | 3362 | static 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 | ||
3552 | log_extents: | 3604 | log_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 | ||