btrfs: extent-tree: Fix a bug that btrfs is unable to add pinned bytes
diff mbox series

Message ID 20190510044505.17422-1-wqu@suse.com
State New
Headers show
Series
  • btrfs: extent-tree: Fix a bug that btrfs is unable to add pinned bytes
Related show

Commit Message

Qu Wenruo May 10, 2019, 4:45 a.m. UTC
Commit ddf30cf03fb5 ("btrfs: extent-tree: Use btrfs_ref to refactor
add_pinned_bytes()") refactored add_pinned_bytes(), but during that
refactor, there are two callers which add the pinned bytes instead
of subtracting.

That refactor misses those two caller, causing incorrect pinned bytes
calculation and resulting unexpected ENOSPC error.

Fix it by adding a new parameter @sign to restore the original behavior.

Reported-by: kernel test robot <rong.a.chen@intel.com>
Fixes: ddf30cf03fb5 ("btrfs: extent-tree: Use btrfs_ref to refactor add_pinned_bytes()")
Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 fs/btrfs/extent-tree.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

Comments

Qu Wenruo May 13, 2019, 2:37 a.m. UTC | #1
On 2019/5/10 下午12:45, Qu Wenruo wrote:
> Commit ddf30cf03fb5 ("btrfs: extent-tree: Use btrfs_ref to refactor
> add_pinned_bytes()") refactored add_pinned_bytes(), but during that
> refactor, there are two callers which add the pinned bytes instead
> of subtracting.
> 
> That refactor misses those two caller, causing incorrect pinned bytes
> calculation and resulting unexpected ENOSPC error.
> 
> Fix it by adding a new parameter @sign to restore the original behavior.
> 
> Reported-by: kernel test robot <rong.a.chen@intel.com>
> Fixes: ddf30cf03fb5 ("btrfs: extent-tree: Use btrfs_ref to refactor add_pinned_bytes()")

Gentle ping.

This patch is needed to fix generic/108 and should reach current rc.

Thanks,
Qu

> Signed-off-by: Qu Wenruo <wqu@suse.com>
> ---
>  fs/btrfs/extent-tree.c | 12 +++++++-----
>  1 file changed, 7 insertions(+), 5 deletions(-)
> 
> diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
> index f79e477a378e..8592d31e321c 100644
> --- a/fs/btrfs/extent-tree.c
> +++ b/fs/btrfs/extent-tree.c
> @@ -757,12 +757,14 @@ static struct btrfs_space_info *__find_space_info(struct btrfs_fs_info *info,
>  }
>  
>  static void add_pinned_bytes(struct btrfs_fs_info *fs_info,
> -			     struct btrfs_ref *ref)
> +			     struct btrfs_ref *ref, int sign)
>  {
>  	struct btrfs_space_info *space_info;
> -	s64 num_bytes = -ref->len;
> +	s64 num_bytes;
>  	u64 flags;
>  
> +	ASSERT(sign == 1 || sign == -1);
> +	num_bytes = sign * ref->len;
>  	if (ref->type == BTRFS_REF_METADATA) {
>  		if (ref->tree_ref.root == BTRFS_CHUNK_TREE_OBJECTID)
>  			flags = BTRFS_BLOCK_GROUP_SYSTEM;
> @@ -2063,7 +2065,7 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
>  	btrfs_ref_tree_mod(fs_info, generic_ref);
>  
>  	if (ret == 0 && old_ref_mod < 0 && new_ref_mod >= 0)
> -		add_pinned_bytes(fs_info, generic_ref);
> +		add_pinned_bytes(fs_info, generic_ref, -1);
>  
>  	return ret;
>  }
> @@ -7190,7 +7192,7 @@ void btrfs_free_tree_block(struct btrfs_trans_handle *trans,
>  	}
>  out:
>  	if (pin)
> -		add_pinned_bytes(fs_info, &generic_ref);
> +		add_pinned_bytes(fs_info, &generic_ref, 1);
>  
>  	if (last_ref) {
>  		/*
> @@ -7238,7 +7240,7 @@ int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_ref *ref)
>  		btrfs_ref_tree_mod(fs_info, ref);
>  
>  	if (ret == 0 && old_ref_mod >= 0 && new_ref_mod < 0)
> -		add_pinned_bytes(fs_info, ref);
> +		add_pinned_bytes(fs_info, ref, 1);
>  
>  	return ret;
>  }
>
David Sterba May 14, 2019, 5:29 p.m. UTC | #2
On Fri, May 10, 2019 at 12:45:05PM +0800, Qu Wenruo wrote:
> Commit ddf30cf03fb5 ("btrfs: extent-tree: Use btrfs_ref to refactor
> add_pinned_bytes()") refactored add_pinned_bytes(), but during that
> refactor, there are two callers which add the pinned bytes instead
> of subtracting.
> 
> That refactor misses those two caller, causing incorrect pinned bytes
> calculation and resulting unexpected ENOSPC error.
> 
> Fix it by adding a new parameter @sign to restore the original behavior.
> 
> Reported-by: kernel test robot <rong.a.chen@intel.com>
> Fixes: ddf30cf03fb5 ("btrfs: extent-tree: Use btrfs_ref to refactor add_pinned_bytes()")
> Signed-off-by: Qu Wenruo <wqu@suse.com>
> ---
>  fs/btrfs/extent-tree.c | 12 +++++++-----
>  1 file changed, 7 insertions(+), 5 deletions(-)
> 
> diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
> index f79e477a378e..8592d31e321c 100644
> --- a/fs/btrfs/extent-tree.c
> +++ b/fs/btrfs/extent-tree.c
> @@ -757,12 +757,14 @@ static struct btrfs_space_info *__find_space_info(struct btrfs_fs_info *info,
>  }
>  
>  static void add_pinned_bytes(struct btrfs_fs_info *fs_info,
> -			     struct btrfs_ref *ref)
> +			     struct btrfs_ref *ref, int sign)

This does not look like a good API, can it be done with a separate
function like sub_pinned_bytes?
Qu Wenruo May 14, 2019, 11:08 p.m. UTC | #3
On 2019/5/15 上午1:29, David Sterba wrote:
> On Fri, May 10, 2019 at 12:45:05PM +0800, Qu Wenruo wrote:
>> Commit ddf30cf03fb5 ("btrfs: extent-tree: Use btrfs_ref to refactor
>> add_pinned_bytes()") refactored add_pinned_bytes(), but during that
>> refactor, there are two callers which add the pinned bytes instead
>> of subtracting.
>>
>> That refactor misses those two caller, causing incorrect pinned bytes
>> calculation and resulting unexpected ENOSPC error.
>>
>> Fix it by adding a new parameter @sign to restore the original behavior.
>>
>> Reported-by: kernel test robot <rong.a.chen@intel.com>
>> Fixes: ddf30cf03fb5 ("btrfs: extent-tree: Use btrfs_ref to refactor add_pinned_bytes()")
>> Signed-off-by: Qu Wenruo <wqu@suse.com>
>> ---
>>  fs/btrfs/extent-tree.c | 12 +++++++-----
>>  1 file changed, 7 insertions(+), 5 deletions(-)
>>
>> diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
>> index f79e477a378e..8592d31e321c 100644
>> --- a/fs/btrfs/extent-tree.c
>> +++ b/fs/btrfs/extent-tree.c
>> @@ -757,12 +757,14 @@ static struct btrfs_space_info *__find_space_info(struct btrfs_fs_info *info,
>>  }
>>  
>>  static void add_pinned_bytes(struct btrfs_fs_info *fs_info,
>> -			     struct btrfs_ref *ref)
>> +			     struct btrfs_ref *ref, int sign)
> 
> This does not look like a good API, can it be done with a separate
> function like sub_pinned_bytes?
> 

No problem, indeed sub_pinned_bytes looks much better.

Thanks,
Qu

Patch
diff mbox series

diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index f79e477a378e..8592d31e321c 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -757,12 +757,14 @@  static struct btrfs_space_info *__find_space_info(struct btrfs_fs_info *info,
 }
 
 static void add_pinned_bytes(struct btrfs_fs_info *fs_info,
-			     struct btrfs_ref *ref)
+			     struct btrfs_ref *ref, int sign)
 {
 	struct btrfs_space_info *space_info;
-	s64 num_bytes = -ref->len;
+	s64 num_bytes;
 	u64 flags;
 
+	ASSERT(sign == 1 || sign == -1);
+	num_bytes = sign * ref->len;
 	if (ref->type == BTRFS_REF_METADATA) {
 		if (ref->tree_ref.root == BTRFS_CHUNK_TREE_OBJECTID)
 			flags = BTRFS_BLOCK_GROUP_SYSTEM;
@@ -2063,7 +2065,7 @@  int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
 	btrfs_ref_tree_mod(fs_info, generic_ref);
 
 	if (ret == 0 && old_ref_mod < 0 && new_ref_mod >= 0)
-		add_pinned_bytes(fs_info, generic_ref);
+		add_pinned_bytes(fs_info, generic_ref, -1);
 
 	return ret;
 }
@@ -7190,7 +7192,7 @@  void btrfs_free_tree_block(struct btrfs_trans_handle *trans,
 	}
 out:
 	if (pin)
-		add_pinned_bytes(fs_info, &generic_ref);
+		add_pinned_bytes(fs_info, &generic_ref, 1);
 
 	if (last_ref) {
 		/*
@@ -7238,7 +7240,7 @@  int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_ref *ref)
 		btrfs_ref_tree_mod(fs_info, ref);
 
 	if (ret == 0 && old_ref_mod >= 0 && new_ref_mod < 0)
-		add_pinned_bytes(fs_info, ref);
+		add_pinned_bytes(fs_info, ref, 1);
 
 	return ret;
 }