mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] f2fs: avoid underflow in get_available_block_count()
@ 2026-11-14  1:17 Daeho Jeong
  0 siblings, 0 replies; only message in thread
From: Daeho Jeong @ 2026-11-14  1:17 UTC (permalink / raw)
  To: linux-kernel, linux-f2fs-devel, kernel-team; +Cc: Daeho Jeong, stable

From: Daeho Jeong <daehojeong@google.com>

get_available_block_count() subtracts current_reserved_blocks,
alias_reserved_blocks and root_reserved_blocks from user_block_count
without checking the result. Only unusable_block_count is handled so
that the result does not go below 0.

f2fs_ioc_reserve_dev_alias() checks the free space with the root
reserved blocks allowed when root calls it, so alias_reserved_blocks can
overlap with the root reserved blocks until the reservation is turned
into valid blocks. For example, with

  user_block_count = 1000, root_reserved_blocks = 100, valid blocks = 30

reserving an alias device of 950 blocks passes the check, since
30 + 950 <= 1000, and sets alias_reserved_blocks to 950. Then, for a
user who cannot use the root reserved blocks, the available block count
is 1000 - 950 - 100, which wraps around to a huge value, so the check in
inc_valid_block_count() does not stop such a user until the reservation
is done.

current_reserved_blocks can make it wrap in the same way, for root as
well, when reserved_blocks is written through sysfs in the meantime,
since it is set without considering alias_reserved_blocks.

Sum up all the reservations and return 0 if they do not fit in
user_block_count, as was done for unusable_block_count only.

Fixes: eae3faf210bd ("f2fs: support dynamic reserve/release for device aliasing")
Cc: stable@vger.kernel.org
Signed-off-by: Daeho Jeong <daehojeong@google.com>
---
This was discussed in the review of "[PATCH v2] f2fs: reserve space to be
shrunk during resize_fs" [1]. v3 of that patch is sent separately on top
of this one.

[1] https://lore.kernel.org/linux-f2fs-devel/20261022165526.1539629-1-daeho43@gmail.com/

 fs/f2fs/f2fs.h | 21 +++++++++------------
 1 file changed, 9 insertions(+), 12 deletions(-)

diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 50a5f845176d..59bc3c2fb70a 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -2710,23 +2710,20 @@ static inline bool __allow_reserved_root(struct f2fs_sb_info *sbi,
 static inline unsigned int get_available_block_count(struct f2fs_sb_info *sbi,
 						struct inode *inode, bool cap)
 {
-	block_t avail_user_block_count;
-
-	avail_user_block_count = sbi->user_block_count -
-					sbi->current_reserved_blocks -
+	u64 reserved = (u64)sbi->current_reserved_blocks +
 					sbi->alias_reserved_blocks;
 
 	if (test_opt(sbi, RESERVE_ROOT) && !__allow_reserved_root(sbi, inode, cap))
-		avail_user_block_count -= F2FS_OPTION(sbi).root_reserved_blocks;
+		reserved += F2FS_OPTION(sbi).root_reserved_blocks;
 
-	if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) {
-		if (avail_user_block_count > sbi->unusable_block_count)
-			avail_user_block_count -= sbi->unusable_block_count;
-		else
-			avail_user_block_count = 0;
-	}
+	if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED)))
+		reserved += sbi->unusable_block_count;
+
+	/* the reservations can overlap each other, so do not wrap around */
+	if (unlikely(reserved >= sbi->user_block_count))
+		return 0;
 
-	return avail_user_block_count;
+	return sbi->user_block_count - reserved;
 }
 
 static inline void f2fs_i_blocks_write(struct inode *, block_t, bool, bool);

base-commit: b9d7379d10d43386b59082da8c9a0b111e054781
-- 
2.56.0.611.g1030f0b940-goog


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2026-11-14  1:17 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-14  1:17 [PATCH] f2fs: avoid underflow in get_available_block_count() Daeho Jeong

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®