aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/inode.c
diff options
context:
space:
mode:
authorJosef Bacik <jbacik@fusionio.com>2013-06-21 16:37:03 -0400
committerJosef Bacik <jbacik@fusionio.com>2013-07-02 11:50:45 -0400
commit7ee9e4405f264e9eda808aa5ca4522746a1af9c1 (patch)
tree66b0ebcb2594309044e3f25ab6836b09662c7601 /fs/btrfs/inode.c
parent925a6efb8ff0c2bdbec107ed9890e62650c83306 (diff)
Btrfs: check if we can nocow if we don't have data space
We always just try and reserve data space when we write, but if we are out of space but have prealloc'ed extents we should still successfully write. This patch will try and see if we can write to prealloc'ed space and if we can go ahead and allow the write to continue. With this patch we now pass xfstests generic/274. Thanks, Signed-off-by: Josef Bacik <jbacik@fusionio.com>
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,