btrfs: don't reserve space for checksums when writing to nocow files
commit feefe1f49d26bad9d8997096e3a200280fa7b1c5 upstream. 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: Filipe Manana <fdmanana@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
dfd1f44e49
commit
4d6b2e17b5
|
@ -243,7 +243,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);
|
||||||
|
@ -258,10 +257,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
|
||||||
|
@ -276,14 +277,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);
|
||||||
|
|
||||||
|
@ -335,7 +342,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);
|
||||||
|
@ -356,7 +363,8 @@ int btrfs_delalloc_reserve_metadata(struct btrfs_inode *inode, u64 num_bytes,
|
||||||
spin_lock(&inode->lock);
|
spin_lock(&inode->lock);
|
||||||
nr_extents = count_max_extents(fs_info, num_bytes);
|
nr_extents = count_max_extents(fs_info, num_bytes);
|
||||||
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);
|
||||||
|
|
||||||
|
@ -390,7 +398,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);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue