[PATCH] f2fs: only redirty pinned folios in redirty_blocks
From: Wenjie Qi
Date: Mon Jul 27 2026 - 09:14:10 EST
redirty_blocks() pins folios with read_cache_folio() and then walks the
same range again with filemap_lock_folio() to redirty them and drop the
references it took.
Commit 5951fee46bef ("f2fs: Use a folio in redirty_blocks()") changed
the second pass to a do/while loop. If read_cache_folio() fails before
anything is pinned, page_idx does not advance but the cleanup loop still
runs once.
If readahead has already populated the failed folio in page cache, that
extra iteration finds it and folio_put_refs(folio, 2) drops one
reference too many. Later drop_caches or reclaim can then report
"BUG: Bad page state".
Only redirty the range that was pinned successfully.
Fixes: 5951fee46bef ("f2fs: Use a folio in redirty_blocks()")
Cc: stable@xxxxxxxxxx
Assisted-by: Codex:gpt-5.5
Signed-off-by: Wenjie Qi <qiwenjie@xxxxxxxxxx>
---
Observed on the baseline after a FAULT_READ_IO-triggered
F2FS_IOC_COMPRESS_FILE:
BUG: Bad page state in process bash pfn:1190b0
aops:f2fs_dblock_aops ino:5 dentry name(?):"redirty"
page dumped because: non-NULL mapping
Call Trace:
dump_stack_lvl+0x53/0x70
bad_page+0xd4/0x220
free_unref_folios+0x72a/0x1320
folios_put_refs+0x348/0x590
mapping_try_invalidate+0x236/0x2d0
drop_pagecache_sb+0x116/0x330
__iterate_supers+0x183/0x200
drop_caches_sysctl_handler+0x72/0x110
proc_sys_call_handler+0x352/0x540
vfs_write+0x5f8/0xf50
ksys_write+0xf9/0x1d0
do_syscall_64+0x5f/0x550
entry_SYSCALL_64_after_hwframe+0x71/0x79
fs/f2fs/file.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index c54897a25981..bb89dd738e96 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -4479,7 +4479,7 @@ static int redirty_blocks(struct inode *inode, pgoff_t page_idx, int len)
page_idx = folio_next_index(folio);
} while (page_len < len);
- do {
+ while (redirty_idx < page_idx) {
folio = filemap_lock_folio(mapping, redirty_idx);
/* It will never fail, when folio has pinned above */
@@ -4492,7 +4492,7 @@ static int redirty_blocks(struct inode *inode, pgoff_t page_idx, int len)
redirty_idx = folio_next_index(folio);
folio_unlock(folio);
folio_put_refs(folio, 2);
- } while (redirty_idx < page_idx);
+ }
return ret;
}
--
2.43.0