mirror of
https://github.com/torvalds/linux.git
synced 2025-11-03 10:10:33 +02:00
There are several things not ideal in copy_one_range(): - Unnecessary temporary variables * block_offset * reserve_bytes * dirty_blocks * num_blocks * release_bytes These are utilized to handle short-copy cases. - Inconsistent handling of btrfs_delalloc_release_extents() There is a hidden behavior that, after reserving metadata for X bytes of data write, we have to call btrfs_delalloc_release_extents() with X once and only once. Calling btrfs_delalloc_release_extents(X - 4K) and btrfs_delalloc_release_extents(4K) will cause outstanding extents accounting to go wrong. This is because the outstanding extents mechanism is not designed to handle shrinking of reserved space. Improve above situations by: - Use a single @reserved_start and @reserved_len pair Now we reserve space for the initial range, and if a short copy happened and we need to shrink the reserved space, we can easily calculate the new length, and update @reserved_len. - Introduce helpers to shrink reserved data and metadata space This is done by two new helpers, shrink_reserved_space() and btrfs_delalloc_shrink_extents(). The later will do a better calculation if we need to modify the outstanding extents, and the first one will be utilized inside copy_one_range(). - Manually unlock, release reserved space and return if no byte is copied Reviewed-by: Filipe Manana <fdmanana@suse.com> Signed-off-by: Qu Wenruo <wqu@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
32 lines
1.3 KiB
C
32 lines
1.3 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
|
|
#ifndef BTRFS_DELALLOC_SPACE_H
|
|
#define BTRFS_DELALLOC_SPACE_H
|
|
|
|
#include <linux/types.h>
|
|
|
|
struct extent_changeset;
|
|
struct btrfs_inode;
|
|
struct btrfs_fs_info;
|
|
|
|
int btrfs_alloc_data_chunk_ondemand(const struct btrfs_inode *inode, u64 bytes);
|
|
int btrfs_check_data_free_space(struct btrfs_inode *inode,
|
|
struct extent_changeset **reserved, u64 start, u64 len,
|
|
bool noflush);
|
|
void btrfs_free_reserved_data_space(struct btrfs_inode *inode,
|
|
struct extent_changeset *reserved, u64 start, u64 len);
|
|
void btrfs_delalloc_release_space(struct btrfs_inode *inode,
|
|
struct extent_changeset *reserved,
|
|
u64 start, u64 len, bool qgroup_free);
|
|
void btrfs_free_reserved_data_space_noquota(struct btrfs_fs_info *fs_info,
|
|
u64 len);
|
|
void btrfs_delalloc_release_metadata(struct btrfs_inode *inode, u64 num_bytes,
|
|
bool qgroup_free);
|
|
int btrfs_delalloc_reserve_space(struct btrfs_inode *inode,
|
|
struct extent_changeset **reserved, u64 start, u64 len);
|
|
int btrfs_delalloc_reserve_metadata(struct btrfs_inode *inode, u64 num_bytes,
|
|
u64 disk_num_bytes, bool noflush);
|
|
void btrfs_delalloc_release_extents(struct btrfs_inode *inode, u64 num_bytes);
|
|
void btrfs_delalloc_shrink_extents(struct btrfs_inode *inode, u64 reserved_len, u64 new_len);
|
|
|
|
#endif /* BTRFS_DELALLOC_SPACE_H */
|