All of lore.kernel.org
 help / color / mirror / Atom feed
From: Qu Wenruo <wqu@suse.com>
To: Daniel Vacek <neelx@suse.com>, David Sterba <dsterba@suse.com>,
	Chris Mason <mason@kernel.org>
Cc: linux-btrfs@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH v2 2/3] btrfs: use bio::remaining for async checksumming synchronization
Date: Sat, 5 Sep 2026 08:20:06 +0930	[thread overview]
Message-ID: <91465187-a892-4b59-857b-e5f5addc0c88@suse.com> (raw)
In-Reply-To: <5c08f2f3-cf49-41ef-84b5-dced3ce6da90@suse.com>



在 2026/9/5 08:11, Qu Wenruo 写道:
> 
> 
> 在 2026/9/3 15:53, Daniel Vacek 写道:
>> We can use bio::remaining counter to sync the offloaded checksuming.
>> As a result we can slim down the btrfs_bio structure by 24 bytes
>> and simplify the code a bit.
>>
>> $ pahole | diff
>> -    /* size: 328, cachelines: 6, members: 15 */
>> +    /* size: 304, cachelines: 5, members: 14 */
>>
>> Moreover this will allow us enabling async checksumming with encryption
>> where we need to checksum the bounce bio instead of our regular one
>> embedded in btrfs_bio. And so we need to extend it's lifetime. This is
>> the preffered way to do so.
>>
>> Signed-off-by: Daniel Vacek <neelx@suse.com>
>> Reviewed-by: Qu Wenruo <wqu@suse.com>
>> ---
>>
>> No change since v1
>> ---
>>   fs/btrfs/bio.c       | 4 ----
>>   fs/btrfs/bio.h       | 4 ----
>>   fs/btrfs/file-item.c | 6 ++----
>>   3 files changed, 2 insertions(+), 12 deletions(-)
>>
>> diff --git a/fs/btrfs/bio.c b/fs/btrfs/bio.c
>> index 19b4855969f5..771b7d598aee 100644
>> --- a/fs/btrfs/bio.c
>> +++ b/fs/btrfs/bio.c
>> @@ -103,7 +103,6 @@ static struct btrfs_bio *btrfs_split_bio(struct 
>> btrfs_fs_info *fs_info,
>>       bbio->can_use_append = orig_bbio->can_use_append;
>>       bbio->is_scrub = orig_bbio->is_scrub;
>>       bbio->is_remap = orig_bbio->is_remap;
>> -    bbio->async_csum = orig_bbio->async_csum;
>>       atomic_inc(&orig_bbio->pending_ios);
>>       return bbio;
>> @@ -114,9 +113,6 @@ void btrfs_bio_end_io(struct btrfs_bio *bbio, 
>> blk_status_t status)
>>       /* Make sure we're already in task context. */
>>       ASSERT(in_task());
>> -    if (bbio->async_csum)
>> -        wait_for_completion(&bbio->csum_done);
>> -
>>       bbio->bio.bi_status = status;
>>       if (bbio->bio.bi_pool == &btrfs_clone_bioset) {
>>           struct btrfs_bio *orig_bbio = bbio->private;
>> diff --git a/fs/btrfs/bio.h b/fs/btrfs/bio.h
>> index b7bd377a0162..bbf362b8668b 100644
>> --- a/fs/btrfs/bio.h
>> +++ b/fs/btrfs/bio.h
>> @@ -58,7 +58,6 @@ struct btrfs_bio {
>>               struct btrfs_ordered_extent *ordered;
>>               struct btrfs_ordered_sum *sums;
>>               struct work_struct csum_work;
>> -            struct completion csum_done;
>>               struct bvec_iter csum_saved_iter;
>>               u64 orig_physical;
>>               u64 orig_logical;
>> @@ -93,9 +92,6 @@ struct btrfs_bio {
>>       /* Whether the bio is coming from copy_remapped_data_io(). */
>>       bool is_remap:1;
>> -    /* Whether the csum generation for data write is async. */
>> -    bool async_csum:1;
>> -
>>       /* Whether the bio is written using zone append. */
>>       bool can_use_append:1;
>> diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c
>> index 4a7681557ec1..0fed4e0d32d5 100644
>> --- a/fs/btrfs/file-item.c
>> +++ b/fs/btrfs/file-item.c
>> @@ -818,9 +818,8 @@ static void csum_one_bio_work(struct work_struct 
>> *work)
>>       struct btrfs_bio *bbio = container_of(work, struct btrfs_bio, 
>> csum_work);
>>       ASSERT(btrfs_op(&bbio->bio) == BTRFS_MAP_WRITE);
>> -    ASSERT(bbio->async_csum == true);
>>       csum_one_bio(bbio);
>> -    complete(&bbio->csum_done);
>> +    bio_endio(&bbio->bio);
>>   }
>>   /*
>> @@ -854,8 +853,7 @@ int btrfs_csum_one_bio(struct btrfs_bio *bbio, 
>> bool async)
>>           csum_one_bio(bbio);
>>           return 0;
>>       }
>> -    init_completion(&bbio->csum_done);
>> -    bbio->async_csum = true;
>> +    bio_inc_remaining(bio);
> 
> There seems to be a window where the bio can be finished before submission.
> 
> Firstly at btrfs_csum_one_bio() time, bio->bi_endio is not yet 
> initialized, it's only properly assigned at btrfs_submit_bio().
> 
> Then we queue the csum generation work.
> 
> But by some bad timing, the bio submission is delayed, we can have the 
> following sequence:
> 
>          Submission               |       Csum generation
> ---------------------------------+------------------------------------
> btrfs_submit_chunk()             |
> |- btrfs_csum_one_bio()          |
> |  |- bio_inc_remaining()        |
> |  |- schedule_work()            | csum_one_bio_work()
> |                                | |- bio_endio()
> |                                | Now the bio is finished, although
> |                                | bi_end_io is NULL, nothing real
> |                                | happened.

Damn it, I really need some tea before reviewing patches in the morning.

A bio has bi_remaining initialized to 1, so bio_inc_remaining() will 
change it to 2.

After bio_inc_remaining(), the next bio_endio() will not call 
bi_end_io(), but only decrease the bi_remaining back to 1.

So it won't call bi_end_io() in this case.

Please discard the above analysis.
> |- btrfs_submit_bio()
> 
> 
> This can be even worse, if the bio_endio() is called when 
> btrfs_submit_bio() has only partially setup the bio (e.g. bi_end_io() is 
> set, but bi_bdev is not set)
> 
> Not mention now it changed the context where the endio function is called.
> 
> Previously csum_one_bio_work() will never call bi_end_io() function, but 
> now it can.
> 
> The change has a much larger impact than I initially thought.
>>       INIT_WORK(&bbio->csum_work, csum_one_bio_work);
>>       schedule_work(&bbio->csum_work);
>>       return 0;
> 


  reply	other threads:[~2026-09-04 22:50 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-03  6:23 [PATCH v2 0/3] btrfs: async checksumming cleanups Daniel Vacek
2026-09-03  6:23 ` [PATCH v2 1/3] btrfs: consume the given iter directly instead of copying in csum_one_bio() Daniel Vacek
2026-09-03  6:45   ` Qu Wenruo
2026-09-03  6:23 ` [PATCH v2 2/3] btrfs: use bio::remaining for async checksumming synchronization Daniel Vacek
2026-09-04 22:41   ` Qu Wenruo
2026-09-04 22:50     ` Qu Wenruo [this message]
2026-09-03  6:23 ` [PATCH v2 3/3] btrfs: promote async checksumming out of EXPERIMENTAL Daniel Vacek
2026-09-03  6:33   ` Qu Wenruo
2026-09-03  6:41     ` Daniel Vacek

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=91465187-a892-4b59-857b-e5f5addc0c88@suse.com \
    --to=wqu@suse.com \
    --cc=dsterba@suse.com \
    --cc=linux-btrfs@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mason@kernel.org \
    --cc=neelx@suse.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.