aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r--fs/btrfs/inode.c22
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 */
6506static noinline int can_nocow_odirect(struct btrfs_trans_handle *trans, 6506static 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;
6597out: 6604out:
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,