aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/inode.c21
1 files changed, 13 insertions, 8 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 7c4e6ccdba3f..4b5398c9f62b 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -5794,7 +5794,9 @@ out:
5794 * block must be cow'd 5794 * block must be cow'd
5795 */ 5795 */
5796static noinline int can_nocow_odirect(struct btrfs_trans_handle *trans, 5796static noinline int can_nocow_odirect(struct btrfs_trans_handle *trans,
5797 struct inode *inode, u64 offset, u64 len) 5797 struct inode *inode, u64 offset, u64 *len,
5798 u64 *orig_start, u64 *orig_block_len,
5799 u64 *ram_bytes)
5798{ 5800{
5799 struct btrfs_path *path; 5801 struct btrfs_path *path;
5800 int ret; 5802 int ret;
@@ -5851,8 +5853,12 @@ static noinline int can_nocow_odirect(struct btrfs_trans_handle *trans,
5851 disk_bytenr = btrfs_file_extent_disk_bytenr(leaf, fi); 5853 disk_bytenr = btrfs_file_extent_disk_bytenr(leaf, fi);
5852 backref_offset = btrfs_file_extent_offset(leaf, fi); 5854 backref_offset = btrfs_file_extent_offset(leaf, fi);
5853 5855
5856 *orig_start = key.offset - backref_offset;
5857 *orig_block_len = btrfs_file_extent_disk_num_bytes(leaf, fi);
5858 *ram_bytes = btrfs_file_extent_ram_bytes(leaf, fi);
5859
5854 extent_end = key.offset + btrfs_file_extent_num_bytes(leaf, fi); 5860 extent_end = key.offset + btrfs_file_extent_num_bytes(leaf, fi);
5855 if (extent_end < offset + len) { 5861 if (extent_end < offset + *len) {
5856 /* extent doesn't include our full range, must cow */ 5862 /* extent doesn't include our full range, must cow */
5857 goto out; 5863 goto out;
5858 } 5864 }
@@ -5876,13 +5882,14 @@ static noinline int can_nocow_odirect(struct btrfs_trans_handle *trans,
5876 */ 5882 */
5877 disk_bytenr += backref_offset; 5883 disk_bytenr += backref_offset;
5878 disk_bytenr += offset - key.offset; 5884 disk_bytenr += offset - key.offset;
5879 num_bytes = min(offset + len, extent_end) - offset; 5885 num_bytes = min(offset + *len, extent_end) - offset;
5880 if (csum_exist_in_range(root, disk_bytenr, num_bytes)) 5886 if (csum_exist_in_range(root, disk_bytenr, num_bytes))
5881 goto out; 5887 goto out;
5882 /* 5888 /*
5883 * all of the above have passed, it is safe to overwrite this extent 5889 * all of the above have passed, it is safe to overwrite this extent
5884 * without cow 5890 * without cow
5885 */ 5891 */
5892 *len = num_bytes;
5886 ret = 1; 5893 ret = 1;
5887out: 5894out:
5888 btrfs_free_path(path); 5895 btrfs_free_path(path);
@@ -6092,7 +6099,7 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock,
6092 em->block_start != EXTENT_MAP_HOLE)) { 6099 em->block_start != EXTENT_MAP_HOLE)) {
6093 int type; 6100 int type;
6094 int ret; 6101 int ret;
6095 u64 block_start; 6102 u64 block_start, orig_start, orig_block_len, ram_bytes;
6096 6103
6097 if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags)) 6104 if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags))
6098 type = BTRFS_ORDERED_PREALLOC; 6105 type = BTRFS_ORDERED_PREALLOC;
@@ -6110,10 +6117,8 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock,
6110 if (IS_ERR(trans)) 6117 if (IS_ERR(trans))
6111 goto must_cow; 6118 goto must_cow;
6112 6119
6113 if (can_nocow_odirect(trans, inode, start, len) == 1) { 6120 if (can_nocow_odirect(trans, inode, start, &len, &orig_start,
6114 u64 orig_start = em->orig_start; 6121 &orig_block_len, &ram_bytes) == 1) {
6115 u64 orig_block_len = em->orig_block_len;
6116
6117 if (type == BTRFS_ORDERED_PREALLOC) { 6122 if (type == BTRFS_ORDERED_PREALLOC) {
6118 free_extent_map(em); 6123 free_extent_map(em);
6119 em = create_pinned_em(inode, start, len, 6124 em = create_pinned_em(inode, start, len,