Commit feefe1f4 authored by Filipe Manana's avatar Filipe Manana Committed by David Sterba

btrfs: don't reserve space for checksums when writing to nocow files

Currently when doing a write to a file we always reserve metadata space
for inserting data checksums. However we don't need to do it if we have
a nodatacow file (-o nodatacow mount option or chattr +C) or if checksums
are disabled (-o nodatasum mount option), as in that case we are only
adding unnecessary pressure to metadata reservations.

For example on x86_64, with the default node size of 16K, a 4K buffered
write into a nodatacow file is reserving 655360 bytes of metadata space,
as it's accounting for checksums. After this change, which stops reserving
space for checksums if we have a nodatacow file or checksums are disabled,
we only need to reserve 393216 bytes of metadata.

CC: stable@vger.kernel.org # 6.1+
Signed-off-by: default avatarFilipe Manana <fdmanana@suse.com>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 12c5128f
...@@ -245,7 +245,6 @@ static void btrfs_calculate_inode_block_rsv_size(struct btrfs_fs_info *fs_info, ...@@ -245,7 +245,6 @@ static void btrfs_calculate_inode_block_rsv_size(struct btrfs_fs_info *fs_info,
struct btrfs_block_rsv *block_rsv = &inode->block_rsv; struct btrfs_block_rsv *block_rsv = &inode->block_rsv;
u64 reserve_size = 0; u64 reserve_size = 0;
u64 qgroup_rsv_size = 0; u64 qgroup_rsv_size = 0;
u64 csum_leaves;
unsigned outstanding_extents; unsigned outstanding_extents;
lockdep_assert_held(&inode->lock); lockdep_assert_held(&inode->lock);
...@@ -260,10 +259,12 @@ static void btrfs_calculate_inode_block_rsv_size(struct btrfs_fs_info *fs_info, ...@@ -260,10 +259,12 @@ static void btrfs_calculate_inode_block_rsv_size(struct btrfs_fs_info *fs_info,
outstanding_extents); outstanding_extents);
reserve_size += btrfs_calc_metadata_size(fs_info, 1); reserve_size += btrfs_calc_metadata_size(fs_info, 1);
} }
csum_leaves = btrfs_csum_bytes_to_leaves(fs_info, if (!(inode->flags & BTRFS_INODE_NODATASUM)) {
inode->csum_bytes); u64 csum_leaves;
reserve_size += btrfs_calc_insert_metadata_size(fs_info,
csum_leaves); csum_leaves = btrfs_csum_bytes_to_leaves(fs_info, inode->csum_bytes);
reserve_size += btrfs_calc_insert_metadata_size(fs_info, csum_leaves);
}
/* /*
* For qgroup rsv, the calculation is very simple: * For qgroup rsv, the calculation is very simple:
* account one nodesize for each outstanding extent * account one nodesize for each outstanding extent
...@@ -278,14 +279,20 @@ static void btrfs_calculate_inode_block_rsv_size(struct btrfs_fs_info *fs_info, ...@@ -278,14 +279,20 @@ static void btrfs_calculate_inode_block_rsv_size(struct btrfs_fs_info *fs_info,
spin_unlock(&block_rsv->lock); spin_unlock(&block_rsv->lock);
} }
static void calc_inode_reservations(struct btrfs_fs_info *fs_info, static void calc_inode_reservations(struct btrfs_inode *inode,
u64 num_bytes, u64 disk_num_bytes, u64 num_bytes, u64 disk_num_bytes,
u64 *meta_reserve, u64 *qgroup_reserve) u64 *meta_reserve, u64 *qgroup_reserve)
{ {
struct btrfs_fs_info *fs_info = inode->root->fs_info;
u64 nr_extents = count_max_extents(fs_info, num_bytes); u64 nr_extents = count_max_extents(fs_info, num_bytes);
u64 csum_leaves = btrfs_csum_bytes_to_leaves(fs_info, disk_num_bytes); u64 csum_leaves;
u64 inode_update = btrfs_calc_metadata_size(fs_info, 1); u64 inode_update = btrfs_calc_metadata_size(fs_info, 1);
if (inode->flags & BTRFS_INODE_NODATASUM)
csum_leaves = 0;
else
csum_leaves = btrfs_csum_bytes_to_leaves(fs_info, disk_num_bytes);
*meta_reserve = btrfs_calc_insert_metadata_size(fs_info, *meta_reserve = btrfs_calc_insert_metadata_size(fs_info,
nr_extents + csum_leaves); nr_extents + csum_leaves);
...@@ -337,7 +344,7 @@ int btrfs_delalloc_reserve_metadata(struct btrfs_inode *inode, u64 num_bytes, ...@@ -337,7 +344,7 @@ int btrfs_delalloc_reserve_metadata(struct btrfs_inode *inode, u64 num_bytes,
* everything out and try again, which is bad. This way we just * everything out and try again, which is bad. This way we just
* over-reserve slightly, and clean up the mess when we are done. * over-reserve slightly, and clean up the mess when we are done.
*/ */
calc_inode_reservations(fs_info, num_bytes, disk_num_bytes, calc_inode_reservations(inode, num_bytes, disk_num_bytes,
&meta_reserve, &qgroup_reserve); &meta_reserve, &qgroup_reserve);
ret = btrfs_qgroup_reserve_meta_prealloc(root, qgroup_reserve, true, ret = btrfs_qgroup_reserve_meta_prealloc(root, qgroup_reserve, true,
noflush); noflush);
...@@ -359,7 +366,8 @@ int btrfs_delalloc_reserve_metadata(struct btrfs_inode *inode, u64 num_bytes, ...@@ -359,7 +366,8 @@ int btrfs_delalloc_reserve_metadata(struct btrfs_inode *inode, u64 num_bytes,
nr_extents = count_max_extents(fs_info, num_bytes); nr_extents = count_max_extents(fs_info, num_bytes);
spin_lock(&inode->lock); spin_lock(&inode->lock);
btrfs_mod_outstanding_extents(inode, nr_extents); btrfs_mod_outstanding_extents(inode, nr_extents);
inode->csum_bytes += disk_num_bytes; if (!(inode->flags & BTRFS_INODE_NODATASUM))
inode->csum_bytes += disk_num_bytes;
btrfs_calculate_inode_block_rsv_size(fs_info, inode); btrfs_calculate_inode_block_rsv_size(fs_info, inode);
spin_unlock(&inode->lock); spin_unlock(&inode->lock);
...@@ -393,7 +401,8 @@ void btrfs_delalloc_release_metadata(struct btrfs_inode *inode, u64 num_bytes, ...@@ -393,7 +401,8 @@ void btrfs_delalloc_release_metadata(struct btrfs_inode *inode, u64 num_bytes,
num_bytes = ALIGN(num_bytes, fs_info->sectorsize); num_bytes = ALIGN(num_bytes, fs_info->sectorsize);
spin_lock(&inode->lock); spin_lock(&inode->lock);
inode->csum_bytes -= num_bytes; if (!(inode->flags & BTRFS_INODE_NODATASUM))
inode->csum_bytes -= num_bytes;
btrfs_calculate_inode_block_rsv_size(fs_info, inode); btrfs_calculate_inode_block_rsv_size(fs_info, inode);
spin_unlock(&inode->lock); spin_unlock(&inode->lock);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment