Received: by 2002:a05:7412:b995:b0:f9:9502:5bb8 with SMTP id it21csp6516159rdb; Tue, 2 Jan 2024 04:52:07 -0800 (PST) X-Google-Smtp-Source: AGHT+IEscxuZ1DNSzcvPIIfjPvDkJOJo/C86VehL5TUBtdeekBwE3hX80/gNnVxuD/EkxIslOI4s X-Received: by 2002:a17:907:9058:b0:a1f:a6bf:4e60 with SMTP id az24-20020a170907905800b00a1fa6bf4e60mr6415729ejc.102.1704199927001; Tue, 02 Jan 2024 04:52:07 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1704199926; cv=none; d=google.com; s=arc-20160816; b=pLHBJB6FIK1Zv8kwIk4B9iIDSwbJYg9uDVURU1up+6y2UG4IAU7SOLlZ+XqlgIvke0 5FxsI0qFRY4aRKTewz3K6hmfqDcx4mpBSSEmJcgbR2d3zB2essB98wiUkaYGV4c2GZGp UCgkefCXiBr6mCkfxcfQxu6K+UxSllj9GI/BbuSTOWLXZfJsUM7zjn6vpm3PjixqwLsS sCn2o75iyjUO+q30f/Qkw+ugIgpfFW7OG61/Lay0ghurhvaQF1605uVxHVSTn4+zdyF5 NRo/X2Ht53Ks6Jc5w2OJteVFO12c1XJs45Rn6efBmZHuwnYDP70Kr/svdCmCDxTcZU58 daKw== 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=yWWoL3IRufgA/+2kSpO6uyfw9eN3ZOO7zvul0qbDPkA=; b=KYBfQddqdhn4QXM1g7QRkX1Y+OLqdX731u64Fx2qKxi5JcWe/bL8wHJ/dtllJs37vn O8ma8Oq3XNMPwuWDROEiFrU8QBFowMVf5CKW8+vPKOl1wi0rqJn99hKlKqvQPXY8P662 UY0jL/ZP7k1qOrP/IxOs3N99iYvO5S1HTw9K/PD0/S98IOgYwg1jgOc4ej3K2F0YbtAM Rc5vdevrBLS2XUw+2EZtSUkVnWY+dIefO+BZaOMbn13JM0Xmq+E7N8tupGGKuHkN+Nlx M2A/Of50aOwRRVqKX2H26+NgE7frBHVOmJL09ltU56Qz4sqRYRWPP4KtFKlZXKuCTQZf aCtg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-ext4+bounces-597-linux.lists.archive=gmail.com@vger.kernel.org designates 147.75.80.249 as permitted sender) smtp.mailfrom="linux-ext4+bounces-597-linux.lists.archive=gmail.com@vger.kernel.org" Return-Path: Received: from am.mirrors.kernel.org (am.mirrors.kernel.org. [147.75.80.249]) by mx.google.com with ESMTPS id vp13-20020a17090712cd00b00a26be3c1a23si8634413ejb.870.2024.01.02.04.52.06 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 02 Jan 2024 04:52:06 -0800 (PST) Received-SPF: pass (google.com: domain of linux-ext4+bounces-597-linux.lists.archive=gmail.com@vger.kernel.org designates 147.75.80.249 as permitted sender) client-ip=147.75.80.249; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-ext4+bounces-597-linux.lists.archive=gmail.com@vger.kernel.org designates 147.75.80.249 as permitted sender) smtp.mailfrom="linux-ext4+bounces-597-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 am.mirrors.kernel.org (Postfix) with ESMTPS id 190191F232D7 for ; Tue, 2 Jan 2024 12:43:00 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id A9D4B10961; Tue, 2 Jan 2024 12:42:12 +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 46F72F517; Tue, 2 Jan 2024 12:42:09 +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 4T4CCv5YgFz4f3jYQ; Tue, 2 Jan 2024 20:42:03 +0800 (CST) Received: from mail02.huawei.com (unknown [10.116.40.128]) by mail.maildlp.com (Postfix) with ESMTP id 07B331A6C6D; Tue, 2 Jan 2024 20:42:07 +0800 (CST) Received: from huaweicloud.com (unknown [10.175.104.67]) by APP4 (Coremail) with SMTP id gCh0CgBnwUGUBJRl+EvDFQ--.31823S7; Tue, 02 Jan 2024 20:42:06 +0800 (CST) From: Zhang Yi To: linux-ext4@vger.kernel.org Cc: linux-fsdevel@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, yi.zhang@huawei.com, yi.zhang@huaweicloud.com, chengzhihao1@huawei.com, yukuai3@huawei.com, wangkefeng.wang@huawei.com Subject: [RFC PATCH v2 03/25] ext4: correct the hole length returned by ext4_map_blocks() Date: Tue, 2 Jan 2024 20:38:56 +0800 Message-Id: <20240102123918.799062-4-yi.zhang@huaweicloud.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20240102123918.799062-1-yi.zhang@huaweicloud.com> References: <20240102123918.799062-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:gCh0CgBnwUGUBJRl+EvDFQ--.31823S7 X-Coremail-Antispam: 1UD129KBjvJXoW3Gr18ZF13Zr15tr13XFy8uFg_yoW7tr43pF Za9ry5Gws8W3yq93yxJF48Zr1rC3W8CrW7JrZ3tr1SyF15Jr48WF18GF12vFZ3tFW8GF1Y vr4jya4jka1akFJanT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUPj14x267AKxVWrJVCq3wAFc2x0x2IEx4CE42xK8VAvwI8IcIk0 rVWrJVCq3wAFIxvE14AKwVWUJVWUGwA2048vs2IY020E87I2jVAFwI0_JrWl82xGYIkIc2 x26xkF7I0E14v26ryj6s0DM28lY4IEw2IIxxk0rwA2F7IY1VAKz4vEj48ve4kI8wA2z4x0 Y4vE2Ix0cI8IcVAFwI0_tr0E3s1l84ACjcxK6xIIjxv20xvEc7CjxVAFwI0_Gr1j6F4UJw A2z4x0Y4vEx4A2jsIE14v26rxl6s0DM28EF7xvwVC2z280aVCY1x0267AKxVW0oVCq3wAS 0I0E0xvYzxvE52x082IY62kv0487Mc02F40EFcxC0VAKzVAqx4xG6I80ewAv7VC0I7IYx2 IY67AKxVWUXVWUAwAv7VC2z280aVAFwI0_Jr0_Gr1lOx8S6xCaFVCjc4AY6r1j6r4UM4x0 Y48IcxkI7VAKI48JM4x0x7Aq67IIx4CEVc8vx2IErcIFxwACI402YVCY1x02628vn2kIc2 xKxwCF04k20xvY0x0EwIxGrwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s026c02F40E14v2 6r1j6r18MI8I3I0E7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_Jw0_GFylIxkGc2 Ij64vIr41lIxAIcVC0I7IYx2IY67AKxVWUJVWUCwCI42IY6xIIjxv20xvEc7CjxVAFwI0_ Cr0_Gr1UMIIF0xvE42xK8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67AKxVWUJVW8Jw CI42IY6I8E87Iv6xkF7I0E14v26r4j6r4UJbIYCTnIWIevJa73UjIFyTuYvjfUoL0eDUUU U 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