Received: by 2002:a05:7412:b995:b0:f9:9502:5bb8 with SMTP id it21csp1337927rdb; Sat, 23 Dec 2023 03:04:52 -0800 (PST) X-Google-Smtp-Source: AGHT+IGXqd3jt/NNsimTS51CkjcsqddPt1ndsiL9KGujjLg6SYUm8BVmPPXxA4jXuHn+v3ZaTVKR X-Received: by 2002:ac8:4e42:0:b0:427:7f35:1c2f with SMTP id e2-20020ac84e42000000b004277f351c2fmr3512474qtw.18.1703329492286; Sat, 23 Dec 2023 03:04:52 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1703329492; cv=none; d=google.com; s=arc-20160816; b=Syh7o+vW1MpxDEvGndlLB5Cnu/lKuY68FYxFnln75MezXmsXs+pqQu1DqSrLZV/fa3 TjdAka+XE5XtWvSGBFk0+5YBMrc24m+BFLfxcpYYfvumCxATMRa2VGIKhJbiDsSrER4+ LnlHUVjwXEPDCXwD6yMYncr/GqhgcLskRvB0L+MZB9BYEWmioqb8seeQlVKJG/tY7Qk6 Bnn871X+XKzEniNyV8ajrosCqGt+Tg9SN/Xm10H14IHQsxKlWFupwvTmv/sdMQbf1Wxb F+DYGSnzLKVJUaxOq0JiSExUg/I+3m9igQOqxktChoBSXiXchGohQie0TT/7xKEWgQNK P3vw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from; bh=Ln80J7upTNFWgdRzColX1AUxnwEQjhN8Ynh/PB6dc4Y=; fh=Uq/HK0tePPZ4uFSrjmAoQ+8fm8HBRKIYZPcFTEYnhm4=; b=no1oVIOKo/VmkQ6O9uy4LFGZ0C0YdqYA4zd3cVJieXem6qN82vxG8oGpRmNPZ88f3M QfkbX9no9hBMPbrHrDbqGjTNhTxew2bbBZ6fNrdK/uZ2n/cJvkpFkUqAADougEppoEiQ bNL7u74ZRyw8/iXvMYcgagU6yCmzdbwN9VYGqjNewL/dWAi7hKLjw1rgvYJNscw0d67o dhbo91e5mY7y1zCran9mjy92WBrYvIwlkCCUBor4qEaKRHrsKjDPPtMcjypMgwDS5CkL Phr/mBqqi1Ep9y5BCMa6NNFHKvoDOXKMfjumeScpGb3ossRuGhzFXZViYql4ON1FSoX4 BhOQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-ext4+bounces-551-linux.lists.archive=gmail.com@vger.kernel.org designates 147.75.199.223 as permitted sender) smtp.mailfrom="linux-ext4+bounces-551-linux.lists.archive=gmail.com@vger.kernel.org" Return-Path: Received: from ny.mirrors.kernel.org (ny.mirrors.kernel.org. [147.75.199.223]) by mx.google.com with ESMTPS id a11-20020a05622a064b00b004237c28cd47si6367280qtb.375.2023.12.23.03.04.52 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 23 Dec 2023 03:04:52 -0800 (PST) Received-SPF: pass (google.com: domain of linux-ext4+bounces-551-linux.lists.archive=gmail.com@vger.kernel.org designates 147.75.199.223 as permitted sender) client-ip=147.75.199.223; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-ext4+bounces-551-linux.lists.archive=gmail.com@vger.kernel.org designates 147.75.199.223 as permitted sender) smtp.mailfrom="linux-ext4+bounces-551-linux.lists.archive=gmail.com@vger.kernel.org" Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ny.mirrors.kernel.org (Postfix) with ESMTPS id 007A71C212F9 for ; Sat, 23 Dec 2023 11:04:52 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id AD868CA6E; Sat, 23 Dec 2023 11:04:45 +0000 (UTC) X-Original-To: linux-ext4@vger.kernel.org Received: from dggsgout12.his.huawei.com (unknown [45.249.212.56]) (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 3E11DBA58 for ; Sat, 23 Dec 2023 11:04:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.19.163.235]) by dggsgout12.his.huawei.com (SkyGuard) with ESMTP id 4Sy1X308Tnz4f3jHV for ; Sat, 23 Dec 2023 19:04:35 +0800 (CST) Received: from mail02.huawei.com (unknown [10.116.40.128]) by mail.maildlp.com (Postfix) with ESMTP id DFB911A08FA for ; Sat, 23 Dec 2023 19:04:37 +0800 (CST) Received: from huaweicloud.com (unknown [10.175.104.67]) by APP4 (Coremail) with SMTP id gCh0CgDX5UW6voZlWeceEg--.27538S7; Sat, 23 Dec 2023 19:04:37 +0800 (CST) From: Zhang Yi To: linux-ext4@vger.kernel.org Cc: tytso@mit.edu, adilger.kernel@dilger.ca, jack@suse.cz, yi.zhang@huawei.com, yi.zhang@huaweicloud.com, chengzhihao1@huawei.com, yukuai3@huawei.com Subject: [RFC PATCH v2 3/6] ext4: correct the hole length returned by ext4_map_blocks() Date: Sat, 23 Dec 2023 19:02:20 +0800 Message-Id: <20231223110223.3650717-4-yi.zhang@huaweicloud.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20231223110223.3650717-1-yi.zhang@huaweicloud.com> References: <20231223110223.3650717-1-yi.zhang@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-ext4@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-CM-TRANSID:gCh0CgDX5UW6voZlWeceEg--.27538S7 X-Coremail-Antispam: 1UD129KBjvJXoW3Gr18ZF13Zr15tr13XFy8uFg_yoW7tr43pF Za9ry5Gws8W3yq93yxJF48Zr1rC3W8CrW7JrZ3tr1SyF15Jr48WF18GF12vFZ3tFW8GF1Y vr4jya4jka1akFJanT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUU9v14x267AKxVWrJVCq3wAFc2x0x2IEx4CE42xK8VAvwI8IcIk0 rVWrJVCq3wAFIxvE14AKwVWUJVWUGwA2048vs2IY020E87I2jVAFwI0_JrWl82xGYIkIc2 x26xkF7I0E14v26ryj6s0DM28lY4IEw2IIxxk0rwA2F7IY1VAKz4vEj48ve4kI8wA2z4x0 Y4vE2Ix0cI8IcVAFwI0_Ar0_tr1l84ACjcxK6xIIjxv20xvEc7CjxVAFwI0_Cr0_Gr1UM2 8EF7xvwVC2z280aVAFwI0_GcCE3s1l84ACjcxK6I8E87Iv6xkF7I0E14v26rxl6s0DM2AI xVAIcxkEcVAq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F40Ex7xfMcIj6xIIjxv20x vE14v26r1Y6r17McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC6x0Yz7v_Jr0_Gr1lF7xv r2IYc2Ij64vIr41lF7I21c0EjII2zVCS5cI20VAGYxC7MxAIw28IcxkI7VAKI48JMxC20s 026xCaFVCjc4AY6r1j6r4UMI8I3I0E5I8CrVAFwI0_Jr0_Jr4lx2IqxVCjr7xvwVAFwI0_ JrI_JrWlx4CE17CEb7AF67AKxVWUtVW8ZwCIc40Y0x0EwIxGrwCI42IY6xIIjxv20xvE14 v26r1j6r1xMIIF0xvE2Ix0cI8IcVCY1x0267AKxVW8JVWxJwCI42IY6xAIw20EY4v20xva j40_Jr0_JF4lIxAIcVC2z280aVAFwI0_Jr0_Gr1lIxAIcVC2z280aVCY1x0267AKxVW8JV W8JrUvcSsGvfC2KfnxnUUI43ZEXa7VUbMq2tUUUUU== X-CM-SenderInfo: d1lo6xhdqjqx5xdzvxpfor3voofrz/ 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 --- fs/ext4/extents.c | 109 +++++++++++++++++++++++++++------------------- 1 file changed, 65 insertions(+), 44 deletions(-) diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index d5efe076d3d3..0892d0568013 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,66 @@ 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. + */ +static void ext4_ext_determine_hole(struct inode *inode, + struct ext4_ext_path *path, + struct ext4_map_blocks *map) +{ + ext4_lblk_t hole_start, len; + struct extent_status es; + + hole_start = map->m_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; + + /* + * Found a delayed range in the hole, handle it if the delayed + * range is before, behind and straddle the queried range. + */ + if (map->m_lblk >= es.es_lblk + es.es_len) { + /* + * Before the queried range, find again from the queried + * start block. + */ + len -= map->m_lblk - hole_start; + hole_start = map->m_lblk; + goto again; + } else if (in_range(map->m_lblk, es.es_lblk, es.es_len)) { + /* + * Straddle the beginning of the queried range, it's no + * longer a hole, adjust the length to the delayed extent's + * after map->m_lblk. + */ + len = es.es_lblk + es.es_len - map->m_lblk; + goto out; + } else { + /* + * Partially or completely behind the queried range, update + * hole length until the beginning of the delayed 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 map->m_lblk */ + if (hole_start != map->m_lblk) + len -= map->m_lblk - hole_start; +out: + map->m_pblk = 0; + map->m_len = min_t(unsigned int, map->m_len, len); +} /* * Block allocation/map/preallocation routine for extents based files @@ -4179,22 +4215,7 @@ 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; - - 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); - - /* 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); - + ext4_ext_determine_hole(inode, path, map); goto out; } -- 2.39.2