diff mbox series

[27/44] btrfs: hold a ref on the root in btrfs_recover_relocation

Message ID 20200124143301.2186319-28-josef@toxicpanda.com (mailing list archive)
State New, archived
Headers show
Series Cleanup how we handle root refs, part 1 | expand

Commit Message

Josef Bacik Jan. 24, 2020, 2:32 p.m. UTC
We look up the fs root in various places in here when recovering from a
crashed relcoation.  Make sure we hold a ref on the root whenever we
look them up.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 fs/btrfs/relocation.c | 21 ++++++++++++++++++---
 1 file changed, 18 insertions(+), 3 deletions(-)

Comments

David Sterba Feb. 5, 2020, 3 p.m. UTC | #1
On Fri, Jan 24, 2020 at 09:32:44AM -0500, Josef Bacik wrote:
> We look up the fs root in various places in here when recovering from a
> crashed relcoation.  Make sure we hold a ref on the root whenever we
> look them up.
> 
> Signed-off-by: Josef Bacik <josef@toxicpanda.com>
> ---
>  fs/btrfs/relocation.c | 21 ++++++++++++++++++---
>  1 file changed, 18 insertions(+), 3 deletions(-)
> 
> diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
> index 9531739b5a8c..81f383df8f63 100644
> --- a/fs/btrfs/relocation.c
> +++ b/fs/btrfs/relocation.c
> @@ -4593,6 +4593,10 @@ int btrfs_recover_relocation(struct btrfs_root *root)
>  		if (btrfs_root_refs(&reloc_root->root_item) > 0) {
>  			fs_root = read_fs_root(fs_info,
>  					       reloc_root->root_key.offset);
> +			if (!btrfs_grab_fs_root(fs_root)) {
> +				err = -ENOENT;
> +				goto out;
> +			}
>  			if (IS_ERR(fs_root)) {

Also in the wrong order.

>  				ret = PTR_ERR(fs_root);
>  				if (ret != -ENOENT) {
David Sterba Feb. 6, 2020, 4:26 p.m. UTC | #2
On Fri, Jan 24, 2020 at 09:32:44AM -0500, Josef Bacik wrote:
> @@ -4593,6 +4593,10 @@ int btrfs_recover_relocation(struct btrfs_root *root)
>  		if (btrfs_root_refs(&reloc_root->root_item) > 0) {
>  			fs_root = read_fs_root(fs_info,
>  					       reloc_root->root_key.offset);
> +			if (!btrfs_grab_fs_root(fs_root)) {
> +				err = -ENOENT;
> +				goto out;
> +			}
>  			if (IS_ERR(fs_root)) {
>  				ret = PTR_ERR(fs_root);
>  				if (ret != -ENOENT) {
> @@ -4604,6 +4608,8 @@ int btrfs_recover_relocation(struct btrfs_root *root)
>  					err = ret;
>  					goto out;
>  				}
> +			} else {
> +				btrfs_put_fs_root(fs_root);
>  			}
>  		}

The order of IS_ERR and btrfs_grab_fs_root is reversed but then it looks
strange:

  4637                         fs_root = read_fs_root(fs_info,
_ 4638                                                reloc_root->root_key.offset);
  4639                         if (IS_ERR(fs_root)) {
  4640                                 ret = PTR_ERR(fs_root);
  4641                                 if (ret != -ENOENT) {
  4642                                         err = ret;
  4643                                         goto out;
  4644                                 }
  4645                                 ret = mark_garbage_root(reloc_root);
  4646                                 if (ret < 0) {
  4647                                         err = ret;
  4648                                         goto out;
  4649                                 }
  4650                         } else {
+ 4651                                 if (!btrfs_grab_fs_root(fs_root)) {
+ 4652                                         err = -ENOENT;
+ 4653                                         goto out;
+ 4654                                 }
  4655                                 btrfs_put_fs_root(fs_root);
  4656                         }
  4657                 }

Seems that the refcounting is not necessary here at all, it just tries
to read the fs root and handle errors if it does not exist, no operation
that would want to keep the fs_root.
Josef Bacik Feb. 6, 2020, 4:30 p.m. UTC | #3
On 2/6/20 11:26 AM, David Sterba wrote:
> On Fri, Jan 24, 2020 at 09:32:44AM -0500, Josef Bacik wrote:
>> @@ -4593,6 +4593,10 @@ int btrfs_recover_relocation(struct btrfs_root *root)
>>   		if (btrfs_root_refs(&reloc_root->root_item) > 0) {
>>   			fs_root = read_fs_root(fs_info,
>>   					       reloc_root->root_key.offset);
>> +			if (!btrfs_grab_fs_root(fs_root)) {
>> +				err = -ENOENT;
>> +				goto out;
>> +			}
>>   			if (IS_ERR(fs_root)) {
>>   				ret = PTR_ERR(fs_root);
>>   				if (ret != -ENOENT) {
>> @@ -4604,6 +4608,8 @@ int btrfs_recover_relocation(struct btrfs_root *root)
>>   					err = ret;
>>   					goto out;
>>   				}
>> +			} else {
>> +				btrfs_put_fs_root(fs_root);
>>   			}
>>   		}
> 
> The order of IS_ERR and btrfs_grab_fs_root is reversed but then it looks
> strange:
> 
>    4637                         fs_root = read_fs_root(fs_info,
> _ 4638                                                reloc_root->root_key.offset);
>    4639                         if (IS_ERR(fs_root)) {
>    4640                                 ret = PTR_ERR(fs_root);
>    4641                                 if (ret != -ENOENT) {
>    4642                                         err = ret;
>    4643                                         goto out;
>    4644                                 }
>    4645                                 ret = mark_garbage_root(reloc_root);
>    4646                                 if (ret < 0) {
>    4647                                         err = ret;
>    4648                                         goto out;
>    4649                                 }
>    4650                         } else {
> + 4651                                 if (!btrfs_grab_fs_root(fs_root)) {
> + 4652                                         err = -ENOENT;
> + 4653                                         goto out;
> + 4654                                 }
>    4655                                 btrfs_put_fs_root(fs_root);
>    4656                         }
>    4657                 }
> 
> Seems that the refcounting is not necessary here at all, it just tries
> to read the fs root and handle errors if it does not exist, no operation
> that would want to keep the fs_root.
>

Yeah we aren't actually using the root here, so strictly speaking we don't need 
the refcount.  But in the future read_fs_root() will return a root with a 
refcount so we will still have to clean it up.  Thanks,

Josef
diff mbox series

Patch

diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index 9531739b5a8c..81f383df8f63 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -4593,6 +4593,10 @@  int btrfs_recover_relocation(struct btrfs_root *root)
 		if (btrfs_root_refs(&reloc_root->root_item) > 0) {
 			fs_root = read_fs_root(fs_info,
 					       reloc_root->root_key.offset);
+			if (!btrfs_grab_fs_root(fs_root)) {
+				err = -ENOENT;
+				goto out;
+			}
 			if (IS_ERR(fs_root)) {
 				ret = PTR_ERR(fs_root);
 				if (ret != -ENOENT) {
@@ -4604,6 +4608,8 @@  int btrfs_recover_relocation(struct btrfs_root *root)
 					err = ret;
 					goto out;
 				}
+			} else {
+				btrfs_put_fs_root(fs_root);
 			}
 		}
 
@@ -4653,10 +4659,15 @@  int btrfs_recover_relocation(struct btrfs_root *root)
 			list_add_tail(&reloc_root->root_list, &reloc_roots);
 			goto out_free;
 		}
+		if (!btrfs_grab_fs_root(fs_root)) {
+			err = -ENOENT;
+			goto out_free;
+		}
 
 		err = __add_reloc_root(reloc_root);
 		BUG_ON(err < 0); /* -ENOMEM or logic error */
 		fs_root->reloc_root = reloc_root;
+		btrfs_put_fs_root(fs_root);
 	}
 
 	err = btrfs_commit_transaction(trans);
@@ -4688,10 +4699,14 @@  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))
+		if (IS_ERR(fs_root)) {
 			err = PTR_ERR(fs_root);
-		else
-			err = btrfs_orphan_cleanup(fs_root);
+		} else {
+			if (btrfs_grab_fs_root(fs_root)) {
+				err = btrfs_orphan_cleanup(fs_root);
+				btrfs_put_fs_root(fs_root);
+			}
+		}
 	}
 	return err;
 }