* [PATCH v4 1/2] f2fs: complete dropbehind write bios in task context
2026-09-03 12:59 [PATCH v4 0/2] f2fs: enable buffered RWF_DONTCACHE Wenjie Qi
@ 2026-09-03 12:59 ` Wenjie Qi
2026-09-04 22:35 ` Tal Zussman
2026-09-03 12:59 ` [PATCH v4 2/2] f2fs: enable buffered RWF_DONTCACHE Wenjie Qi
2026-09-05 7:07 ` [syzbot ci] " syzbot ci
2 siblings, 1 reply; 7+ messages in thread
From: Wenjie Qi @ 2026-09-03 12:59 UTC (permalink / raw)
To: jaegeuk, chao
Cc: linux-f2fs-devel, linux-kernel, hch, jack, axboe, tz2294, baohua,
linux-block, linux-fsdevel, linux-mm, qiwenjie, qwjhust
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@xiaomi.com>
---
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
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [PATCH v4 1/2] f2fs: complete dropbehind write bios in task context
2026-09-03 12:59 ` [PATCH v4 1/2] f2fs: complete dropbehind write bios in task context Wenjie Qi
@ 2026-09-04 22:35 ` Tal Zussman
0 siblings, 0 replies; 7+ messages in thread
From: Tal Zussman @ 2026-09-04 22:35 UTC (permalink / raw)
To: Wenjie Qi, jaegeuk, chao
Cc: linux-f2fs-devel, linux-kernel, hch, jack, axboe, baohua,
linux-block, linux-fsdevel, linux-mm, qiwenjie
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@xiaomi.com>
> ---
> 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
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v4 2/2] f2fs: enable buffered RWF_DONTCACHE
2026-09-03 12:59 [PATCH v4 0/2] f2fs: enable buffered RWF_DONTCACHE Wenjie Qi
2026-09-03 12:59 ` [PATCH v4 1/2] f2fs: complete dropbehind write bios in task context Wenjie Qi
@ 2026-09-03 12:59 ` Wenjie Qi
2026-09-05 7:07 ` [syzbot ci] " syzbot ci
2 siblings, 0 replies; 7+ messages in thread
From: Wenjie Qi @ 2026-09-03 12:59 UTC (permalink / raw)
To: jaegeuk, chao
Cc: linux-f2fs-devel, linux-kernel, hch, jack, axboe, tz2294, baohua,
linux-block, linux-fsdevel, linux-mm, qiwenjie, qwjhust
Pass FGP_DONTCACHE to f2fs_filemap_get_folio() for IOCB_DONTCACHE writes
and advertise FOP_DONTCACHE.
Keep the F2FS-specific lookup because write_begin_get_folio() adds
FGP_STABLE, which can deadlock here.
Signed-off-by: Wenjie Qi <qiwenjie@xiaomi.com>
---
fs/f2fs/data.c | 9 ++++++---
fs/f2fs/file.c | 2 +-
2 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index b0fedacfd12..6e816c9349a 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -3884,11 +3884,15 @@ static int f2fs_write_begin(const struct kiocb *iocb,
struct inode *inode = mapping->host;
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
struct folio *folio;
+ fgf_t fgp_flags = FGP_LOCK | FGP_WRITE | FGP_CREAT;
pgoff_t index = pos >> PAGE_SHIFT;
bool need_balance = false;
block_t blkaddr = NULL_ADDR;
int err = 0;
+ if (iocb->ki_flags & IOCB_DONTCACHE)
+ fgp_flags |= FGP_DONTCACHE;
+
trace_f2fs_write_begin(inode, pos, len);
if (!f2fs_is_checkpoint_ready(sbi)) {
@@ -3934,9 +3938,8 @@ static int f2fs_write_begin(const struct kiocb *iocb,
* Do not use FGP_STABLE to avoid deadlock.
* Will wait that below with our IO control.
*/
- folio = f2fs_filemap_get_folio(mapping, index,
- FGP_LOCK | FGP_WRITE | FGP_CREAT,
- mapping_gfp_mask(mapping));
+ folio = f2fs_filemap_get_folio(mapping, index, fgp_flags,
+ mapping_gfp_mask(mapping));
if (IS_ERR(folio)) {
err = PTR_ERR(folio);
goto fail;
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index edc352569e8..570244ae4fc 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -5909,6 +5909,6 @@ const struct file_operations f2fs_file_operations = {
.splice_read = f2fs_file_splice_read,
.splice_write = iter_file_splice_write,
.fadvise = f2fs_file_fadvise,
- .fop_flags = FOP_BUFFER_RASYNC,
+ .fop_flags = FOP_BUFFER_RASYNC | FOP_DONTCACHE,
.setlease = generic_setlease,
};
--
2.43.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* [syzbot ci] Re: f2fs: enable buffered RWF_DONTCACHE
2026-09-03 12:59 [PATCH v4 0/2] f2fs: enable buffered RWF_DONTCACHE Wenjie Qi
2026-09-03 12:59 ` [PATCH v4 1/2] f2fs: complete dropbehind write bios in task context Wenjie Qi
2026-09-03 12:59 ` [PATCH v4 2/2] f2fs: enable buffered RWF_DONTCACHE Wenjie Qi
@ 2026-09-05 7:07 ` syzbot ci
2026-09-05 13:29 ` [PATCH] f2fs: handle NULL kiocb in write_begin Wenjie Qi
2 siblings, 1 reply; 7+ messages in thread
From: syzbot ci @ 2026-09-05 7:07 UTC (permalink / raw)
To: axboe, baohua, chao, hch, jack, jaegeuk, linux-block,
linux-f2fs-devel, linux-fsdevel, linux-kernel, linux-mm, qiwenjie,
qwjhust, tz2294
Cc: syzbot, syzkaller-bugs
syzbot ci has tested the following series
[v4] f2fs: enable buffered RWF_DONTCACHE
https://lore.kernel.org/all/cover.1788438786.git.qiwenjie@xiaomi.com
* [PATCH v4 1/2] f2fs: complete dropbehind write bios in task context
* [PATCH v4 2/2] f2fs: enable buffered RWF_DONTCACHE
and found the following issue:
general protection fault in f2fs_write_begin
Full report is available here:
https://ci.syzbot.org/series/cbb9ded8-1388-4a7b-bfa7-44082b04025b
***
general protection fault in f2fs_write_begin
tree: mm-new
URL: https://kernel.googlesource.com/pub/scm/linux/kernel/git/akpm/mm.git
base: e3fc12b08aadde9cec7b3799ac0e0c9a1aa245c4
arch: amd64
compiler: Debian clang version 22.1.8 (++20260613092233+e80beda6e255-1~exp1~20260613092250.77), Debian LLD 22.1.8
config: https://ci.syzbot.org/builds/e5903709-6ea2-4b1e-9dfc-f073e36367f7/config
syz repro: https://ci.syzbot.org/findings/d05a5d64-e9a3-4714-9b41-43042eaaa82c/syz_repro
loop0: detected capacity change from 0 to 40427
F2FS-fs (loop0): invalid crc value
F2FS-fs (loop0): f2fs_recover_fsync_data: recovery fsync data, check_only: 0
F2FS-fs (loop0): Mounted with checkpoint version = 48b305e5
Oops: general protection fault, probably for non-canonical address 0xdffffc0000000004: 0000 [#1] SMP KASAN PTI
KASAN: null-ptr-deref in range [0x0000000000000020-0x0000000000000027]
CPU: 1 UID: 0 PID: 5791 Comm: syz.0.17 Not tainted syzkaller #0 PREEMPT(full)
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.2-debian-1.16.2-1 04/01/2014
RIP: 0010:f2fs_write_begin+0x181/0x28e0 fs/f2fs/data.c:3893
Code: e7 e8 23 21 d4 fd 49 8b 04 24 48 89 44 24 40 41 c6 45 2c 04 c7 84 24 a0 02 00 00 00 00 00 00 48 83 c3 20 48 89 d8 48 c1 e8 03 <42> 0f b6 04 30 84 c0 0f 85 e9 23 00 00 41 be 80 00 00 00 44 23 33
RSP: 0018:ffffc900037af7a0 EFLAGS: 00010202
RAX: 0000000000000004 RBX: 0000000000000020 RCX: dffffc0000000000
RDX: 0000000000000000 RSI: ffff8881b465c918 RDI: 0000000000000000
RBP: ffffc900037afad0 R08: ffffc900037afb80 R09: ffffc900037afba0
R10: dffffc0000000000 R11: ffffffff8463a450 R12: ffff88816b91e678
R13: fffff520006f5f1c R14: dffffc0000000000 R15: ffff8881b465c918
FS: 00007f65b5e096c0(0000) GS:ffff8882a8cd9000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007f65b4e70050 CR3: 000000016a860000 CR4: 00000000000006f0
Call Trace:
<TASK>
page_symlink+0x27a/0x440 fs/namei.c:6556
f2fs_symlink+0x5fc/0x970 fs/f2fs/namei.c:714
vfs_symlink+0x18b/0x330 fs/namei.c:5794
filename_symlinkat+0x1cd/0x410 fs/namei.c:5819
__do_sys_symlinkat fs/namei.c:5839 [inline]
__se_sys_symlinkat+0x4e/0x2b0 fs/namei.c:5834
do_syscall_x64 arch/x86/entry/syscall_64.c:61 [inline]
do_syscall_64+0x166/0x520 arch/x86/entry/syscall_64.c:84
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f65b4f9e159
Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 e8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007f65b5e09028 EFLAGS: 00000246 ORIG_RAX: 000000000000010a
RAX: ffffffffffffffda RBX: 00007f65b5225fa0 RCX: 00007f65b4f9e159
RDX: 00002000000005c0 RSI: ffffffffffffff9c RDI: 0000200000000700
RBP: 00007f65b5035024 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
R13: 00007f65b5226038 R14: 00007f65b5225fa0 R15: 00007fffb6ecc0c8
</TASK>
Modules linked in:
---[ end trace 0000000000000000 ]---
RIP: 0010:f2fs_write_begin+0x181/0x28e0 fs/f2fs/data.c:3893
Code: e7 e8 23 21 d4 fd 49 8b 04 24 48 89 44 24 40 41 c6 45 2c 04 c7 84 24 a0 02 00 00 00 00 00 00 48 83 c3 20 48 89 d8 48 c1 e8 03 <42> 0f b6 04 30 84 c0 0f 85 e9 23 00 00 41 be 80 00 00 00 44 23 33
RSP: 0018:ffffc900037af7a0 EFLAGS: 00010202
RAX: 0000000000000004 RBX: 0000000000000020 RCX: dffffc0000000000
RDX: 0000000000000000 RSI: ffff8881b465c918 RDI: 0000000000000000
RBP: ffffc900037afad0 R08: ffffc900037afb80 R09: ffffc900037afba0
R10: dffffc0000000000 R11: ffffffff8463a450 R12: ffff88816b91e678
R13: fffff520006f5f1c R14: dffffc0000000000 R15: ffff8881b465c918
FS: 00007f65b5e096c0(0000) GS:ffff8882a8cd9000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007f65b4feb840 CR3: 000000016a860000 CR4: 00000000000006f0
----------------
Code disassembly (best guess), 1 bytes skipped:
0: e8 23 21 d4 fd call 0xfdd42128
5: 49 8b 04 24 mov (%r12),%rax
9: 48 89 44 24 40 mov %rax,0x40(%rsp)
e: 41 c6 45 2c 04 movb $0x4,0x2c(%r13)
13: c7 84 24 a0 02 00 00 movl $0x0,0x2a0(%rsp)
1a: 00 00 00 00
1e: 48 83 c3 20 add $0x20,%rbx
22: 48 89 d8 mov %rbx,%rax
25: 48 c1 e8 03 shr $0x3,%rax
* 29: 42 0f b6 04 30 movzbl (%rax,%r14,1),%eax <-- trapping instruction
2e: 84 c0 test %al,%al
30: 0f 85 e9 23 00 00 jne 0x241f
36: 41 be 80 00 00 00 mov $0x80,%r14d
3c: 44 23 33 and (%rbx),%r14d
***
If these findings have caused you to resend the series or submit a
separate fix, please add the following tag to your commit message:
Tested-by: syzbot@syzkaller.appspotmail.com
---
This report is generated by a bot. It may contain errors.
syzbot ci engineers can be reached at syzkaller@googlegroups.com.
To test a fix for this bug, please reply with `#syz test`
(on a separate line) and attach the patch to the email.
Notes:
- The patch will be applied on top of the tested series (as an
incremental fix).
- To test a new version of the whole series, please send it directly
to syzbot@lists.linux.dev.
- Arguments like custom git repos and branches are not supported.
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH] f2fs: handle NULL kiocb in write_begin
2026-09-05 7:07 ` [syzbot ci] " syzbot ci
@ 2026-09-05 13:29 ` Wenjie Qi
2026-09-05 14:26 ` [syzbot ci] Re: f2fs: enable buffered RWF_DONTCACHE syzbot ci
0 siblings, 1 reply; 7+ messages in thread
From: Wenjie Qi @ 2026-09-05 13:29 UTC (permalink / raw)
To: syzbot+cid5582b8164122eda
Cc: syzbot, syzkaller-bugs, jaegeuk, chao, linux-f2fs-devel,
linux-kernel, hch, jack, axboe, tz2294, baohua, linux-block,
linux-fsdevel, linux-mm, qiwenjie, qwjhust
From: Wenjie Qi <qiwenjie@xiaomi.com>
The address-space write_begin callback is also used by internal callers
that pass a NULL kiocb, including page_symlink().
Check iocb before propagating IOCB_DONTCACHE into the F2FS-specific folio
lookup flags.
Fixes: cd5bc4fbb900 ("f2fs: enable buffered RWF_DONTCACHE")
Reported-by: syzbot+cid5582b8164122eda@syzkaller.appspotmail.com
Closes: https://ci.syzbot.org/series/cbb9ded8-1388-4a7b-bfa7-44082b04025b
Signed-off-by: Wenjie Qi <qiwenjie@xiaomi.com>
---
#syz test
fs/f2fs/data.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 6e816c9349a..63625ab3f1e 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -3890,7 +3890,7 @@ static int f2fs_write_begin(const struct kiocb *iocb,
block_t blkaddr = NULL_ADDR;
int err = 0;
- if (iocb->ki_flags & IOCB_DONTCACHE)
+ if (iocb && iocb->ki_flags & IOCB_DONTCACHE)
fgp_flags |= FGP_DONTCACHE;
trace_f2fs_write_begin(inode, pos, len);
--
2.43.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* [syzbot ci] Re: f2fs: enable buffered RWF_DONTCACHE
2026-09-05 13:29 ` [PATCH] f2fs: handle NULL kiocb in write_begin Wenjie Qi
@ 2026-09-05 14:26 ` syzbot ci
0 siblings, 0 replies; 7+ messages in thread
From: syzbot ci @ 2026-09-05 14:26 UTC (permalink / raw)
To: qwjhust, axboe, baohua, chao, hch, jack, jaegeuk, linux-block,
linux-f2fs-devel, linux-fsdevel, linux-kernel, linux-mm, qiwenjie,
syzbot, syzkaller-bugs, tz2294
Cc: syzbot, syzkaller-bugs
syzbot ci has tested the suggested fix patch on top of the following series:
[v4] f2fs: enable buffered RWF_DONTCACHE
https://lore.kernel.org/all/cover.1788438786.git.qiwenjie@xiaomi.com
Patch: https://ci.syzbot.org/jobs/279baf88-89a3-4cb8-93c2-4bd86aa5092e/patch
Testing results:
* [build 0] Build Patched: passed
* [build 0] Boot test: Patched: passed
* [build 0] Previous reproducers: passed
- general protection fault in f2fs_write_begin (patched) - passed
Full report is available here:
https://ci.syzbot.org/session/7e05d54c-8b9e-4e22-a746-48153ea42a60
---
This report is generated by a bot. It may contain errors.
syzbot ci engineers can be reached at syzkaller@googlegroups.com.
^ permalink raw reply [flat|nested] 7+ messages in thread