From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BCF0128D831 for ; Tue, 25 Aug 2026 01:27:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787621229; cv=none; b=somDrtqYOrN/P7EwN80I9i4VKhq0NTF+5JbVe19V0I9A1ICV461G9fXWIUl6Fnb6Ip2c7NQEZ2MHIY8lk/RuFoI5mkFrx280ILFwxSscXnJGxMt3aRybHgcB9Eta6pl+OnmcomdYBlQufo+78VR88H2wg5HEPmrKOqkpgPXcecM= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787621229; c=relaxed/simple; bh=XcYsDBIVm2euzAwKF7QphUOcBlKoyShUDKpAlCTJh6s=; h=Message-ID:Date:MIME-Version:Cc:Subject:To:References:From: In-Reply-To:Content-Type; b=B1JBcMHpCVIIqYIAtr70vv38sfz711QAJK99OvCMndQa5O6KgxlEcO9AG990Nsx0rahAGJtMgKL5DO16qYcwzShUbbEkYKq5I88ZdBmN0DARA4nkdSbTT/TA8INNAb12yOA843lUJ8zBe/hEz6eqLvdZQ5zTXlglMG7VZJuzYi8= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=QymtTB3d; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="QymtTB3d" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 24BAE1F000E9; Tue, 25 Aug 2026 01:27:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1787621227; bh=M+Xl4sVRDzIEksh7IPs2vgHPZG7H1Ti4kamwZwxyyfY=; h=Date:Cc:Subject:To:References:From:In-Reply-To; b=QymtTB3d1RRAcV9maY7grkB7Mkswf9VW4WLp7nR8FRptprmLXj/M62B3c4MefhmVX 7/FkezZABro9XuyE6F0+mV5Y+pk4u+cegmVKGBVgu1kVcAQFNHNc0INvYr28AcT1dM 0Ds408CmcmFitsCI0x2ngZDNVLCFQKVnGlGdl1jXY0Xrm9p1NLoVwkfBxSSSxAFoY7 0GcZOnO/o1TiCGF4H/wj93UTleJgYZom7MSiEXKbN45MUpLzze90Y6nX5rOe6E+C4n ZY5DrQU64lxt4UHzApT1BxBpwBKq/Hq3xngZQ8rhsjZ8XRheMwCj0iqKU7p3xpZSrQ i80ERhzRyqppg== Message-ID: Date: Tue, 25 Aug 2026 09:27:04 +0800 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Cc: chao@kernel.org, linux-kernel@vger.kernel.org, linux-f2fs-devel@lists.sourceforge.net, kernel-team@android.com, Daeho Jeong Subject: Re: [f2fs-dev] [PATCH] f2fs: accurately adjust free_sections during free_segment_range To: Daeho Jeong References: <20260818171412.3201082-1-daeho43@gmail.com> <2b2dc21a-a78d-416c-aa4f-7531c1b62321@kernel.org> Content-Language: en-US From: Chao Yu In-Reply-To: Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit On 8/25/26 09:21, Daeho Jeong wrote: > On Mon, Aug 24, 2026 at 6:05 PM Chao Yu wrote: >> >> On 8/19/26 01:14, Daeho Jeong wrote: >>> From: Daeho Jeong >>> >>> In free_segment_range(), MAIN_SECS(sbi) is temporarily reduced by `secs` >>> while valid blocks in the truncated range are evacuated by GC. >>> >>> However, if any sections within the truncated range were already free, >>> failing to deduct them from FREE_I(sbi)->free_sections leads to an >>> over-estimation of available space in the reduced main area, causing >>> inconsistent free section accounting. >>> >>> Fix this by calculating the number of already-free sections in the >>> truncated range under segmap_lock, deducting them from free_sections upon >>> entering free_segment_range(), and restoring them under segmap_lock on exit. >> >> I think we need to change commit message a bit to reflect real issues? >> >> Fixes and Cc stable line here. >> >>> >>> Signed-off-by: Daeho Jeong >>> Signed-off-by: Sunmin Jeong >>> --- >>> fs/f2fs/gc.c | 15 ++++++++++++++- >>> 1 file changed, 14 insertions(+), 1 deletion(-) >>> >>> diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c >>> index 787133ee2eb2..f3a6fc6d08ae 100644 >>> --- a/fs/f2fs/gc.c >>> +++ b/fs/f2fs/gc.c >>> @@ -2200,8 +2200,9 @@ int f2fs_gc_range(struct f2fs_sb_info *sbi, >>> static int free_segment_range(struct f2fs_sb_info *sbi, >>> unsigned int secs, bool dry_run) >>> { >>> - unsigned int next_inuse, start, end; >>> + unsigned int secno, next_inuse, start, end, end_secno; >>> struct cp_control cpc = { CP_RESIZE, 0, 0, 0 }; >>> + unsigned int freed_secs = 0; >>> int gc_mode, gc_type; >>> int err = 0; >>> int type; >>> @@ -2210,6 +2211,7 @@ static int free_segment_range(struct f2fs_sb_info *sbi, >>> MAIN_SECS(sbi) -= secs; >>> start = MAIN_SECS(sbi) * SEGS_PER_SEC(sbi); >>> end = MAIN_SEGS(sbi) - 1; >>> + end_secno = GET_SEC_FROM_SEG(sbi, end); >>> >>> mutex_lock(&DIRTY_I(sbi)->seglist_lock); >>> for (gc_mode = 0; gc_mode < MAX_GC_POLICY; gc_mode++) >>> @@ -2221,6 +2223,14 @@ static int free_segment_range(struct f2fs_sb_info *sbi, >>> sbi->next_victim_seg[gc_type] = NULL_SEGNO; >>> mutex_unlock(&DIRTY_I(sbi)->seglist_lock); >>> >>> + spin_lock(&FREE_I(sbi)->segmap_lock); >>> + for (secno = MAIN_SECS(sbi); secno <= end_secno; secno++) { >>> + if (!test_bit(secno, FREE_I(sbi)->free_secmap)) >>> + freed_secs++; >>> + } >>> + FREE_I(sbi)->free_sections -= freed_secs; >>> + spin_unlock(&FREE_I(sbi)->segmap_lock); >>> + >> >> Before f2fs_gc_range >> 0..89 have 10 dirty/full sections, 80 free sections. >> 90..99 have 5 dirty sections, 5 free sections. >> >> FREE_I(sbi)->free_sections -= freed_secs; >> free_sections = 85 - 5 = 80 >> >> After f2fs_gc_range >> 0..89 have 13 dirty/full sections, 77 free sections. >> 90..99 have 10 free sections. >> free_sections = 77 (.free_sections) + 10 (secs) = 87 >> >>> /* Move out cursegs from the target range */ >>> for (type = CURSEG_HOT_DATA; type < NR_CURSEG_TYPE; type++) { >>> err = f2fs_allocate_segment_for_resize(sbi, type, start, end); >>> @@ -2245,6 +2255,9 @@ static int free_segment_range(struct f2fs_sb_info *sbi, >>> f2fs_bug_on(sbi, 1); >>> } >>> out: >>> + spin_lock(&FREE_I(sbi)->segmap_lock); >>> + FREE_I(sbi)->free_sections += freed_secs; >> >> So, shouldn't be? >> FREE_I(sbi)->free_sections += secs; > > During f2fs_gc_range(), when the dirty sections in 90..99 are cleaned and > freed, `__set_test_and_free()` is invoked for those sections, which > automatically increments `FREE_I(sbi)->free_sections` for each newly > freed section? Ah, I see, thanks for correcting me. :) Thanks, > >> >> Thanks, >> >>> + spin_unlock(&FREE_I(sbi)->segmap_lock); >>> MAIN_SECS(sbi) += secs; >>> return err; >>> } >>