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 --- 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); +} + 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