fs/f2fs/data.c | 27 +++++++++++++++++++++------ fs/f2fs/file.c | 2 +- 2 files changed, 22 insertions(+), 7 deletions(-)
This series enables buffered RWF_DONTCACHE on F2FS for sustained one-pass
streaming writes, where retaining the written data can displace more useful
cache.
Patch 1 marks dropbehind write bios with BIO_COMPLETE_IN_TASK and uses the
same flag to keep normal and dropbehind folios separate in the IPU and OPU
paths. The block layer owns deferral from unsafe completion contexts.
Patch 2 passes FGP_DONTCACHE to the F2FS buffered write folio lookup and
advertises FOP_DONTCACHE.
Tests were run on a Xiaomi phone with 10.7 GiB of kernel-visible memory,
running Android 16 and Linux 6.12.69 with 4 KiB pages. /data used F2FS.
The performance test wrote exactly 64 GiB per run at 4 KiB,
8 KiB, 16 KiB, 32 KiB, 64 KiB, 128 KiB, 256 KiB, 512 KiB, and 1 MiB.
Two counterbalanced rounds ran ascending normal-first and descending
dontcache-first. Values below are equal-weight means of both runs; N=2.
The pwritev2() writer models the streaming workload; it does not show that
an unchanged Android application already issues RWF_DONTCACHE.
Android remained active with displays off. Each run started after a cache
reset and at least 120 seconds of cooldown. Throughput and one-second
kswapd0/global-memory samples cover the write loop.
Write-loop throughput was:
normal MiB/s dontcache MiB/s
I/O r1 r2 mean r1 r2 mean change
4K 946.28 935.74 941.01 291.36 309.31 300.33 -68.08%
8K 1077.05 1105.84 1091.45 477.79 479.79 478.79 -56.13%
16K 1126.84 1118.49 1122.67 643.40 652.06 647.73 -42.30%
32K 1150.62 1036.33 1093.48 762.24 751.45 756.84 -30.79%
64K 1144.80 1163.82 1154.31 852.11 851.19 851.65 -26.22%
128K 1166.29 1162.84 1164.57 867.47 865.05 866.26 -25.61%
256K 1153.61 1172.78 1163.19 895.53 885.33 890.43 -23.45%
512K 1173.61 1197.34 1185.48 903.09 903.01 903.05 -23.82%
1M 1126.22 1154.59 1140.41 850.74 894.60 872.67 -23.48%
Average kswapd0 CPU and average global Cached were:
I/O kswapd0 CPU, normal/DC Cached MiB, normal/DC
4K 18.45% / 0% 4830.15 / 686.56
8K 21.60% / 0% 4862.35 / 591.48
16K 22.75% / 0% 4905.47 / 625.07
32K 22.05% / 0% 4945.82 / 561.59
64K 23.46% / 0% 4920.77 / 639.78
128K 23.16% / 0% 4971.37 / 693.26
256K 23.68% / 0% 4956.93 / 668.60
512K 24.25% / 0% 4972.22 / 663.92
1M 22.01% / 0% 5001.09 / 705.30
Other global memory means were:
MemAvailable MiB Dirty MiB Writeback MiB
I/O normal / DC normal / DC normal / DC
4K 6513.08 / 6382.31 640.48 / 33.93 37.94 / 0.09
8K 6560.77 / 6529.33 690.89 / 43.57 40.84 / 0.54
16K 6587.46 / 6519.94 789.16 / 62.67 61.58 / 4.64
32K 6571.95 / 6566.74 850.48 / 69.14 67.69 / 9.24
64K 6600.64 / 6559.89 856.97 / 134.28 59.60 / 16.19
128K 6627.03 / 6465.10 873.68 / 137.57 60.57 / 41.50
256K 6615.58 / 6541.09 885.98 / 158.15 61.25 / 29.57
512K 6625.52 / 6534.41 900.65 / 139.07 63.65 / 30.35
1M 6677.09 / 6539.89 909.70 / 187.56 51.58 / 33.46
Active(file) MiB Inactive(file) MiB
I/O normal / DC normal / DC
4K 279.57 / 264.13 4426.38 / 183.12
8K 262.32 / 260.97 4472.62 / 182.19
16K 392.09 / 252.95 4392.78 / 195.82
32K 254.30 / 248.44 4554.18 / 187.34
64K 252.73 / 244.94 4545.40 / 267.28
128K 322.02 / 243.95 4530.63 / 298.91
256K 245.47 / 240.02 4586.64 / 303.92
512K 254.75 / 232.05 4591.17 / 288.27
1M 238.88 / 233.64 4638.81 / 341.00
Dontcache left zero target-file pages resident at every size. Normal
retained about 1.19--1.24 million pages. Normal runs incurred roughly
15.6 million kswapd page scans and steals per run, while dontcache recorded
zero. Direct scan and allocation-stall deltas were zero in both modes.
A controlled explicit-dontcache model issued 64 KiB writes for 120 seconds
at 64, 128, and 256 MiB/s. Both modes sustained all three rates in both
rounds with no final schedule overrun. Between 0.02% and 0.41% of writes
completed late, with a maximum schedule lag of 3.3--6.0 ms. Dontcache left
zero target pages resident. This was a controlled model, not an unchanged
Xiaomi application.
Buffered read throughput was:
I/O normal MiB/s dontcache MiB/s change
4K 1825.50 1695.10 -7.14%
8K 1901.46 1847.96 -2.81%
16K 1941.60 1872.55 -3.56%
32K 1960.95 1905.92 -2.81%
64K 1951.35 1886.54 -3.32%
128K 1960.03 1915.82 -2.26%
256K 1976.01 1900.41 -3.83%
512K 1973.31 1911.24 -3.15%
1M 2230.91 2007.82 -10.00%
Dontcache left zero source pages resident in all measured read runs.
The normal-I/O control showed read-throughput differences of +0.67%,
-0.90%, and -2.58%, and write-throughput differences of -1.75%, +0.33%,
and +2.33%, at 4 KiB, 64 KiB, and 1 MiB respectively.
Changes since v3:
- use the common block task-context completion infrastructure;
- rebase onto the current F2FS development branch based on v7.3-rc1.
Wenjie Qi (2):
f2fs: complete dropbehind write bios in task context
f2fs: enable buffered RWF_DONTCACHE
fs/f2fs/data.c | 27 +++++++++++++++++++++------
fs/f2fs/file.c | 2 +-
2 files changed, 22 insertions(+), 7 deletions(-)
--
2.43.0
This series enables buffered RWF_DONTCACHE on F2FS for sustained one-pass
streaming writes, where retaining the written data can displace more useful
cache.
Patch 1 marks dropbehind write bios with BIO_COMPLETE_IN_TASK. Normal and
dropbehind folios may share otherwise mergeable IPU and OPU bios; the flag
is set monotonically when a dropbehind folio joins an existing bio. The
block layer owns deferral from unsafe completion contexts.
Patch 2 passes FGP_DONTCACHE to the F2FS buffered write folio lookup,
advertises FOP_DONTCACHE, and handles internal write_begin callers that
pass a NULL kiocb.
Tests were run on a Xiaomi phone with 10.7 GiB of kernel-visible memory,
running Android 16 and Linux 6.12.69 with 4 KiB pages. /data used F2FS.
The performance test wrote exactly 64 GiB per run at 4 KiB,
8 KiB, 16 KiB, 32 KiB, 64 KiB, 128 KiB, 256 KiB, 512 KiB, and 1 MiB.
Two counterbalanced rounds ran ascending normal-first and descending
dontcache-first. Values below are equal-weight means of both runs; N=2.
The pwritev2() writer models the streaming workload; it does not show that
an unchanged Android application already issues RWF_DONTCACHE.
Android remained active with displays off. Each run started after a cache
reset and at least 120 seconds of cooldown. Throughput and one-second
kswapd0/global-memory samples cover the write loop.
Write-loop throughput was:
normal MiB/s dontcache MiB/s
I/O r1 r2 mean r1 r2 mean change
4K 946.28 935.74 941.01 291.36 309.31 300.33 -68.08%
8K 1077.05 1105.84 1091.45 477.79 479.79 478.79 -56.13%
16K 1126.84 1118.49 1122.67 643.40 652.06 647.73 -42.30%
32K 1150.62 1036.33 1093.48 762.24 751.45 756.84 -30.79%
64K 1144.80 1163.82 1154.31 852.11 851.19 851.65 -26.22%
128K 1166.29 1162.84 1164.57 867.47 865.05 866.26 -25.61%
256K 1153.61 1172.78 1163.19 895.53 885.33 890.43 -23.45%
512K 1173.61 1197.34 1185.48 903.09 903.01 903.05 -23.82%
1M 1126.22 1154.59 1140.41 850.74 894.60 872.67 -23.48%
Average kswapd0 CPU and average global Cached were:
I/O kswapd0 CPU, normal/DC Cached MiB, normal/DC
4K 18.45% / 0% 4830.15 / 686.56
8K 21.60% / 0% 4862.35 / 591.48
16K 22.75% / 0% 4905.47 / 625.07
32K 22.05% / 0% 4945.82 / 561.59
64K 23.46% / 0% 4920.77 / 639.78
128K 23.16% / 0% 4971.37 / 693.26
256K 23.68% / 0% 4956.93 / 668.60
512K 24.25% / 0% 4972.22 / 663.92
1M 22.01% / 0% 5001.09 / 705.30
Other global memory means were:
MemAvailable MiB Dirty MiB Writeback MiB
I/O normal / DC normal / DC normal / DC
4K 6513.08 / 6382.31 640.48 / 33.93 37.94 / 0.09
8K 6560.77 / 6529.33 690.89 / 43.57 40.84 / 0.54
16K 6587.46 / 6519.94 789.16 / 62.67 61.58 / 4.64
32K 6571.95 / 6566.74 850.48 / 69.14 67.69 / 9.24
64K 6600.64 / 6559.89 856.97 / 134.28 59.60 / 16.19
128K 6627.03 / 6465.10 873.68 / 137.57 60.57 / 41.50
256K 6615.58 / 6541.09 885.98 / 158.15 61.25 / 29.57
512K 6625.52 / 6534.41 900.65 / 139.07 63.65 / 30.35
1M 6677.09 / 6539.89 909.70 / 187.56 51.58 / 33.46
Active(file) MiB Inactive(file) MiB
I/O normal / DC normal / DC
4K 279.57 / 264.13 4426.38 / 183.12
8K 262.32 / 260.97 4472.62 / 182.19
16K 392.09 / 252.95 4392.78 / 195.82
32K 254.30 / 248.44 4554.18 / 187.34
64K 252.73 / 244.94 4545.40 / 267.28
128K 322.02 / 243.95 4530.63 / 298.91
256K 245.47 / 240.02 4586.64 / 303.92
512K 254.75 / 232.05 4591.17 / 288.27
1M 238.88 / 233.64 4638.81 / 341.00
Dontcache left zero target-file pages resident at every size. Normal
retained about 1.19--1.24 million pages. Normal runs incurred roughly
15.6 million kswapd page scans and steals per run, while dontcache recorded
zero. Direct scan and allocation-stall deltas were zero in both modes.
A controlled explicit-dontcache model issued 64 KiB writes for 120 seconds
at 64, 128, and 256 MiB/s. Both modes sustained all three rates in both
rounds with no final schedule overrun. Between 0.02% and 0.41% of writes
completed late, with a maximum schedule lag of 3.3--6.0 ms. Dontcache left
zero target pages resident. This was a controlled model, not an unchanged
Xiaomi application.
Buffered read throughput was:
I/O normal MiB/s dontcache MiB/s change
4K 1825.50 1695.10 -7.14%
8K 1901.46 1847.96 -2.81%
16K 1941.60 1872.55 -3.56%
32K 1960.95 1905.92 -2.81%
64K 1951.35 1886.54 -3.32%
128K 1960.03 1915.82 -2.26%
256K 1976.01 1900.41 -3.83%
512K 1973.31 1911.24 -3.15%
1M 2230.91 2007.82 -10.00%
Dontcache left zero source pages resident in all measured read runs.
The normal-I/O control showed read-throughput differences of +0.67%,
-0.90%, and -2.58%, and write-throughput differences of -1.75%, +0.33%,
and +2.33%, at 4 KiB, 64 KiB, and 1 MiB respectively.
As a separate memory-pressure supplement, I tested F2FS on x86-64 QEMU
with the F2FS images backed by the host NVMe. Each run issued a 1-GiB
homogeneous sequential write using 8-KiB or 1-MiB I/O. Normal and
dontcache each ran in three counterbalanced rounds with
memory.max=255852544, memory.swap.max=0, and formal tracing was disabled.
Values below are medians of three completed runs.
I/O N done D done MiB/s N/D memcg MiB N/D
8 KiB 3/3 3/3 236.259/227.634 160.867/2.075
1 MiB 3/3 3/3 222.232/859.805 155.178/9.098
I/O scan N/D steal N/D
8 KiB 270,821/0 201,227/0
1 MiB 344,267/0 201,013/0
Scan is the number of pages examined by reclaim, while steal is the number
of pages successfully reclaimed. memcg MiB is average memory.current.
At 8 KiB, dontcache throughput was 3.65% lower. The paired changes were
-12.7%, +65.8%, and -3.65%, so the direction was not stable. At 1 MiB,
dontcache throughput was 286.90% higher, and all three paired changes were
positive: +96.1%, +257.8%, and +295.8%. Average memory.current decreased by
98.71% at 8 KiB and 94.14% at 1 MiB. Dontcache recorded zero scan and steal
in both profiles.
Changes since v4:
- allow normal and dropbehind folios to share write bios, following iomap,
and set BIO_COMPLETE_IN_TASK when a dropbehind folio joins an existing
bio;
- handle internal write_begin callers that pass a NULL kiocb;
- add QEMU memory-pressure and mixed-bio measurements.
Wenjie Qi (2):
f2fs: complete dropbehind write bios in task context
f2fs: enable buffered RWF_DONTCACHE
fs/f2fs/data.c | 15 ++++++++++++---
fs/f2fs/file.c | 2 +-
2 files changed, 13 insertions(+), 4 deletions(-)
--
2.43.0
Hi Jaegeuk and Chao, Friendly ping on this series. v5 includes the mixed-bio completion update, the syzbot NULL-kiocb fix, and the additional memory-pressure data. Please let me know if this direction is acceptable or if another revision is needed. Thanks, Wenjie
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.
Normal folios can safely share a bio that needs task-context
completion: they do not carry the dropbehind flag and are not invalidated
at their own writeback completion. Follow iomap and allow otherwise
mergeable normal and dropbehind folios to share IPU and OPU bios.
If a dropbehind folio joins an existing bio, set
BIO_COMPLETE_IN_TASK after the add succeeds. 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>
---
An F2FS QEMU A/B ran 80 untraced 1-GiB formal cases: ten
counterbalanced pairs for each OPU/IPU and 4-KiB/64-KiB profile.
The primary write-plus-fdatasync mixed/segregated ratios were:
Path I/O Mixed/segregated Interpretation
OPU 4 KiB 1.133 Mixed was 13.3% faster
OPU 64 KiB 1.021 Mixed was 2.1% faster
IPU 4 KiB 4.469 Mixed was 4.47x as fast
IPU 64 KiB 1.063 Mixed was 6.3% faster
A separate 64-MiB IPU/4-KiB trace observed 16,384 segregated DATA bios,
all 4 KiB, versus 117 mixed DATA bios with a maximum of 13.21 MiB. Deferred
bios were 8,192 versus 117.
Changes since v4:
- allow normal and dropbehind folios to share IPU and OPU bios;
- set BIO_COMPLETE_IN_TASK monotonically after a dropbehind folio is
successfully added to an existing bio;
- add focused segregated/mixed QEMU results.
fs/f2fs/data.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index ebb0275aa8f..fc48a752fe9 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;
@@ -865,6 +867,8 @@ static int add_ipu_page(struct f2fs_io_info *fio, struct bio **bio,
fio_folio->mapping->host,
fio_folio->index, fio) &&
bio_add_folio(*bio, folio, folio_size(folio), 0)) {
+ if (folio_test_dropbehind(fio->folio))
+ bio_set_flag(*bio, BIO_COMPLETE_IN_TASK);
ret = 0;
break;
}
@@ -1100,6 +1104,8 @@ void f2fs_submit_page_write(struct f2fs_io_info *fio)
__submit_merged_bio(io);
goto alloc_new;
}
+ if (folio_test_dropbehind(fio->folio))
+ bio_set_flag(io->bio, BIO_COMPLETE_IN_TASK);
if (fio->io_wbc)
wbc_account_cgroup_owner(fio->io_wbc, fio->folio,
--
2.43.0
Pass FGP_DONTCACHE to f2fs_filemap_get_folio() for
IOCB_DONTCACHE writes and advertise FOP_DONTCACHE.
The address-space write_begin callback is also used by internal
callers that pass a NULL kiocb, including page_symlink(). Check iocb before
inspecting its flags.
Keep the F2FS-specific lookup because write_begin_get_folio() adds
FGP_STABLE, which can deadlock here.
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>
---
Changes since v4:
- handle internal write_begin callers that pass a NULL kiocb;
- add syzbot report attribution.
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 fc48a752fe9..c9b29882f07 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -3883,11 +3883,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 && iocb->ki_flags & IOCB_DONTCACHE)
+ fgp_flags |= FGP_DONTCACHE;
+
trace_f2fs_write_begin(inode, pos, len);
if (!f2fs_is_checkpoint_ready(sbi)) {
@@ -3933,9 +3937,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 c763fb972e8..92f916ca8b9 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -5920,6 +5920,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
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.
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
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.
© 2016 - 2026 Red Hat, Inc.