From nobody Sun Dec 14 05:53:38 2025 Received: from mail-pl1-f201.google.com (mail-pl1-f201.google.com [209.85.214.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 469FB30FC10 for ; Fri, 12 Dec 2025 08:40:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1765528843; cv=none; b=GAxGmASLUyhOhBSyqZloD85kmxvyAzBlE+UqHDetSe6XT4f3hL6k8gF4K2zvggc+wvvaVG7xm7unPfOaM9LAZqKDpvoZJjNQaCHMSS9oVi/O9ANlLlcn3F4atkCL9MTLvam3uZNf45PJUDWNqU3nUiU/TYTi+kYcICqWSbH3sNY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1765528843; c=relaxed/simple; bh=MY1UYFT10XbFeF+OAsDLxxt7tF7cowav6E88HSyewBc=; h=Date:Mime-Version:Message-ID:Subject:From:To:Cc:Content-Type; b=Vj9ljxFyL6ER70oOjgR9YMX+24+bo8QPtsDv6o2xMBhC+J48F+x4B8x+0Gh/cLbkEqL8SgGt8Ucxa2S70JVBl4ZufUwgN6eZlbtpPoiZg8YFrd+b48cBNg0oUPK+Nia5p6Bc1Q03VtypSkCVXrpLL8xOrNXy8mT+U/e34BgFoX0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--joannechien.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=y41fpvnx; arc=none smtp.client-ip=209.85.214.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--joannechien.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="y41fpvnx" Received: by mail-pl1-f201.google.com with SMTP id d9443c01a7336-2956cdcdc17so11237395ad.3 for ; Fri, 12 Dec 2025 00:40:42 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1765528841; x=1766133641; darn=vger.kernel.org; h=content-transfer-encoding:cc:to:from:subject:message-id :mime-version:date:from:to:cc:subject:date:message-id:reply-to; bh=J+1Q31liwzyxEUF9mCpDGCaZblwD4ntldwQB7kNf2wk=; b=y41fpvnxo1sTA0iQ0nGUSgUhRed/kHQPTEpvwEvE7SinxCVBKb5J4NNXdtzAG5miOI sOTylz7RM7I3TOYw/GJ+MbKgFW2hLyOAM+2EMjkBm251fT35LLA7bMbSX+9r+ZOBuq6M AeQoic1ifk/O9JecvHwKjxDBIwmoAVBFoC4MjUO5TDMBffDFrdtNbBnUhi1ocConEDrS CbMBxbzLU24wpCWbDabKVpMS1SG/fbag7ZVdLeBn1fmsPuBn+Am/p3Cc9Qmxse+vobiM 6i/ueRDLD6e/uKOpEFigUWsiOkeusq8qjQkYUiHdGwMCqwLdF4BUoLa6RUeELYRNpnlt RS7Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1765528841; x=1766133641; h=content-transfer-encoding:cc:to:from:subject:message-id :mime-version:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=J+1Q31liwzyxEUF9mCpDGCaZblwD4ntldwQB7kNf2wk=; b=PnxCcYLrqZItAqk7oIjL17BPW4bjWbzF320s9K521+Pz3Yt7TLx71iz/VkvW14BrCz UGfo+Y9SiUXsrZwr7ZCbQ0JYN7EC6hezyQwv9roxGJNcCqX/hOJisvGx4MJKyo8H5Qry CpVsWEpiOldVjyTWChkTcy86d9xSy8QNqrwQz9b5HySDUY3aReK7lpVJ4eQg7pqahjfJ 8w3IphQKXOw8SP/PhtCl8Kno+T0yMwFT1SKLdHnGaDIIlvGGxD5Ex85nSEgPl6bw0EPL eetJGJXyg+v99hUZc96sCsXxRk8jbbGxvgPBAuXzf163B+khu3fe4CWUQBzRkfp2hVHx SLGg== X-Forwarded-Encrypted: i=1; AJvYcCW6UwlPG1tW0Z4fmy6bEGHRbarlvjv68NYoTPIGcCzpMKxD87DXv0/TpdLxfzFQsUNCbYWcf3ZwJYuHli8=@vger.kernel.org X-Gm-Message-State: AOJu0YyEQLcfK+MjP6rKKca0m7kqA4Z4UWHm5mUSoLsBMDo1gKPB6d47 WVEMLnsfbqfCXr9OEHs/RtmmZf/lQROOP6qJtzB3nqAnOD2jGHKWdvugdVlqcHyJqHrA+61XUEs FPVxynoaw/V/KH3h+bdlVanRuqw== X-Google-Smtp-Source: AGHT+IE72j85UESVSezikTB3MO42Z+Y9yhAd2ivh3xAM8PKb/TdEyGE+LCB9khpZK8gT3uWdfvn/s2+wbN2yRAyxJA== X-Received: from plkn10.prod.google.com ([2002:a17:902:6a8a:b0:298:9ac:ccc8]) (user=joannechien job=prod-delivery.src-stubby-dispatcher) by 2002:a17:903:2f50:b0:298:60d5:d272 with SMTP id d9443c01a7336-29f23e08409mr19423385ad.17.1765528841502; Fri, 12 Dec 2025 00:40:41 -0800 (PST) Date: Fri, 12 Dec 2025 08:40:34 +0000 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 X-Mailer: git-send-email 2.52.0.239.gd5f0c6e74e-goog Message-ID: <20251212084034.2878836-1-joannechien@google.com> Subject: [PATCH v1] f2fs: improve check for enough free sections From: Joanne Chang To: Jaegeuk Kim , Chao Yu Cc: linux-f2fs-devel@lists.sourceforge.net, linux-kernel@vger.kernel.org, Joanne Chang Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The check for enough sections in segment.h has the following issues: 1. has_not_enough_free_secs() should return "enough secs" when "free_secs >=3D upper_secs", not just structly greater. Conversely, it should only return "not enough secs" when "free_secs < lower_secs", not when they are equal. This accounts for the possibility that blocks can fit within curseg without requiring an additional free section. 2. __get_secs_required() currently separates the needed space to section and block parts, checking them against free sections and curseg, respectively. This does not consider the case where curseg cannot hold the whole block part, but excess free sections beyond the section part can accommodate some of the block part. 3. has_curseg_enough_space() only checks CURSEG_HOT_DATA for dentry blocks, but when active_logs=3D6, they may be placed in WARM and COLD sections. Also, the current logic does not consider that dentry and data blocks can be put in the same section when active_logs=3D2 or 6. This patch modifies the three functions to address the above issues: 1. Rename has_curseg_enough_space() to get_additional_blocks_required(). Calculate the minimum node, dentry, and data blocks curseg can accommodate. Then subtract these from the total required blocks of respective type to determine the worst-case number of blocks that must be placed in free sections. 2. In __get_secs_required(), get the number of blocks needing new sections from the new get_additional_blocks_required(). Return the upper bound of necessary free sections for these blocks. For active_logs=3D2 or 6, dentry blocks are combined with data blocks. 3. In has_not_enough_free_secs(), get the required sections from __get_secs_required(), and return =E2=80=9Cnot enough secs=E2=80=9D if =E2= =80=9Cfree_secs < required_secs=E2=80=9D. Signed-off-by: Joanne Chang --- fs/f2fs/gc.c | 2 +- fs/f2fs/segment.h | 99 ++++++++++++++++++++++------------------------- 2 files changed, 47 insertions(+), 54 deletions(-) diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index 384fa7e2085b..6afd57fa5387 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -2000,7 +2000,7 @@ int f2fs_gc(struct f2fs_sb_info *sbi, struct f2fs_gc_= control *gc_control) goto stop; } =20 - __get_secs_required(sbi, NULL, &upper_secs, NULL); + upper_secs =3D __get_secs_required(sbi); =20 /* * Write checkpoint to reclaim prefree segments. diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h index 07dcbcbeb7c6..20daaccb34a5 100644 --- a/fs/f2fs/segment.h +++ b/fs/f2fs/segment.h @@ -621,97 +621,90 @@ static inline unsigned int get_left_section_blocks(st= ruct f2fs_sb_info *sbi, return CAP_BLKS_PER_SEC(sbi) - get_ckpt_valid_blocks(sbi, segno, true); } =20 -static inline bool has_curseg_enough_space(struct f2fs_sb_info *sbi, - unsigned int node_blocks, unsigned int data_blocks, - unsigned int dent_blocks) +static inline void get_additional_blocks_required(struct f2fs_sb_info *sbi, + unsigned int *total_node_blocks, unsigned int *total_data_blocks, + unsigned int *total_dent_blocks, bool separate_dent) { - unsigned int segno, left_blocks, blocks; + unsigned int segno, left_blocks; int i; + unsigned int min_free_node_blocks =3D CAP_BLKS_PER_SEC(sbi); + unsigned int min_free_dent_blocks =3D CAP_BLKS_PER_SEC(sbi); + unsigned int min_free_data_blocks =3D CAP_BLKS_PER_SEC(sbi); =20 /* check current data/node sections in the worst case. */ for (i =3D CURSEG_HOT_DATA; i < NR_PERSISTENT_LOG; i++) { segno =3D CURSEG_I(sbi, i)->segno; =20 if (unlikely(segno =3D=3D NULL_SEGNO)) - return false; + return; =20 left_blocks =3D get_left_section_blocks(sbi, i, segno); =20 - blocks =3D i <=3D CURSEG_COLD_DATA ? data_blocks : node_blocks; - if (blocks > left_blocks) - return false; + if (i > CURSEG_COLD_DATA) + min_free_node_blocks =3D min(min_free_node_blocks, left_blocks); + else if (i =3D=3D CURSEG_HOT_DATA && separate_dent) + min_free_dent_blocks =3D left_blocks; + else + min_free_data_blocks =3D min(min_free_data_blocks, left_blocks); } =20 - /* check current data section for dentry blocks. */ - segno =3D CURSEG_I(sbi, CURSEG_HOT_DATA)->segno; - - if (unlikely(segno =3D=3D NULL_SEGNO)) - return false; - - left_blocks =3D get_left_section_blocks(sbi, CURSEG_HOT_DATA, segno); - - if (dent_blocks > left_blocks) - return false; - return true; + *total_node_blocks =3D (*total_node_blocks > min_free_node_blocks) ? + *total_node_blocks - min_free_node_blocks : 0; + *total_dent_blocks =3D (*total_dent_blocks > min_free_dent_blocks) ? + *total_dent_blocks - min_free_dent_blocks : 0; + *total_data_blocks =3D (*total_data_blocks > min_free_data_blocks) ? + *total_data_blocks - min_free_data_blocks : 0; } =20 /* - * calculate needed sections for dirty node/dentry and call - * has_curseg_enough_space, please note that, it needs to account - * dirty data as well in lfs mode when checkpoint is disabled. + * call get_additional_blocks_required to calculate dirty blocks + * needing to be placed in free sections, please note that, it + * needs to account dirty data as well in lfs mode when checkpoint + * is disabled. */ -static inline void __get_secs_required(struct f2fs_sb_info *sbi, - unsigned int *lower_p, unsigned int *upper_p, bool *curseg_p) +static inline int __get_secs_required(struct f2fs_sb_info *sbi) { unsigned int total_node_blocks =3D get_pages(sbi, F2FS_DIRTY_NODES) + get_pages(sbi, F2FS_DIRTY_DENTS) + get_pages(sbi, F2FS_DIRTY_IMETA); unsigned int total_dent_blocks =3D get_pages(sbi, F2FS_DIRTY_DENTS); unsigned int total_data_blocks =3D 0; - unsigned int node_secs =3D total_node_blocks / CAP_BLKS_PER_SEC(sbi); - unsigned int dent_secs =3D total_dent_blocks / CAP_BLKS_PER_SEC(sbi); - unsigned int data_secs =3D 0; - unsigned int node_blocks =3D total_node_blocks % CAP_BLKS_PER_SEC(sbi); - unsigned int dent_blocks =3D total_dent_blocks % CAP_BLKS_PER_SEC(sbi); - unsigned int data_blocks =3D 0; + bool separate_dent =3D true; =20 - if (f2fs_lfs_mode(sbi)) { + if (f2fs_lfs_mode(sbi)) total_data_blocks =3D get_pages(sbi, F2FS_DIRTY_DATA); - data_secs =3D total_data_blocks / CAP_BLKS_PER_SEC(sbi); - data_blocks =3D total_data_blocks % CAP_BLKS_PER_SEC(sbi); + + /* + * When active_logs !=3D 4, dentry blocks and data blocks can be + * mixed in the same logs, so check their space together. + */ + if (F2FS_OPTION(sbi).active_logs !=3D 4) { + total_data_blocks +=3D total_dent_blocks; + total_dent_blocks =3D 0; + separate_dent =3D false; } =20 - if (lower_p) - *lower_p =3D node_secs + dent_secs + data_secs; - if (upper_p) - *upper_p =3D node_secs + dent_secs + data_secs + - (node_blocks ? 1 : 0) + (dent_blocks ? 1 : 0) + - (data_blocks ? 1 : 0); - if (curseg_p) - *curseg_p =3D has_curseg_enough_space(sbi, - node_blocks, data_blocks, dent_blocks); + get_additional_blocks_required(sbi, &total_node_blocks, &total_dent_block= s, + &total_data_blocks, separate_dent); + + return DIV_ROUND_UP(total_node_blocks, CAP_BLKS_PER_SEC(sbi)) + + DIV_ROUND_UP(total_dent_blocks, CAP_BLKS_PER_SEC(sbi)) + + DIV_ROUND_UP(total_data_blocks, CAP_BLKS_PER_SEC(sbi)); } =20 static inline bool has_not_enough_free_secs(struct f2fs_sb_info *sbi, int freed, int needed) { - unsigned int free_secs, lower_secs, upper_secs; - bool curseg_space; + unsigned int free_secs, required_secs; =20 if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING))) return false; =20 - __get_secs_required(sbi, &lower_secs, &upper_secs, &curseg_space); - free_secs =3D free_sections(sbi) + freed; - lower_secs +=3D needed + reserved_sections(sbi); - upper_secs +=3D needed + reserved_sections(sbi); + required_secs =3D needed + reserved_sections(sbi) + + __get_secs_required(sbi); =20 - if (free_secs > upper_secs) - return false; - if (free_secs <=3D lower_secs) - return true; - return !curseg_space; + return free_secs < required_secs; } =20 static inline bool has_enough_free_secs(struct f2fs_sb_info *sbi, --=20 2.52.0.239.gd5f0c6e74e-goog