diff options
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 22 |
1 files changed, 13 insertions, 9 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index d65a55c9be8a..33a9e9da726d 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -6504,7 +6504,9 @@ out: | |||
6504 | * block must be cow'd | 6504 | * block must be cow'd |
6505 | */ | 6505 | */ |
6506 | static noinline int can_nocow_odirect(struct btrfs_trans_handle *trans, | 6506 | static noinline int can_nocow_odirect(struct btrfs_trans_handle *trans, |
6507 | struct inode *inode, u64 offset, u64 len) | 6507 | struct inode *inode, u64 offset, u64 *len, |
6508 | u64 *orig_start, u64 *orig_block_len, | ||
6509 | u64 *ram_bytes) | ||
6508 | { | 6510 | { |
6509 | struct btrfs_path *path; | 6511 | struct btrfs_path *path; |
6510 | int ret; | 6512 | int ret; |
@@ -6561,8 +6563,12 @@ static noinline int can_nocow_odirect(struct btrfs_trans_handle *trans, | |||
6561 | disk_bytenr = btrfs_file_extent_disk_bytenr(leaf, fi); | 6563 | disk_bytenr = btrfs_file_extent_disk_bytenr(leaf, fi); |
6562 | backref_offset = btrfs_file_extent_offset(leaf, fi); | 6564 | backref_offset = btrfs_file_extent_offset(leaf, fi); |
6563 | 6565 | ||
6566 | *orig_start = key.offset - backref_offset; | ||
6567 | *orig_block_len = btrfs_file_extent_disk_num_bytes(leaf, fi); | ||
6568 | *ram_bytes = btrfs_file_extent_ram_bytes(leaf, fi); | ||
6569 | |||
6564 | extent_end = key.offset + btrfs_file_extent_num_bytes(leaf, fi); | 6570 | extent_end = key.offset + btrfs_file_extent_num_bytes(leaf, fi); |
6565 | if (extent_end < offset + len) { | 6571 | if (extent_end < offset + *len) { |
6566 | /* extent doesn't include our full range, must cow */ | 6572 | /* extent doesn't include our full range, must cow */ |
6567 | goto out; | 6573 | goto out; |
6568 | } | 6574 | } |
@@ -6586,13 +6592,14 @@ static noinline int can_nocow_odirect(struct btrfs_trans_handle *trans, | |||
6586 | */ | 6592 | */ |
6587 | disk_bytenr += backref_offset; | 6593 | disk_bytenr += backref_offset; |
6588 | disk_bytenr += offset - key.offset; | 6594 | disk_bytenr += offset - key.offset; |
6589 | num_bytes = min(offset + len, extent_end) - offset; | 6595 | num_bytes = min(offset + *len, extent_end) - offset; |
6590 | if (csum_exist_in_range(root, disk_bytenr, num_bytes)) | 6596 | if (csum_exist_in_range(root, disk_bytenr, num_bytes)) |
6591 | goto out; | 6597 | goto out; |
6592 | /* | 6598 | /* |
6593 | * all of the above have passed, it is safe to overwrite this extent | 6599 | * all of the above have passed, it is safe to overwrite this extent |
6594 | * without cow | 6600 | * without cow |
6595 | */ | 6601 | */ |
6602 | *len = num_bytes; | ||
6596 | ret = 1; | 6603 | ret = 1; |
6597 | out: | 6604 | out: |
6598 | btrfs_free_path(path); | 6605 | btrfs_free_path(path); |
@@ -6790,7 +6797,7 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock, | |||
6790 | em->block_start != EXTENT_MAP_HOLE)) { | 6797 | em->block_start != EXTENT_MAP_HOLE)) { |
6791 | int type; | 6798 | int type; |
6792 | int ret; | 6799 | int ret; |
6793 | u64 block_start; | 6800 | u64 block_start, orig_start, orig_block_len, ram_bytes; |
6794 | 6801 | ||
6795 | if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags)) | 6802 | if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags)) |
6796 | type = BTRFS_ORDERED_PREALLOC; | 6803 | type = BTRFS_ORDERED_PREALLOC; |
@@ -6808,11 +6815,8 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock, | |||
6808 | if (IS_ERR(trans)) | 6815 | if (IS_ERR(trans)) |
6809 | goto must_cow; | 6816 | goto must_cow; |
6810 | 6817 | ||
6811 | if (can_nocow_odirect(trans, inode, start, len) == 1) { | 6818 | if (can_nocow_odirect(trans, inode, start, &len, &orig_start, |
6812 | u64 orig_start = em->orig_start; | 6819 | &orig_block_len, &ram_bytes) == 1) { |
6813 | u64 orig_block_len = em->orig_block_len; | ||
6814 | u64 ram_bytes = em->ram_bytes; | ||
6815 | |||
6816 | if (type == BTRFS_ORDERED_PREALLOC) { | 6820 | if (type == BTRFS_ORDERED_PREALLOC) { |
6817 | free_extent_map(em); | 6821 | free_extent_map(em); |
6818 | em = create_pinned_em(inode, start, len, | 6822 | em = create_pinned_em(inode, start, len, |