Re: [PATCH 2/2] btrfs: Don't set SHAREABLE flag for data reloc tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




On 13.05.20 г. 9:16 ч., Qu Wenruo wrote:
> SHAREABLE flag is set for subvolumes because users can create snapshot
> for subvolumes, thus sharing tree blocks of them.
> 
> But users can't access data reloc tree as it's only an internal tree for
> data relocation, thus it doesn't need the full path replacement treat at
> all.
> 
> This patch will make data reloc tree just a non-shareable tree, and add
> btrfs_fs_info::dreloc_root for data reloc tree, so relocation code can
> grab it from fs_info directly.
> 
> This would slightly improve tree relocation, as now data reloc tree
> can go through regular COW routine to get relocated, without bothering
> the complex tree reloc tree routine.
> 
> Signed-off-by: Qu Wenruo <wqu@xxxxxxxx>
> ---
>  fs/btrfs/ctree.h      |  1 +
>  fs/btrfs/disk-io.c    | 14 +++++++++++++-
>  fs/btrfs/inode.c      |  7 ++++---
>  fs/btrfs/relocation.c | 18 ++++--------------
>  4 files changed, 22 insertions(+), 18 deletions(-)
> 
> diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
> index 65c09aea4cb9..a9690f438a15 100644
> --- a/fs/btrfs/ctree.h
> +++ b/fs/btrfs/ctree.h
> @@ -582,6 +582,7 @@ struct btrfs_fs_info {
>  	struct btrfs_root *quota_root;
>  	struct btrfs_root *uuid_root;
>  	struct btrfs_root *free_space_root;
> +	struct btrfs_root *dreloc_root;

Rename this to data_reloc_root or simply reloc_root, dreloc is rather
cryptic.
>  
>  	/* the log root tree is a directory of all the other log roots */
>  	struct btrfs_root *log_root_tree;
> diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
> index 4dd3206c1ace..7355ebc648c5 100644
> --- a/fs/btrfs/disk-io.c
> +++ b/fs/btrfs/disk-io.c
> @@ -1419,7 +1419,8 @@ static int btrfs_init_fs_root(struct btrfs_root *root)
>  	if (ret)
>  		goto fail;
>  
> -	if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID) {
> +	if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID &&
> +	    root->root_key.objectid != BTRFS_DATA_RELOC_TREE_OBJECTID) {
>  		set_bit(BTRFS_ROOT_SHAREABLE, &root->state);
>  		btrfs_check_and_init_root_item(&root->root_item);
>  	}
> @@ -1525,6 +1526,7 @@ void btrfs_free_fs_info(struct btrfs_fs_info *fs_info)
>  	btrfs_put_root(fs_info->uuid_root);
>  	btrfs_put_root(fs_info->free_space_root);
>  	btrfs_put_root(fs_info->fs_root);
> +	btrfs_put_root(fs_info->dreloc_root);
>  	btrfs_check_leaked_roots(fs_info);
>  	btrfs_extent_buffer_leak_debug_check(fs_info);
>  	kfree(fs_info->super_copy);
> @@ -1981,6 +1983,7 @@ static void free_root_pointers(struct btrfs_fs_info *info, bool free_chunk_root)
>  	free_root_extent_buffers(info->quota_root);
>  	free_root_extent_buffers(info->uuid_root);
>  	free_root_extent_buffers(info->fs_root);
> +	free_root_extent_buffers(info->dreloc_root);
>  	if (free_chunk_root)
>  		free_root_extent_buffers(info->chunk_root);
>  	free_root_extent_buffers(info->free_space_root);
> @@ -2287,6 +2290,15 @@ static int btrfs_read_roots(struct btrfs_fs_info *fs_info)
>  	set_bit(BTRFS_ROOT_TRACK_DIRTY, &root->state);
>  	fs_info->csum_root = root;
>  
> +	location.objectid = BTRFS_DATA_RELOC_TREE_OBJECTID;
> +	root = btrfs_get_fs_root(fs_info, &location, true);
> +	if (IS_ERR(root)) {
> +		ret = PTR_ERR(root);
> +		goto out;
> +	}
> +	set_bit(BTRFS_ROOT_TRACK_DIRTY, &root->state);
> +	fs_info->dreloc_root = root;
> +
>  	location.objectid = BTRFS_QUOTA_TREE_OBJECTID;
>  	root = btrfs_read_tree_root(tree_root, &location);
>  	if (!IS_ERR(root)) {
> diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
> index 13bbb6b0d495..6b7ba20eee52 100644
> --- a/fs/btrfs/inode.c
> +++ b/fs/btrfs/inode.c
> @@ -4133,7 +4133,7 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
>  	 * inode.
>  	 */
>  	if (test_bit(BTRFS_ROOT_SHAREABLE, &root->state) ||
> -	    root == fs_info->tree_root)
> +	    root == fs_info->tree_root || root == fs_info->dreloc_root)
>  		btrfs_drop_extent_cache(BTRFS_I(inode), ALIGN(new_size,
>  					fs_info->sectorsize),
>  					(u64)-1, 0);
> @@ -4338,7 +4338,8 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
>  
>  		if (found_extent &&
>  		    (test_bit(BTRFS_ROOT_SHAREABLE, &root->state) ||
> -		     root == fs_info->tree_root)) {
> +		     root == fs_info->tree_root ||
> +		     root == fs_info->dreloc_root)) {
>  			struct btrfs_ref ref = { 0 };
>  
>  			bytes_deleted += extent_num_bytes;
> @@ -5046,7 +5047,7 @@ void btrfs_evict_inode(struct inode *inode)
>  		btrfs_end_transaction(trans);
>  	}
>  
> -	if (!(root == fs_info->tree_root ||
> +	if (!(root == fs_info->tree_root || root == fs_info->dreloc_root ||
>  	      root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID))
>  		btrfs_return_ino(root, btrfs_ino(BTRFS_I(inode)));
>  
> diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
> index 437b782c57e6..cb45ae92f15d 100644
> --- a/fs/btrfs/relocation.c
> +++ b/fs/btrfs/relocation.c
> @@ -1087,7 +1087,8 @@ int replace_file_extents(struct btrfs_trans_handle *trans,
>  		 * if we are modifying block in fs tree, wait for readpage
>  		 * to complete and drop the extent cache
>  		 */
> -		if (root->root_key.objectid != BTRFS_TREE_RELOC_OBJECTID) {
> +		if (root->root_key.objectid != BTRFS_TREE_RELOC_OBJECTID &&
> +		    root->root_key.objectid != BTRFS_DATA_RELOC_TREE_OBJECTID) {
>  			if (first) {
>  				inode = find_next_inode(root, key.objectid);
>  				first = 0;
> @@ -3470,15 +3471,11 @@ struct inode *create_reloc_inode(struct btrfs_fs_info *fs_info,
>  {
>  	struct inode *inode = NULL;
>  	struct btrfs_trans_handle *trans;
> -	struct btrfs_root *root;
> +	struct btrfs_root *root = fs_info->dreloc_root;

So why haven't you added code in btrfs_get_fs_root to quickly return a
refcounted root and instead reference it without incrementing the refcount?

>  	struct btrfs_key key;
>  	u64 objectid;
>  	int err = 0;
>  
> -	root = read_fs_root(fs_info, BTRFS_DATA_RELOC_TREE_OBJECTID);
> -	if (IS_ERR(root))
> -		return ERR_CAST(root);
> -
>  	trans = btrfs_start_transaction(root, 6);
>  	if (IS_ERR(trans)) {
>  		btrfs_put_root(root);
> @@ -3501,7 +3498,6 @@ struct inode *create_reloc_inode(struct btrfs_fs_info *fs_info,
>  
>  	err = btrfs_orphan_add(trans, BTRFS_I(inode));
>  out:
> -	btrfs_put_root(root);
>  	btrfs_end_transaction(trans);
>  	btrfs_btree_balance_dirty(fs_info);
>  	if (err) {
> @@ -3870,13 +3866,7 @@ int btrfs_recover_relocation(struct btrfs_root *root)
>  
>  	if (err == 0) {
>  		/* cleanup orphan inode in data relocation tree */
> -		fs_root = read_fs_root(fs_info, BTRFS_DATA_RELOC_TREE_OBJECTID);
> -		if (IS_ERR(fs_root)) {
> -			err = PTR_ERR(fs_root);
> -		} else {
> -			err = btrfs_orphan_cleanup(fs_root);
> -			btrfs_put_root(fs_root);
> -		}
> +		err = btrfs_orphan_cleanup(fs_info->dreloc_root);
>  	}
>  	return err;
>  }
> 



[Index of Archives]     [Linux Filesystem Development]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux