From nobody Sat Feb 7 11:38:27 2026 Received: from SHSQR01.spreadtrum.com (mx1.unisoc.com [222.66.158.135]) (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 A4736383 for ; Mon, 25 Nov 2024 03:12:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=222.66.158.135 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732504369; cv=none; b=bWIVQ+caSTyTVUnkmHUbTMb4mXSxVdZUoti+YlA8PoNWeE2viIRv3hA/u66FOEPINA16B+BjjCKYeW1NchHfNptYUhh0tVaRVJLMt6U6c9pnVyB2zEBaMLHG/0+jmtKyb9z04V58+6oD1GsdFN36bNim0VAcW0XawSz9dx9tUxg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732504369; c=relaxed/simple; bh=whAw5JJNDhwuLao/X3+wdw3lXHts8emTQzdlq8cj/9o=; h=From:To:CC:Subject:Date:Message-ID:References:In-Reply-To: Content-Type:MIME-Version; b=cnleMD6qrm41FA/pW/jh2Qk6M3EmDJ1DxXPG6TPbhILRLHpgGdnlZVLU9ZjqzbUKihYK7WFUpz/RRMswDLVy1HEzzComZiKfSqqVVlnhE71mPA5HbJ11ZpZ5ouy/Ze8IKnBtRuWzaWcBDyIywpjWNfDj9itC8jRYA3c/HE0R4OM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=unisoc.com; spf=pass smtp.mailfrom=unisoc.com; arc=none smtp.client-ip=222.66.158.135 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=unisoc.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=unisoc.com Received: from dlp.unisoc.com ([10.29.3.86]) by SHSQR01.spreadtrum.com with ESMTP id 4AP3BhdB014494; Mon, 25 Nov 2024 11:11:43 +0800 (+08) (envelope-from Xiuhong.Wang@unisoc.com) Received: from SHDLP.spreadtrum.com (bjmbx01.spreadtrum.com [10.0.64.7]) by dlp.unisoc.com (SkyGuard) with ESMTPS id 4XxW0k4Rh8z2L708x; Mon, 25 Nov 2024 11:10:14 +0800 (CST) Received: from BJMBX02.spreadtrum.com (10.0.64.8) by BJMBX01.spreadtrum.com (10.0.64.7) with Microsoft SMTP Server (TLS) id 15.0.1497.23; Mon, 25 Nov 2024 11:11:41 +0800 Received: from BJMBX02.spreadtrum.com ([fe80::c8c3:f3a0:9c9f:b0fb]) by BJMBX02.spreadtrum.com ([fe80::c8c3:f3a0:9c9f:b0fb%19]) with mapi id 15.00.1497.023; Mon, 25 Nov 2024 11:11:41 +0800 From: =?utf-8?B?546L56eA57qiIChYaXVob25nIFdhbmcp?= To: Chao Yu , "jaegeuk@kernel.org" CC: "linux-f2fs-devel@lists.sourceforge.net" , "linux-kernel@vger.kernel.org" , =?utf-8?B?54mb5b+X5Zu9IChaaGlndW8gTml1KQ==?= Subject: =?utf-8?B?562U5aSNOiBbUEFUQ0ggdjIgMS8yXSBmMmZzOiBmaXggdG8gc2hyaW5rIHJl?= =?utf-8?Q?ad_extent_node_in_batches?= Thread-Topic: [PATCH v2 1/2] f2fs: fix to shrink read extent node in batches Thread-Index: AQHbPKriTpuXgQFPPEKg2n4+Qt0+5rLHVgTw Date: Mon, 25 Nov 2024 03:11:40 +0000 Message-ID: <6ddf779148f44295acfbe547d9ec3aab@BJMBX02.spreadtrum.com> References: <20241122065005.3772987-1-chao@kernel.org> In-Reply-To: <20241122065005.3772987-1-chao@kernel.org> Accept-Language: zh-CN, en-US Content-Language: zh-CN X-MS-Has-Attach: X-MS-TNEF-Correlator: x-ms-exchange-transport-fromentityheader: Hosted Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MAIL: SHSQR01.spreadtrum.com 4AP3BhdB014494 Hi Chao, after tested in this weekend with these patch base on the orginal case, no = issue reproduced, so Tested-by: Xiuhong Wang thanks! Reported-by: Xiuhong Wang -----=E9=82=AE=E4=BB=B6=E5=8E=9F=E4=BB=B6----- =E5=8F=91=E4=BB=B6=E4=BA=BA: Chao Yu =20 =E5=8F=91=E9=80=81=E6=97=B6=E9=97=B4: 2024=E5=B9=B411=E6=9C=8822=E6=97=A5 1= 4:50 =E6=94=B6=E4=BB=B6=E4=BA=BA: jaegeuk@kernel.org =E6=8A=84=E9=80=81: linux-f2fs-devel@lists.sourceforge.net; linux-kernel@vg= er.kernel.org; Chao Yu ; =E7=8E=8B=E7=A7=80=E7=BA=A2 (Xiuh= ong Wang) ; =E7=89=9B=E5=BF=97=E5=9B=BD (Zhiguo Ni= u) =E4=B8=BB=E9=A2=98: [PATCH v2 1/2] f2fs: fix to shrink read extent node in = batches =E6=B3=A8=E6=84=8F: =E8=BF=99=E5=B0=81=E9=82=AE=E4=BB=B6=E6=9D=A5=E8=87=AA= =E4=BA=8E=E5=A4=96=E9=83=A8=E3=80=82=E9=99=A4=E9=9D=9E=E4=BD=A0=E7=A1=AE=E5= =AE=9A=E9=82=AE=E4=BB=B6=E5=86=85=E5=AE=B9=E5=AE=89=E5=85=A8=EF=BC=8C=E5=90= =A6=E5=88=99=E4=B8=8D=E8=A6=81=E7=82=B9=E5=87=BB=E4=BB=BB=E4=BD=95=E9=93=BE= =E6=8E=A5=E5=92=8C=E9=99=84=E4=BB=B6=E3=80=82 CAUTION: This email originated from outside of the organization. Do not cli= ck links or open attachments unless you recognize the sender and know the c= ontent is safe. We use rwlock to protect core structure data of extent tree during its shri= nk, however, if there is a huge number of extent nodes in extent tree, duri= ng shrink of extent tree, it may hold rwlock for a very long time, which ma= y trigger kernel hang issue. This patch fixes to shrink read extent node in batches, so that, critical r= egion of the rwlock can be shrunk to avoid its extreme long time hold. Reported-by: Xiuhong Wang Closes: https://lore.kernel.org/linux-f2fs-devel/20241112110627.1314632-1-x= iuhong.wang@unisoc.com/ Signed-off-by: Xiuhong Wang Signed-off-by: Zhiguo Niu Signed-off-by: Chao Yu --- v2: - no updates. fs/f2fs/extent_cache.c | 69 +++++++++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 28 deletions(-) diff --git a/fs/f2fs/extent_cache.c b/fs/f2fs/extent_cache.c index 019c1f7b= 7fa5..b7a6817b44b0 100644 --- a/fs/f2fs/extent_cache.c +++ b/fs/f2fs/extent_cache.c @@ -379,21 +379,22 @@ static struct extent_tree *__grab_extent_tree(struct = inode *inode, } static unsigned int __free_extent_tree(struct f2fs_sb_info *sbi, - struct extent_tree *et) + struct extent_tree *et, unsigned int=20 + nr_shrink) { struct rb_node *node, *next; struct extent_node *en; - unsigned int count =3D atomic_read(&et->node_cnt); + unsigned int count; node =3D rb_first_cached(&et->root); - while (node) { + + for (count =3D 0; node && count < nr_shrink; count++) { next =3D rb_next(node); en =3D rb_entry(node, struct extent_node, rb_node); __release_extent_node(sbi, et, en); node =3D next; } - return count - atomic_read(&et->node_cnt); + return count; } static void __drop_largest_extent(struct extent_tree *et, @@ -622,6 +623,3= 0 @@ static struct extent_node *__insert_extent_tree(struct f2fs_sb_info *s= bi, return en; } +static unsigned int __destroy_extent_node(struct inode *inode, + enum extent_type type) { + struct f2fs_sb_info *sbi =3D F2FS_I_SB(inode); + struct extent_tree *et =3D F2FS_I(inode)->extent_tree[type]; + unsigned int nr_shrink =3D type =3D=3D EX_READ ? + READ_EXTENT_CACHE_SHRINK_NUMBER : + AGE_EXTENT_CACHE_SHRINK_NUMBER; + unsigned int node_cnt =3D 0; + + if (!et || !atomic_read(&et->node_cnt)) + return 0; + + while (atomic_read(&et->node_cnt)) { + write_lock(&et->lock); + node_cnt +=3D __free_extent_tree(sbi, et, nr_shrink); + write_unlock(&et->lock); + } + + f2fs_bug_on(sbi, atomic_read(&et->node_cnt)); + + return node_cnt; +} + static void __update_extent_tree_range(struct inode *inode, struct extent_info *tei, enum extent_type type) { = @@ -760,9 +785,6 @@ static void __update_extent_tree_range(struct inode *in= ode, } } - if (is_inode_flag_set(inode, FI_NO_EXTENT)) - __free_extent_tree(sbi, et); - if (et->largest_updated) { et->largest_updated =3D false; updated =3D true; @@ -780,6 +802,9 @@ static void __update_extent_tree_range(struct inode *in= ode, out_read_extent_cache: write_unlock(&et->lock); + if (is_inode_flag_set(inode, FI_NO_EXTENT)) + __destroy_extent_node(inode, EX_READ); + if (updated) f2fs_mark_inode_dirty_sync(inode, true); } @@ -942,10 +967= ,14 @@ static unsigned int __shrink_extent_tree(struct f2fs_sb_info *sbi, i= nt nr_shrink list_for_each_entry_safe(et, next, &eti->zombie_list, list) { if (atomic_read(&et->node_cnt)) { write_lock(&et->lock); - node_cnt +=3D __free_extent_tree(sbi, et); + node_cnt +=3D __free_extent_tree(sbi, et, + nr_shrink - node_cnt -=20 + tree_cnt); write_unlock(&et->lock); } - f2fs_bug_on(sbi, atomic_read(&et->node_cnt)); + + if (atomic_read(&et->node_cnt)) + goto unlock_out; + list_del_init(&et->list); radix_tree_delete(&eti->extent_tree_root, et->ino); kmem_cache_free(extent_tree_slab, et); @@ -1084,23 +1113,6 = @@ unsigned int f2fs_shrink_age_extent_tree(struct f2fs_sb_info *sbi, int n= r_shrink return __shrink_extent_tree(sbi, nr_shrink, EX_BLOCK_AGE); } -static unsigned int __destroy_extent_node(struct inode *inode, - enum extent_type type) -{ - struct f2fs_sb_info *sbi =3D F2FS_I_SB(inode); - struct extent_tree *et =3D F2FS_I(inode)->extent_tree[type]; - unsigned int node_cnt =3D 0; - - if (!et || !atomic_read(&et->node_cnt)) - return 0; - - write_lock(&et->lock); - node_cnt =3D __free_extent_tree(sbi, et); - write_unlock(&et->lock); - - return node_cnt; -} - void f2fs_destroy_extent_node(struct inode *inode) { __destroy_extent_node(inode, EX_READ); @@ -1109,7 +1121,6 @@ void f= 2fs_destroy_extent_node(struct inode *inode) static void __drop_extent_tree(struct inode *inode, enum extent_type type)= { - struct f2fs_sb_info *sbi =3D F2FS_I_SB(inode); struct extent_tree *et =3D F2FS_I(inode)->extent_tree[type]; bool updated =3D false; @@ -1117,7 +1128,6 @@ static void __drop_extent_tree(struct inode *inode, e= num extent_type type) return; write_lock(&et->lock); - __free_extent_tree(sbi, et); if (type =3D=3D EX_READ) { set_inode_flag(inode, FI_NO_EXTENT); if (et->largest.len) { @@ -1126,6 +1136,9 @@ static void __drop_extent_tree(struct inode *inode, e= num extent_type type) } } write_unlock(&et->lock); + + __destroy_extent_node(inode, type); + if (updated) f2fs_mark_inode_dirty_sync(inode, true); } -- 2.40.1