diff options
| author | Cen Zhang <zzzccc427@gmail.com> | 2026-05-05 20:55:10 +0800 |
|---|---|---|
| committer | Jaegeuk Kim <jaegeuk@kernel.org> | 2026-06-22 19:52:34 +0000 |
| commit | fb645a976f53b175a49bdf52cfcd2c56f4b1456a (patch) | |
| tree | d9f3b02adc35369eb53b5450cc91dad4c514ced0 | |
| parent | b952837f734c3a627877bf922408dac04588a643 (diff) | |
f2fs: annotate lockless NAT counter reads
nat_cnt[] is updated while callers hold nat_tree_lock, but F2FS samples
the counters locklessly in f2fs_available_free_memory(),
excess_dirty_nats(), and excess_cached_nats(). Those helpers only steer
cache reclaim and background sync heuristics; they do not control NAT
entry lifetime or checkpoint correctness.
Document the intent with data_race(READ_ONCE()) and a short comment
instead of adding locking to the balance path.
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
| -rw-r--r-- | fs/f2fs/node.c | 6 | ||||
| -rw-r--r-- | fs/f2fs/node.h | 8 |
2 files changed, 11 insertions, 3 deletions
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index b1247de25411..a464d5ee1124 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -73,7 +73,11 @@ bool f2fs_available_free_memory(struct f2fs_sb_info *sbi, int type) sizeof(struct free_nid)) >> PAGE_SHIFT; res = mem_size < ((avail_ram * nm_i->ram_thresh / 100) >> 2); } else if (type == NAT_ENTRIES) { - mem_size = (nm_i->nat_cnt[TOTAL_NAT] * + /* + * nat_cnt[] is heuristic accounting. Sample it locklessly here + * to avoid taking nat_tree_lock in the balance path. + */ + mem_size = (data_race(READ_ONCE(nm_i->nat_cnt[TOTAL_NAT])) * sizeof(struct nat_entry)) >> PAGE_SHIFT; res = mem_size < ((avail_ram * nm_i->ram_thresh / 100) >> 2); if (excess_cached_nats(sbi)) diff --git a/fs/f2fs/node.h b/fs/f2fs/node.h index bcf2034e4263..5e114f352099 100644 --- a/fs/f2fs/node.h +++ b/fs/f2fs/node.h @@ -129,13 +129,17 @@ static inline void raw_nat_from_node_info(struct f2fs_nat_entry *raw_ne, static inline bool excess_dirty_nats(struct f2fs_sb_info *sbi) { - return NM_I(sbi)->nat_cnt[DIRTY_NAT] >= NM_I(sbi)->max_nid * + /* nat_cnt[] is heuristic accounting sampled locklessly here. */ + return data_race(READ_ONCE(NM_I(sbi)->nat_cnt[DIRTY_NAT])) >= + NM_I(sbi)->max_nid * NM_I(sbi)->dirty_nats_ratio / 100; } static inline bool excess_cached_nats(struct f2fs_sb_info *sbi) { - return NM_I(sbi)->nat_cnt[TOTAL_NAT] >= DEF_NAT_CACHE_THRESHOLD; + /* nat_cnt[] is heuristic accounting sampled locklessly here. */ + return data_race(READ_ONCE(NM_I(sbi)->nat_cnt[TOTAL_NAT])) >= + DEF_NAT_CACHE_THRESHOLD; } enum mem_type { |
