[PATCH v2] f2fs: avoid underflow when counting free NIDs

From: Kelvin Zhang

Date: Mon Aug 31 2026 - 21:34:41 EST


__count_free_nids() subtracts the retention threshold before checking
whether the cached count exceeds it. The operands are unsigned, so a
smaller cache wraps before the result is assigned to long.

The PAGE_SIZE-derived threshold happens to make this an unsigned long
subtraction, whose wrapped result becomes negative when converted to
long by supported toolchains. Do not rely on operand width or
unsigned-to-signed conversion. Compare values before subtracting.

Fixes: 1b38dc8e74a3 ("f2fs: shrink nat_cache entries")
Fixes: 02110a4fd531 ("f2fs: avoid casted negative value as shrink count")
Cc: stable@xxxxxxxxxx
Reviewed-by: Chao Yu <chao@xxxxxxxxxx>
Signed-off-by: Kelvin Zhang <zhangxp1998@xxxxxxxxx>
---
Changes since v1:
- add the Fixes and stable Cc trailers suggested by Chao
- carry Chao's Reviewed-by
- resend as a standalone patch through direct SMTP because the v1 list copy
was corrupted by mail transport line wrapping

v1: https://lore.kernel.org/linux-f2fs-devel/CAH=xXfG2Hzc-kNAPqEUsTJ4hwrQ-gYEnFrXHGxL7qpYpggkLUQ@xxxxxxxxxxxxxx/
---
fs/f2fs/shrinker.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/fs/f2fs/shrinker.c b/fs/f2fs/shrinker.c
index 4f6bf5926de4..1fd0ee4f89a9 100644
--- a/fs/f2fs/shrinker.c
+++ b/fs/f2fs/shrinker.c
@@ -23,9 +23,10 @@ static unsigned long __count_nat_entries(struct f2fs_sb_info *sbi)

static unsigned long __count_free_nids(struct f2fs_sb_info *sbi)
{
- long count = NM_I(sbi)->nid_cnt[FREE_NID] - MAX_FREE_NIDS;
+ unsigned long count = NM_I(sbi)->nid_cnt[FREE_NID];
+ unsigned long max = MAX_FREE_NIDS;

- return count > 0 ? count : 0;
+ return count > max ? count - max : 0;
}

static unsigned long __count_extent_cache(struct f2fs_sb_info *sbi,

base-commit: c966d29e01bbf829f8bb4a39a49811c56cdb49c3
--
2.53.0