Re: [PATCH v3 1/2] f2fs: complete dropbehind write bios in safe task context
From: Wenjie Qi
Date: Tue Aug 25 2026 - 02:44:06 EST
Thanks, I missed that these helpers had landed for 7.3.
I'll rebase the next revision and use BIO_COMPLETE_IN_TASK for dropbehind
write bios, removing the F2FS-local context check and dropbehind-specific
workqueue deferral. I'll also Cc the people and lists involved with the
common code.
On Tue, Aug 25, 2026 at 1:48 PM Christoph Hellwig <hch@xxxxxxxxxxxxx> wrote:
>
> On Mon, Aug 24, 2026 at 06:33:46PM +0800, Wenjie Qi wrote:
> > Buffered RWF_DONTCACHE writes invalidate dropbehind folios from writeback
> > completion. Keep normal and dropbehind folios in separate write bios, and
> > defer dropbehind bios to sbi->wq unless completion runs in preemptible task
> > context.
> >
> > Use an F2FS-local context check for this decision. Task context alone is
> > not sufficient: preemption may still be disabled, or completion may run in
> > a preemptible RCU read-side critical section.
> >
> > Keep the existing large-ATC deferral unchanged.
>
> Please reuse all the helpers added in common code in 7.3 for deferring
> bios and tsting if that that is neeeded instead of badly reinventing
> the logic. It also is really helpful to Cc people involved with the
> code and the relevant mailing lists.
>
> >
> > Signed-off-by: Wenjie Qi <qiwenjie@xxxxxxxxxx>
> > ---
> > fs/f2fs/data.c | 50 ++++++++++++++++++++++++++++++++++++++++++--------
> > 1 file changed, 42 insertions(+), 8 deletions(-)
> >
> > diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> > index 6ae0eb37d20..774a3e2d8e3 100644
> > --- a/fs/f2fs/data.c
> > +++ b/fs/f2fs/data.c
> > @@ -21,6 +21,7 @@
> > #include <linux/fiemap.h>
> > #include <linux/iomap.h>
> > #include <linux/fserror.h>
> > +#include <linux/rcupdate.h>
> >
> > #include "f2fs.h"
> > #include "node.h"
> > @@ -43,9 +44,29 @@ struct f2fs_folio_state {
> >
> > struct f2fs_bio {
> > struct work_struct work;
> > + bool dropbehind;
> > struct bio bio;
> > };
> >
> > +static struct f2fs_bio *to_f2fs_bio(struct bio *bio)
> > +{
> > + return container_of(bio, struct f2fs_bio, bio);
> > +}
> > +
> > +/* Keep in sync with the proposed block-layer bio_in_atomic(). */
> > +static bool f2fs_bio_in_atomic(void)
> > +{
> > +#ifdef CONFIG_PREEMPTION
> > + if (rcu_preempt_depth())
> > + return true;
> > +#endif
> > +#ifndef CONFIG_PREEMPT_COUNT
> > + return true;
> > +#else
> > + return !preemptible();
> > +#endif
> > +}
> > +
> > #define F2FS_BIO_POOL_SIZE NR_CURSEG_TYPE
> >
> > int __init f2fs_init_bioset(void)
> > @@ -426,12 +447,13 @@ static void f2fs_write_end_io(struct bio *bio)
> >
> > sbi = bio->bi_private;
> >
> > - if (in_atomic() && bio->bi_iter.bi_size > sbi->max_atc_write_bio_size) {
> > - struct work_struct *w;
> > + if ((to_f2fs_bio(bio)->dropbehind && f2fs_bio_in_atomic()) ||
> > + (in_atomic() &&
> > + bio->bi_iter.bi_size > sbi->max_atc_write_bio_size)) {
> > + struct work_struct *work = &to_f2fs_bio(bio)->work;
> >
> > - w = &container_of(bio, struct f2fs_bio, bio)->work;
> > - INIT_WORK(w, f2fs_write_end_io_work);
> > - queue_work(sbi->wq, w);
> > + INIT_WORK(work, f2fs_write_end_io_work);
> > + queue_work(sbi->wq, work);
> > } else {
> > f2fs_write_end_bio(bio);
> > }
> > @@ -530,6 +552,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);
> > + to_f2fs_bio(bio)->dropbehind =
> > + !is_read_io(fio->op) && folio_test_dropbehind(fio->folio);
> > bio->bi_iter.bi_sector = sector;
> > if (is_read_io(fio->op)) {
> > bio->bi_end_io = f2fs_read_end_io;
> > @@ -825,6 +849,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 to_f2fs_bio(bio)->dropbehind ==
> > + folio_test_dropbehind(fio->folio);
> > +}
> > +
> > static bool io_type_is_mergeable(struct f2fs_bio_info *io,
> > struct f2fs_io_info *fio)
> > {
> > @@ -1017,8 +1048,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) {
> > @@ -1118,7 +1151,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
> >
> ---end quoted text---