[RFC PATCH 1/3] f2fs: prepare cur_valid_map for safe lockless access

From: 'wallentx

Date: Mon Mar 09 2026 - 06:38:53 EST


From: wallentx <william.allentx@xxxxxxxxx>

checkpoint validation and segment_bits_seq_show() can read
cur_valid_map without taking the segment lock.

A following patch will allow zoned LFS segments to switch between
shared and private SIT valid maps, so those readers need to tolerate
pointer publication safely.

Prepare for that by reading cur_valid_map under RCU in the lockless
paths and by publishing the initial map pointer with RCU semantics.
This is preparatory and does not change the SIT layout or allocation
policy yet.

Signed-off-by: wallentx <william.allentx@xxxxxxxxx>
---
fs/f2fs/checkpoint.c | 4 +++-
fs/f2fs/segment.c | 3 ++-
fs/f2fs/sysfs.c | 9 ++++++++-
3 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
index 6dd39b7de11a..7b196d9df0f7 100644
--- a/fs/f2fs/checkpoint.c
+++ b/fs/f2fs/checkpoint.c
@@ -354,7 +354,9 @@ static bool __is_bitmap_valid(struct f2fs_sb_info *sbi, block_t blkaddr,
offset = GET_BLKOFF_FROM_SEG0(sbi, blkaddr);
se = get_seg_entry(sbi, segno);

- exist = f2fs_test_bit(offset, se->cur_valid_map);
+ rcu_read_lock();
+ exist = f2fs_test_bit(offset, rcu_dereference(se->cur_valid_map));
+ rcu_read_unlock();

/* skip data, if we already have an error in checkpoint. */
if (unlikely(f2fs_cp_error(sbi)))
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index 23faf6725632..c9cfc8f17698 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -4845,7 +4845,8 @@ static int build_sit_info(struct f2fs_sb_info *sbi)
bitmap = sit_i->bitmap;

for (start = 0; start < MAIN_SEGS(sbi); start++) {
- sit_i->sentries[start].cur_valid_map = bitmap;
+ rcu_assign_pointer(sit_i->sentries[start].cur_valid_map,
+ bitmap);
bitmap += SIT_VBLOCK_MAP_SIZE;

sit_i->sentries[start].ckpt_valid_map = bitmap;
diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c
index 969e06b65b04..9c79f7b63583 100644
--- a/fs/f2fs/sysfs.c
+++ b/fs/f2fs/sysfs.c
@@ -1782,11 +1782,18 @@ static int __maybe_unused segment_bits_seq_show(struct seq_file *seq,

for (i = 0; i < total_segs; i++) {
struct seg_entry *se = get_seg_entry(sbi, i);
+ unsigned char map[SIT_VBLOCK_MAP_SIZE];

seq_printf(seq, "%-10d", i);
seq_printf(seq, "%d|%-3u|", se->type, se->valid_blocks);
+
+ rcu_read_lock();
+ memcpy(map, rcu_dereference(se->cur_valid_map),
+ SIT_VBLOCK_MAP_SIZE);
+ rcu_read_unlock();
+
for (j = 0; j < SIT_VBLOCK_MAP_SIZE; j++)
- seq_printf(seq, " %.2x", se->cur_valid_map[j]);
+ seq_printf(seq, " %.2x", map[j]);
seq_printf(seq, "| %llx", se->mtime);
seq_putc(seq, '\n');
}
--
2.53.0