From nobody Thu Dec 18 04:51:18 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 93E66C77B73 for ; Mon, 24 Apr 2023 03:40:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230077AbjDXDkF (ORCPT ); Sun, 23 Apr 2023 23:40:05 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35368 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229517AbjDXDjq (ORCPT ); Sun, 23 Apr 2023 23:39:46 -0400 Received: from szxga01-in.huawei.com (szxga01-in.huawei.com [45.249.212.187]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 53F542132; Sun, 23 Apr 2023 20:39:44 -0700 (PDT) Received: from dggpeml500021.china.huawei.com (unknown [172.30.72.53]) by szxga01-in.huawei.com (SkyGuard) with ESMTP id 4Q4W73071nzsRr1; Mon, 24 Apr 2023 11:38:07 +0800 (CST) Received: from huawei.com (10.175.127.227) by dggpeml500021.china.huawei.com (7.185.36.21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.23; Mon, 24 Apr 2023 11:39:42 +0800 From: Baokun Li To: CC: , , , , , , , , Subject: [PATCH v4 05/12] ext4: use pre-allocated es in __es_remove_extent() Date: Mon, 24 Apr 2023 11:38:39 +0800 Message-ID: <20230424033846.4732-6-libaokun1@huawei.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20230424033846.4732-1-libaokun1@huawei.com> References: <20230424033846.4732-1-libaokun1@huawei.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Originating-IP: [10.175.127.227] X-ClientProxiedBy: dggems701-chm.china.huawei.com (10.3.19.178) To dggpeml500021.china.huawei.com (7.185.36.21) X-CFilter-Loop: Reflected Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" When splitting extent, if the second extent can not be dropped, we return -ENOMEM and use GFP_NOFAIL to preallocate an extent_status outside of i_es_lock and pass it to __es_remove_extent() to be used as the second extent. This ensures that __es_remove_extent() is executed successfully, thus ensuring consistency in the extent status tree. If the second extent is not undroppable, we simply drop it and return 0. Then retry is no longer necessary, remove it. Now, __es_remove_extent() will always remove what it should, maybe more. Suggested-by: Jan Kara Signed-off-by: Baokun Li Reviewed-by: Jan Kara --- fs/ext4/extents_status.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c index a6a62a744e83..7219116e0d68 100644 --- a/fs/ext4/extents_status.c +++ b/fs/ext4/extents_status.c @@ -147,7 +147,8 @@ static struct kmem_cache *ext4_pending_cachep; static int __es_insert_extent(struct inode *inode, struct extent_status *n= ewes, struct extent_status *prealloc); static int __es_remove_extent(struct inode *inode, ext4_lblk_t lblk, - ext4_lblk_t end, int *reserved); + ext4_lblk_t end, int *reserved, + struct extent_status *prealloc); static int es_reclaim_extents(struct ext4_inode_info *ei, int *nr_to_scan); static int __es_shrink(struct ext4_sb_info *sbi, int nr_to_scan, struct ext4_inode_info *locked_ei); @@ -869,7 +870,7 @@ int ext4_es_insert_extent(struct inode *inode, ext4_lbl= k_t lblk, ext4_es_insert_extent_check(inode, &newes); =20 write_lock(&EXT4_I(inode)->i_es_lock); - err =3D __es_remove_extent(inode, lblk, end, NULL); + err =3D __es_remove_extent(inode, lblk, end, NULL, NULL); if (err !=3D 0) goto error; retry: @@ -1315,6 +1316,7 @@ static unsigned int get_rsvd(struct inode *inode, ext= 4_lblk_t end, * @lblk - first block in range * @end - last block in range * @reserved - number of cluster reservations released + * @prealloc - pre-allocated es to avoid memory allocation failures * * If @reserved is not NULL and delayed allocation is enabled, counts * block/cluster reservations freed by removing range and if bigalloc @@ -1322,7 +1324,8 @@ static unsigned int get_rsvd(struct inode *inode, ext= 4_lblk_t end, * error code on failure. */ static int __es_remove_extent(struct inode *inode, ext4_lblk_t lblk, - ext4_lblk_t end, int *reserved) + ext4_lblk_t end, int *reserved, + struct extent_status *prealloc) { struct ext4_es_tree *tree =3D &EXT4_I(inode)->i_es_tree; struct rb_node *node; @@ -1330,14 +1333,12 @@ static int __es_remove_extent(struct inode *inode, = ext4_lblk_t lblk, struct extent_status orig_es; ext4_lblk_t len1, len2; ext4_fsblk_t block; - int err; + int err =3D 0; bool count_reserved =3D true; struct rsvd_count rc; =20 if (reserved =3D=3D NULL || !test_opt(inode->i_sb, DELALLOC)) count_reserved =3D false; -retry: - err =3D 0; =20 es =3D __es_tree_search(&tree->root, lblk); if (!es) @@ -1371,14 +1372,13 @@ static int __es_remove_extent(struct inode *inode, = ext4_lblk_t lblk, orig_es.es_len - len2; ext4_es_store_pblock_status(&newes, block, ext4_es_status(&orig_es)); - err =3D __es_insert_extent(inode, &newes, NULL); + err =3D __es_insert_extent(inode, &newes, prealloc); if (err) { + if (!ext4_es_must_keep(&newes)) + return 0; + es->es_lblk =3D orig_es.es_lblk; es->es_len =3D orig_es.es_len; - if ((err =3D=3D -ENOMEM) && - __es_shrink(EXT4_SB(inode->i_sb), - 128, EXT4_I(inode))) - goto retry; goto out; } } else { @@ -1478,7 +1478,7 @@ int ext4_es_remove_extent(struct inode *inode, ext4_l= blk_t lblk, * is reclaimed. */ write_lock(&EXT4_I(inode)->i_es_lock); - err =3D __es_remove_extent(inode, lblk, end, &reserved); + err =3D __es_remove_extent(inode, lblk, end, &reserved, NULL); write_unlock(&EXT4_I(inode)->i_es_lock); ext4_es_print_tree(inode); ext4_da_release_space(inode, reserved); @@ -2021,7 +2021,7 @@ int ext4_es_insert_delayed_block(struct inode *inode,= ext4_lblk_t lblk, =20 write_lock(&EXT4_I(inode)->i_es_lock); =20 - err =3D __es_remove_extent(inode, lblk, lblk, NULL); + err =3D __es_remove_extent(inode, lblk, lblk, NULL, NULL); if (err !=3D 0) goto error; retry: --=20 2.31.1