diff mbox series

btrfs: do not consider send context as valid when trying to flush qgroups

Message ID 1020602e269415d91c713afdfb9a11921a3ceda6.1619087848.git.fdmanana@suse.com (mailing list archive)
State New, archived
Headers show
Series btrfs: do not consider send context as valid when trying to flush qgroups | expand

Commit Message

Filipe Manana April 22, 2021, 11:09 a.m. UTC
From: Filipe Manana <fdmanana@suse.com>

At qgroup.c:try_flush_qgroup() we are asserting that current->journal_info
is either NULL or has the value BTRFS_SEND_TRANS_STUB.

However allowing for BTRFS_SEND_TRANS_STUB makes no sense because:

1) It is misleading, because send operations are read-only and do not
   ever need to reserve qgroup space;

2) We already assert that current->journal_info != BTRFS_SEND_TRANS_STUB
   at transaction.c:start_transaction();

3) On a kernel without CONFIG_BTRFS_ASSERT=y set, it would result in
   a crash if try_flush_qgroup() is ever called in a send context, because
   at transaction.c:start_transaction we cast current->journal_info into
   a struct btrfs_trans_handle pointer and then dereference it.

So just do allow a send context at try_flush_qgroup() and update the
comment about it.

Signed-off-by: Filipe Manana <fdmanana@suse.com>
---
 fs/btrfs/qgroup.c | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

Comments

Qu Wenruo April 22, 2021, 11:17 a.m. UTC | #1
On 2021/4/22 下午7:09, fdmanana@kernel.org wrote:
> From: Filipe Manana <fdmanana@suse.com>
>
> At qgroup.c:try_flush_qgroup() we are asserting that current->journal_info
> is either NULL or has the value BTRFS_SEND_TRANS_STUB.
>
> However allowing for BTRFS_SEND_TRANS_STUB makes no sense because:
>
> 1) It is misleading, because send operations are read-only and do not
>     ever need to reserve qgroup space;
>
> 2) We already assert that current->journal_info != BTRFS_SEND_TRANS_STUB
>     at transaction.c:start_transaction();
>
> 3) On a kernel without CONFIG_BTRFS_ASSERT=y set, it would result in
>     a crash if try_flush_qgroup() is ever called in a send context, because
>     at transaction.c:start_transaction we cast current->journal_info into
>     a struct btrfs_trans_handle pointer and then dereference it.
>
> So just do allow a send context at try_flush_qgroup() and update the
> comment about it.
>
> Signed-off-by: Filipe Manana <fdmanana@suse.com>

Reviewed-by: Qu Wenruo <wqu@suse.com>

Thanks,
Qu
> ---
>   fs/btrfs/qgroup.c | 14 +++++++++-----
>   1 file changed, 9 insertions(+), 5 deletions(-)
>
> diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
> index 366a6a289796..3ded812f522c 100644
> --- a/fs/btrfs/qgroup.c
> +++ b/fs/btrfs/qgroup.c
> @@ -3545,11 +3545,15 @@ static int try_flush_qgroup(struct btrfs_root *root)
>   	struct btrfs_trans_handle *trans;
>   	int ret;
>
> -	/* Can't hold an open transaction or we run the risk of deadlocking */
> -	ASSERT(current->journal_info == NULL ||
> -	       current->journal_info == BTRFS_SEND_TRANS_STUB);
> -	if (WARN_ON(current->journal_info &&
> -		    current->journal_info != BTRFS_SEND_TRANS_STUB))
> +	/*
> +	 * Can't hold an open transaction or we run the risk of deadlocking,
> +	 * and can't either be under the context of a send operation (where
> +	 * current->journal_info is set to BTRFS_SEND_TRANS_STUB), as that
> +	 * would result in a crash when starting a transaction and does not
> +	 * make sense either (send is a read-only operation).
> +	 */
> +	ASSERT(current->journal_info == NULL);
> +	if (WARN_ON(current->journal_info))
>   		return 0;
>
>   	/*
>
David Sterba April 28, 2021, 5:20 p.m. UTC | #2
On Thu, Apr 22, 2021 at 12:09:21PM +0100, fdmanana@kernel.org wrote:
> From: Filipe Manana <fdmanana@suse.com>
> 
> At qgroup.c:try_flush_qgroup() we are asserting that current->journal_info
> is either NULL or has the value BTRFS_SEND_TRANS_STUB.
> 
> However allowing for BTRFS_SEND_TRANS_STUB makes no sense because:
> 
> 1) It is misleading, because send operations are read-only and do not
>    ever need to reserve qgroup space;
> 
> 2) We already assert that current->journal_info != BTRFS_SEND_TRANS_STUB
>    at transaction.c:start_transaction();
> 
> 3) On a kernel without CONFIG_BTRFS_ASSERT=y set, it would result in
>    a crash if try_flush_qgroup() is ever called in a send context, because
>    at transaction.c:start_transaction we cast current->journal_info into
>    a struct btrfs_trans_handle pointer and then dereference it.
> 
> So just do allow a send context at try_flush_qgroup() and update the
> comment about it.
> 
> Signed-off-by: Filipe Manana <fdmanana@suse.com>

Added to misc-next, thanks.
diff mbox series

Patch

diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
index 366a6a289796..3ded812f522c 100644
--- a/fs/btrfs/qgroup.c
+++ b/fs/btrfs/qgroup.c
@@ -3545,11 +3545,15 @@  static int try_flush_qgroup(struct btrfs_root *root)
 	struct btrfs_trans_handle *trans;
 	int ret;
 
-	/* Can't hold an open transaction or we run the risk of deadlocking */
-	ASSERT(current->journal_info == NULL ||
-	       current->journal_info == BTRFS_SEND_TRANS_STUB);
-	if (WARN_ON(current->journal_info &&
-		    current->journal_info != BTRFS_SEND_TRANS_STUB))
+	/*
+	 * Can't hold an open transaction or we run the risk of deadlocking,
+	 * and can't either be under the context of a send operation (where
+	 * current->journal_info is set to BTRFS_SEND_TRANS_STUB), as that
+	 * would result in a crash when starting a transaction and does not
+	 * make sense either (send is a read-only operation).
+	 */
+	ASSERT(current->journal_info == NULL);
+	if (WARN_ON(current->journal_info))
 		return 0;
 
 	/*