diff options
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 85 |
1 files changed, 32 insertions, 53 deletions
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; |