From patchwork Sat Jan 27 01:58:02 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zhang Yi X-Patchwork-Id: 13533894 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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 86D04C47DA9 for ; Sat, 27 Jan 2024 02:02:54 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 5A84A6B0083; Fri, 26 Jan 2024 21:02:50 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 41FD56B0095; Fri, 26 Jan 2024 21:02:50 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id F257E6B0083; Fri, 26 Jan 2024 21:02:49 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0016.hostedemail.com [216.40.44.16]) by kanga.kvack.org (Postfix) with ESMTP id D1BC96B0087 for ; Fri, 26 Jan 2024 21:02:49 -0500 (EST) Received: from smtpin30.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay04.hostedemail.com (Postfix) with ESMTP id A89211A0FFA for ; Sat, 27 Jan 2024 02:02:49 +0000 (UTC) X-FDA: 81723442458.30.8B0055C Received: from dggsgout11.his.huawei.com (unknown [45.249.212.51]) by imf12.hostedemail.com (Postfix) with ESMTP id 3440140010 for ; Sat, 27 Jan 2024 02:02:45 +0000 (UTC) Authentication-Results: imf12.hostedemail.com; dkim=none; dmarc=none; spf=pass (imf12.hostedemail.com: domain of yi.zhang@huaweicloud.com designates 45.249.212.51 as permitted sender) smtp.mailfrom=yi.zhang@huaweicloud.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1706320967; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=wSf1NcIMWRvjDJDKI/OHBqUKBoVpTLWWYixqR/BPt/g=; b=fWhHfNgngFsRYwv6ocztuYtxIU4OvMiVF1MdX2YXkG5MLrCjbNQadg1ZsaKnfqTmvzHEri kFZrGn0c3GOxWJVqMN2/nIw4zwkQ4EVc30gXZ6E9N+JT9sP9ygnrnMHJyKMuBrDNQg67wR aLiRCFrwy5omhI5M1X3urDO/wfr1IcI= ARC-Authentication-Results: i=1; imf12.hostedemail.com; dkim=none; dmarc=none; spf=pass (imf12.hostedemail.com: domain of yi.zhang@huaweicloud.com designates 45.249.212.51 as permitted sender) smtp.mailfrom=yi.zhang@huaweicloud.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1706320967; a=rsa-sha256; cv=none; b=BmIj1KB7PgpdUJmDmK0oqrhcD0wV255OYOy3hbORMG58lhiQKpQUjulK8j3zEwCZJ1bluV CFHAYZXlTEF4YNo7xPegVaS36mjWO8dEJxFndHLdZXoY0ixTVv9zWgsL4TzsDuQQY+pVkZ LoIC/4Z4VPstPbln1jOInKU8lFwoBa0= Received: from mail.maildlp.com (unknown [172.19.93.142]) by dggsgout11.his.huawei.com (SkyGuard) with ESMTP id 4TMHrV6ldjz4f3lg0 for ; Sat, 27 Jan 2024 10:02:34 +0800 (CST) Received: from mail02.huawei.com (unknown [10.116.40.112]) by mail.maildlp.com (Postfix) with ESMTP id 4F1FD1A016E for ; Sat, 27 Jan 2024 10:02:41 +0800 (CST) Received: from huaweicloud.com (unknown [10.175.104.67]) by APP1 (Coremail) with SMTP id cCh0CgAX5g40ZLRlGJtmCA--.7377S7; Sat, 27 Jan 2024 10:02:41 +0800 (CST) From: Zhang Yi To: linux-ext4@vger.kernel.org Cc: linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, linux-kernel@vger.kernel.org, tytso@mit.edu, adilger.kernel@dilger.ca, jack@suse.cz, ritesh.list@gmail.com, hch@infradead.org, djwong@kernel.org, willy@infradead.org, zokeefe@google.com, yi.zhang@huawei.com, yi.zhang@huaweicloud.com, chengzhihao1@huawei.com, yukuai3@huawei.com, wangkefeng.wang@huawei.com Subject: [PATCH v3 03/26] ext4: correct the hole length returned by ext4_map_blocks() Date: Sat, 27 Jan 2024 09:58:02 +0800 Message-Id: <20240127015825.1608160-4-yi.zhang@huaweicloud.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20240127015825.1608160-1-yi.zhang@huaweicloud.com> References: <20240127015825.1608160-1-yi.zhang@huaweicloud.com> MIME-Version: 1.0 X-CM-TRANSID: cCh0CgAX5g40ZLRlGJtmCA--.7377S7 X-Coremail-Antispam: 1UD129KBjvJXoW3Gr1UCF4DJw13Xw47uFyrCrg_yoWxJr13pF Wfury5Gws8W34q93yxAF4UZr1rC3W8CrW7JrZ3tr1SyF15Jr48WF18KF12vFZ3tFWrJF1Y vr4jya4UCa1akaDanT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUPj14x267AKxVWrJVCq3wAFc2x0x2IEx4CE42xK8VAvwI8IcIk0 rVWrJVCq3wAFIxvE14AKwVWUJVWUGwA2048vs2IY020E87I2jVAFwI0_JrWl82xGYIkIc2 x26xkF7I0E14v26ryj6s0DM28lY4IEw2IIxxk0rwA2F7IY1VAKz4vEj48ve4kI8wA2z4x0 Y4vE2Ix0cI8IcVAFwI0_Ar0_tr1l84ACjcxK6xIIjxv20xvEc7CjxVAFwI0_Gr1j6F4UJw A2z4x0Y4vEx4A2jsIE14v26rxl6s0DM28EF7xvwVC2z280aVCY1x0267AKxVW0oVCq3wAS 0I0E0xvYzxvE52x082IY62kv0487Mc02F40EFcxC0VAKzVAqx4xG6I80ewAv7VC0I7IYx2 IY67AKxVWUXVWUAwAv7VC2z280aVAFwI0_Jr0_Gr1lOx8S6xCaFVCjc4AY6r1j6r4UM4x0 Y48IcxkI7VAKI48JM4x0x7Aq67IIx4CEVc8vx2IErcIFxwACI402YVCY1x02628vn2kIc2 xKxwCF04k20xvY0x0EwIxGrwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s026c02F40E14v2 6r1j6r18MI8I3I0E7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_GFv_WrylIxkGc2 Ij64vIr41lIxAIcVC0I7IYx2IY67AKxVWUJVWUCwCI42IY6xIIjxv20xvEc7CjxVAFwI0_ Cr0_Gr1UMIIF0xvE42xK8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67AKxVWUJVW8Jw CI42IY6I8E87Iv6xkF7I0E14v26r4j6r4UJbIYCTnIWIevJa73UjIFyTuYvjfUoL0eDUUU U X-CM-SenderInfo: d1lo6xhdqjqx5xdzvxpfor3voofrz/ X-Rspam-User: X-Stat-Signature: dintgkrno47x3sbx6gwt3oiy3m1x84uk X-Rspamd-Server: rspam07 X-Rspamd-Queue-Id: 3440140010 X-HE-Tag: 1706320965-590566 X-HE-Meta: U2FsdGVkX1//QWhEumNZ8Xa7h92vo8ZeQkOSOUW6U0UgvuozC3FSmW7S2VUN2BYOkEJsGaNMYuD286UtPvpLfljDWFx3cVtKEn24mlCOLZpT+cnIqcR0kgrH1sjcYZgJ4jihiinv1SbKcppfrFxPSFOi2Tc+3MhsezogaCZovZvccPR1aKFgczA4bGeERo98Wis81vqlSo/eJn4VsKo/Wtf0AgC/DvMG0Ymr/7Mc8+ydyNFkTS9g+FLYv6i4g7mdPTJcO57skL0CqWDoUMrqfv2Al/71IBkkJ/kXx6GDyJ8pyaqfmdH/XKlsM+LsaWT1q3WaVUtKzEacdPiNidStmIyvSmPjNnBfM+UwvHDd1kFZWJRIgcGRAL6DQImSfb8XbHS0GZSQoILQLpvInyCVmbNJgSHHjRamsxcJdDPPCEDxP6Wzz4Uw9H5U7JmFKKaAOfquotoQjDeOgC4yH51INkYz/wwK5zgiCcymwLjND/pGZjNinxPc3+ARlqYIuEoxFxAc0Pf69vh6V3rBtVf+qApOcu2Q0avUkuP8jzlXQcN+NTu/zPOlTVVcC0bqrPtg5fnPikCGskiwG191jXw2G8rqhj3yW+7jacJvMnEsAIe9SoUxS9FEqZ2qIN2ImkYo6CBTKS+jRCEwc+3O+aBjyx5Sid7TF7sbAvoVjCoeh+oWniyswQm0db533HrGPJe0hjgPafCphMAA2f9qLBIGWhNwPHLLv2LwIJg6GRoLpvGyEx2oD0jVJ+sPJtQq/xmxKVltHx8m6RPuksncOzmBj6hysse3vRQoVAx2YWla7cv6lomefJU72plF1NBN8M9LkGkFUMZyLO35ATBp2HeYQtSza5CtOHFQWNlkI1A6KfQ7NB0FgtZAcscGP7e9fsZELBCxLbWUoAPsPH2dm3uFTxiHmTFnWLx745oBbDCDy/rwwH4uckaActVKseu5VuSlLfZ2lV1OFvz57acpi2D JxJYN1dw t+zY90h6sqDukfgmdQ4eoNkqj8XpNqwE8YJHVfPYCjXrQYe5BIix1LDSOzs0ZEoyltcKUTtmSglVRm1PwS2NuCYD24WPx27MRtnD4cGyvvl5I8iG4GcNdxfl33H7l5DXVs1hTcPYy4FHSu+5ED65a6pYsJq6T/0WvQKbXyEAgue2+WWnEfTh0bTb9RhTscSEl12EU853N2gbt1KP9oVPvhYk0dh7BIKv3I8VrCg/yOSxD5vqE9ve3bskxvq60ORz+yjEIq5V49Ta4/0iFd20+wIK9nIIpfgf5fhwKEzNB0G5ItGY= X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: From: Zhang Yi In ext4_map_blocks(), if we can't find a range of mapping in the extents cache, we are calling ext4_ext_map_blocks() to search the real path and ext4_ext_determine_hole() to determine the hole range. But if the querying range was partially or completely overlaped by a delalloc extent, we can't find it in the real extent path, so the returned hole length could be incorrect. Fortunately, ext4_ext_put_gap_in_cache() have already handle delalloc extent, but it searches start from the expanded hole_start, doesn't start from the querying range, so the delalloc extent found could not be the one that overlaped the querying range, plus, it also didn't adjust the hole length. Let's just remove ext4_ext_put_gap_in_cache(), handle delalloc and insert adjusted hole extent in ext4_ext_determine_hole(). Signed-off-by: Zhang Yi Suggested-by: Jan Kara Reviewed-by: Jan Kara Signed-off-by: Luis Henriques (SUSE) --- fs/ext4/extents.c | 111 +++++++++++++++++++++++++++++----------------- 1 file changed, 70 insertions(+), 41 deletions(-) diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index d5efe076d3d3..e0b7e48c4c67 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -2229,7 +2229,7 @@ static int ext4_fill_es_cache_info(struct inode *inode, /* - * ext4_ext_determine_hole - determine hole around given block + * ext4_ext_find_hole - find hole around given block according to the given path * @inode: inode we lookup in * @path: path in extent tree to @lblk * @lblk: pointer to logical block around which we want to determine hole @@ -2241,9 +2241,9 @@ static int ext4_fill_es_cache_info(struct inode *inode, * The function returns the length of a hole starting at @lblk. We update @lblk * to the beginning of the hole if we managed to find it. */ -static ext4_lblk_t ext4_ext_determine_hole(struct inode *inode, - struct ext4_ext_path *path, - ext4_lblk_t *lblk) +static ext4_lblk_t ext4_ext_find_hole(struct inode *inode, + struct ext4_ext_path *path, + ext4_lblk_t *lblk) { int depth = ext_depth(inode); struct ext4_extent *ex; @@ -2270,30 +2270,6 @@ static ext4_lblk_t ext4_ext_determine_hole(struct inode *inode, return len; } -/* - * ext4_ext_put_gap_in_cache: - * calculate boundaries of the gap that the requested block fits into - * and cache this gap - */ -static void -ext4_ext_put_gap_in_cache(struct inode *inode, ext4_lblk_t hole_start, - ext4_lblk_t hole_len) -{ - struct extent_status es; - - ext4_es_find_extent_range(inode, &ext4_es_is_delayed, hole_start, - hole_start + hole_len - 1, &es); - if (es.es_len) { - /* There's delayed extent containing lblock? */ - if (es.es_lblk <= hole_start) - return; - hole_len = min(es.es_lblk - hole_start, hole_len); - } - ext_debug(inode, " -> %u:%u\n", hole_start, hole_len); - ext4_es_insert_extent(inode, hole_start, hole_len, ~0, - EXTENT_STATUS_HOLE); -} - /* * ext4_ext_rm_idx: * removes index from the index block. @@ -4062,6 +4038,69 @@ static int get_implied_cluster_alloc(struct super_block *sb, return 0; } +/* + * Determine hole length around the given logical block, first try to + * locate and expand the hole from the given @path, and then adjust it + * if it's partially or completely converted to delayed extents, insert + * it into the extent cache tree if it's indeed a hole, finally return + * the length of the determined extent. + */ +static ext4_lblk_t ext4_ext_determine_insert_hole(struct inode *inode, + struct ext4_ext_path *path, + ext4_lblk_t lblk) +{ + ext4_lblk_t hole_start, len; + struct extent_status es; + + hole_start = lblk; + len = ext4_ext_find_hole(inode, path, &hole_start); +again: + ext4_es_find_extent_range(inode, &ext4_es_is_delayed, hole_start, + hole_start + len - 1, &es); + if (!es.es_len) + goto insert_hole; + + /* + * There's a delalloc extent in the hole, handle it if the delalloc + * extent is in front of, behind and straddle the queried range. + */ + if (lblk >= es.es_lblk + es.es_len) { + /* + * The delalloc extent is in front of the queried range, + * find again from the queried start block. + */ + len -= lblk - hole_start; + hole_start = lblk; + goto again; + } else if (in_range(lblk, es.es_lblk, es.es_len)) { + /* + * The delalloc extent containing lblk, it must have been + * added after ext4_map_blocks() checked the extent status + * tree, adjust the length to the delalloc extent's after + * lblk. + */ + len = es.es_lblk + es.es_len - lblk; + return len; + } else { + /* + * The delalloc extent is partially or completely behind + * the queried range, update hole length until the + * beginning of the delalloc extent. + */ + len = min(es.es_lblk - hole_start, len); + } + +insert_hole: + /* Put just found gap into cache to speed up subsequent requests */ + ext_debug(inode, " -> %u:%u\n", hole_start, len); + ext4_es_insert_extent(inode, hole_start, len, ~0, EXTENT_STATUS_HOLE); + + /* Update hole_len to reflect hole size after lblk */ + if (hole_start != lblk) + len -= lblk - hole_start; + + return len; +} /* * Block allocation/map/preallocation routine for extents based files @@ -4179,22 +4218,12 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode, * we couldn't try to create block if create flag is zero */ if ((flags & EXT4_GET_BLOCKS_CREATE) == 0) { - ext4_lblk_t hole_start, hole_len; + ext4_lblk_t len; - hole_start = map->m_lblk; - hole_len = ext4_ext_determine_hole(inode, path, &hole_start); - /* - * put just found gap into cache to speed up - * subsequent requests - */ - ext4_ext_put_gap_in_cache(inode, hole_start, hole_len); + len = ext4_ext_determine_insert_hole(inode, path, map->m_lblk); - /* Update hole_len to reflect hole size after map->m_lblk */ - if (hole_start != map->m_lblk) - hole_len -= map->m_lblk - hole_start; map->m_pblk = 0; - map->m_len = min_t(unsigned int, map->m_len, hole_len); - + map->m_len = min_t(unsigned int, map->m_len, len); goto out; }