Re: [PATCH v4 1/2] f2fs: complete dropbehind write bios in task context

From: Tal Zussman

Date: Fri Sep 04 2026 - 18:39:54 EST


On 9/3/26 3:59 PM, Wenjie Qi wrote:
> Buffered RWF_DONTCACHE writes invalidate dropbehind folios at writeback
> completion. Mark these bios BIO_COMPLETE_IN_TASK so the block layer runs
> F2FS completion in task context when needed.
>
> Use the same flag to keep normal and dropbehind folios from merging in the
> IPU and OPU paths. Classify the original page-cache folio rather than an
> encrypted or compressed replacement folio.
>
> Keep the existing large-ATC completion path unchanged.
>
> Signed-off-by: Wenjie Qi <qiwenjie@xxxxxxxxxx>
> ---
> fs/f2fs/data.c | 18 +++++++++++++++---
> 1 file changed, 15 insertions(+), 3 deletions(-)
>
> diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> index 21f396ebe22..b0fedacfd12 100644
> --- a/fs/f2fs/data.c
> +++ b/fs/f2fs/data.c
> @@ -503,6 +503,8 @@ static struct bio *__bio_alloc(struct f2fs_io_info *fio, int npages)
> bio = bio_alloc_bioset(bdev, npages,
> fio->op | fio->op_flags | f2fs_io_flags(fio),
> GFP_NOIO, &f2fs_bioset);
> + if (!is_read_io(fio->op) && folio_test_dropbehind(fio->folio))
> + bio_set_flag(bio, BIO_COMPLETE_IN_TASK);
> bio->bi_iter.bi_sector = sector;
> if (is_read_io(fio->op)) {
> bio->bi_end_io = f2fs_read_end_io;
> @@ -793,6 +795,13 @@ static bool page_is_mergeable(struct f2fs_sb_info *sbi, struct bio *bio,
> return bio->bi_bdev == f2fs_target_device(sbi, cur_blkaddr, NULL);
> }
>
> +static bool f2fs_bio_dropbehind_mergeable(struct bio *bio,
> + struct f2fs_io_info *fio)
> +{
> + return bio_flagged(bio, BIO_COMPLETE_IN_TASK) ==
> + folio_test_dropbehind(fio->folio);
> +}
> +

So I'm admittedly not very familiar with f2fs, but why is it necessary
to prevent merging here? For iomap, we concluded that merging was fine,
as it just results in some extra folios getting resolved in task context
(see commit efbde6f9f449 ("iomap: use BIO_COMPLETE_IN_TASK for dropbehind
writeback")).

> static bool io_type_is_mergeable(struct f2fs_bio_info *io,
> struct f2fs_io_info *fio)
> {
> @@ -985,8 +994,10 @@ int f2fs_merge_page_bio(struct f2fs_io_info *fio)
>
> trace_f2fs_submit_folio_bio(data_folio, fio);
>
> - if (bio && !page_is_mergeable(fio->sbi, bio, *fio->last_block,
> - fio->new_blkaddr))
> + if (bio &&
> + (!page_is_mergeable(fio->sbi, bio, *fio->last_block,
> + fio->new_blkaddr) ||
> + !f2fs_bio_dropbehind_mergeable(bio, fio)))
> f2fs_submit_merged_ipu_write(fio->sbi, &bio, NULL);
> alloc_new:
> if (!bio) {
> @@ -1086,7 +1097,8 @@ void f2fs_submit_page_write(struct f2fs_io_info *fio)
> (!io_is_mergeable(sbi, io->bio, io, fio, io->last_block_in_bio,
> fio->new_blkaddr) ||
> !f2fs_crypt_mergeable_bio(io->bio, fio_inode(fio),
> - bio_folio->index, fio)))
> + bio_folio->index, fio) ||
> + !f2fs_bio_dropbehind_mergeable(io->bio, fio)))
> __submit_merged_bio(io);
> alloc_new:
> if (io->bio == NULL) {
> --
> 2.43.0
>