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.c40
1 files changed, 25 insertions, 15 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 8edcdf6910f7..4d7c02258390 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -1641,7 +1641,7 @@ static void btrfs_clear_bit_hook(struct inode *inode,
1641 btrfs_delalloc_release_metadata(inode, len); 1641 btrfs_delalloc_release_metadata(inode, len);
1642 1642
1643 if (root->root_key.objectid != BTRFS_DATA_RELOC_TREE_OBJECTID 1643 if (root->root_key.objectid != BTRFS_DATA_RELOC_TREE_OBJECTID
1644 && do_list) 1644 && do_list && !(state->state & EXTENT_NORESERVE))
1645 btrfs_free_reserved_data_space(inode, len); 1645 btrfs_free_reserved_data_space(inode, len);
1646 1646
1647 __percpu_counter_add(&root->fs_info->delalloc_bytes, -len, 1647 __percpu_counter_add(&root->fs_info->delalloc_bytes, -len,
@@ -6396,10 +6396,10 @@ out:
6396 * returns 1 when the nocow is safe, < 1 on error, 0 if the 6396 * returns 1 when the nocow is safe, < 1 on error, 0 if the
6397 * block must be cow'd 6397 * block must be cow'd
6398 */ 6398 */
6399static noinline int can_nocow_odirect(struct btrfs_trans_handle *trans, 6399noinline int can_nocow_extent(struct btrfs_trans_handle *trans,
6400 struct inode *inode, u64 offset, u64 *len, 6400 struct inode *inode, u64 offset, u64 *len,
6401 u64 *orig_start, u64 *orig_block_len, 6401 u64 *orig_start, u64 *orig_block_len,
6402 u64 *ram_bytes) 6402 u64 *ram_bytes)
6403{ 6403{
6404 struct btrfs_path *path; 6404 struct btrfs_path *path;
6405 int ret; 6405 int ret;
@@ -6413,7 +6413,7 @@ static noinline int can_nocow_odirect(struct btrfs_trans_handle *trans,
6413 u64 num_bytes; 6413 u64 num_bytes;
6414 int slot; 6414 int slot;
6415 int found_type; 6415 int found_type;
6416 6416 bool nocow = (BTRFS_I(inode)->flags & BTRFS_INODE_NODATACOW);
6417 path = btrfs_alloc_path(); 6417 path = btrfs_alloc_path();
6418 if (!path) 6418 if (!path)
6419 return -ENOMEM; 6419 return -ENOMEM;
@@ -6453,18 +6453,28 @@ static noinline int can_nocow_odirect(struct btrfs_trans_handle *trans,
6453 /* not a regular extent, must cow */ 6453 /* not a regular extent, must cow */
6454 goto out; 6454 goto out;
6455 } 6455 }
6456
6457 if (!nocow && found_type == BTRFS_FILE_EXTENT_REG)
6458 goto out;
6459
6456 disk_bytenr = btrfs_file_extent_disk_bytenr(leaf, fi); 6460 disk_bytenr = btrfs_file_extent_disk_bytenr(leaf, fi);
6461 if (disk_bytenr == 0)
6462 goto out;
6463
6464 if (btrfs_file_extent_compression(leaf, fi) ||
6465 btrfs_file_extent_encryption(leaf, fi) ||
6466 btrfs_file_extent_other_encoding(leaf, fi))
6467 goto out;
6468
6457 backref_offset = btrfs_file_extent_offset(leaf, fi); 6469 backref_offset = btrfs_file_extent_offset(leaf, fi);
6458 6470
6459 *orig_start = key.offset - backref_offset; 6471 if (orig_start) {
6460 *orig_block_len = btrfs_file_extent_disk_num_bytes(leaf, fi); 6472 *orig_start = key.offset - backref_offset;
6461 *ram_bytes = btrfs_file_extent_ram_bytes(leaf, fi); 6473 *orig_block_len = btrfs_file_extent_disk_num_bytes(leaf, fi);
6474 *ram_bytes = btrfs_file_extent_ram_bytes(leaf, fi);
6475 }
6462 6476
6463 extent_end = key.offset + btrfs_file_extent_num_bytes(leaf, fi); 6477 extent_end = key.offset + btrfs_file_extent_num_bytes(leaf, fi);
6464 if (extent_end < offset + *len) {
6465 /* extent doesn't include our full range, must cow */
6466 goto out;
6467 }
6468 6478
6469 if (btrfs_extent_readonly(root, disk_bytenr)) 6479 if (btrfs_extent_readonly(root, disk_bytenr))
6470 goto out; 6480 goto out;
@@ -6708,8 +6718,8 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock,
6708 if (IS_ERR(trans)) 6718 if (IS_ERR(trans))
6709 goto must_cow; 6719 goto must_cow;
6710 6720
6711 if (can_nocow_odirect(trans, inode, start, &len, &orig_start, 6721 if (can_nocow_extent(trans, inode, start, &len, &orig_start,
6712 &orig_block_len, &ram_bytes) == 1) { 6722 &orig_block_len, &ram_bytes) == 1) {
6713 if (type == BTRFS_ORDERED_PREALLOC) { 6723 if (type == BTRFS_ORDERED_PREALLOC) {
6714 free_extent_map(em); 6724 free_extent_map(em);
6715 em = create_pinned_em(inode, start, len, 6725 em = create_pinned_em(inode, start, len,