[f2fs-dev] [PATCH v2 1/2] f2fs: complete dropbehind write bios in safe task context
Wenjie Qi <[email protected]>
| Newsgroups | net.sourceforge.lists.linux-f2fs-devel,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
Buffered RWF_DONTCACHE writes invalidate dropbehind folios from writeback completion. Keep normal and dropbehind folios in separate write bios, and defer a dropbehind bio to sbi->wq unless completion runs in preemptible task context. Use the same eligibility conditions as the proposed bio_in_atomic() helper. Unlike !in_task(), this also covers disabled preemption and preemptible RCU read-side critical sections. Keep the existing large-ATC deferral unchanged. Link: https://lore.kernel.org/linux-mm/[email protected]/ Signed-off-by: Wenjie Qi <[email protected]> --- 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 _______________________________________________ Linux-f2fs-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel