From: Sasha Levin <sashal@kernel.org>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: Zhang Yi <yi.zhang@huawei.com>, Jan Kara <jack@suse.cz>,
Theodore Ts'o <tytso@mit.edu>, Sasha Levin <sashal@kernel.org>,
adilger.kernel@dilger.ca, linux-ext4@vger.kernel.org
Subject: [PATCH AUTOSEL 6.7 43/44] ext4: correct the hole length returned by ext4_map_blocks()
Date: Wed, 7 Feb 2024 16:21:10 -0500 [thread overview]
Message-ID: <20240207212142.1399-43-sashal@kernel.org> (raw)
In-Reply-To: <20240207212142.1399-1-sashal@kernel.org>
From: Zhang Yi <yi.zhang@huawei.com>
[ Upstream commit 6430dea07e85958fa87d0276c0c4388dd51e630b ]
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 <yi.zhang@huawei.com>
Suggested-by: Jan Kara <jack@suse.cz>
Reviewed-by: Jan Kara <jack@suse.cz>
Link: https://lore.kernel.org/r/20240127015825.1608160-4-yi.zhang@huaweicloud.com
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
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;
}
--
2.43.0
next prev parent reply other threads:[~2024-02-07 21:23 UTC|newest]
Thread overview: 46+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-02-07 21:20 [PATCH AUTOSEL 6.7 01/44] ext4: avoid dividing by 0 in mb_update_avg_fragment_size() when block bitmap corrupt Sasha Levin
2024-02-07 21:20 ` [PATCH AUTOSEL 6.7 02/44] ext4: avoid allocating blocks from corrupted group in ext4_mb_try_best_found() Sasha Levin
2024-02-07 21:20 ` [PATCH AUTOSEL 6.7 03/44] ext4: avoid allocating blocks from corrupted group in ext4_mb_find_by_goal() Sasha Levin
2024-02-07 21:20 ` [PATCH AUTOSEL 6.7 04/44] Input: goodix - accept ACPI resources with gpio_count == 3 && gpio_int_idx == 0 Sasha Levin
2024-02-07 21:20 ` [PATCH AUTOSEL 6.7 05/44] dmaengine: ti: edma: Add some null pointer checks to the edma_probe Sasha Levin
2024-02-07 21:20 ` [PATCH AUTOSEL 6.7 06/44] ASoC: amd: acp: Add check for cpu dai link initialization Sasha Levin
2024-02-07 21:20 ` [PATCH AUTOSEL 6.7 07/44] ASoC: codecs: wcd934x: drop unneeded regulator include Sasha Levin
2024-02-08 11:37 ` Mark Brown
2024-02-22 12:29 ` Sasha Levin
2024-02-07 21:20 ` [PATCH AUTOSEL 6.7 08/44] regulator: pwm-regulator: Add validity checks in continuous .get_voltage Sasha Levin
2024-02-07 21:20 ` [PATCH AUTOSEL 6.7 09/44] HID: logitech-hidpp: add support for Logitech G Pro X Superlight 2 Sasha Levin
2024-02-07 21:20 ` [PATCH AUTOSEL 6.7 10/44] ALSA: hda: Replace numeric device IDs with constant values Sasha Levin
2024-02-07 21:20 ` [PATCH AUTOSEL 6.7 11/44] ALSA: hda: Increase default bdl_pos_adj for Apollo Lake Sasha Levin
2024-02-07 21:20 ` [PATCH AUTOSEL 6.7 12/44] HID: nvidia-shield: Add missing null pointer checks to LED initialization Sasha Levin
2024-02-07 21:20 ` [PATCH AUTOSEL 6.7 13/44] nvmet-tcp: fix nvme tcp ida memory leak Sasha Levin
2024-02-07 21:20 ` [PATCH AUTOSEL 6.7 14/44] usb: ucsi_acpi: Quirk to ack a connector change ack cmd Sasha Levin
2024-02-07 21:20 ` [PATCH AUTOSEL 6.7 15/44] ALSA: usb-audio: Check presence of valid altsetting control Sasha Levin
2024-02-07 21:20 ` [PATCH AUTOSEL 6.7 16/44] ASoC: sunxi: sun4i-spdif: Add support for Allwinner H616 Sasha Levin
2024-02-07 21:20 ` [PATCH AUTOSEL 6.7 17/44] ALSA: hda: cs35l41: Support additional ASUS Zenbook UX3402VA Sasha Levin
2024-02-07 21:20 ` [PATCH AUTOSEL 6.7 18/44] ALSA: hda: cs35l41: Support ASUS Zenbook UM3402YAR Sasha Levin
2024-02-07 21:20 ` [PATCH AUTOSEL 6.7 19/44] regulator (max5970): Fix IRQ handler Sasha Levin
2024-02-07 21:20 ` [PATCH AUTOSEL 6.7 20/44] spi: sh-msiof: avoid integer overflow in constants Sasha Levin
2024-02-07 21:20 ` [PATCH AUTOSEL 6.7 21/44] Input: xpad - add Lenovo Legion Go controllers Sasha Levin
2024-02-07 21:20 ` [PATCH AUTOSEL 6.7 22/44] misc: open-dice: Fix spurious lockdep warning Sasha Levin
2024-02-07 21:20 ` [PATCH AUTOSEL 6.7 23/44] netfilter: conntrack: check SCTP_CID_SHUTDOWN_ACK for vtag setting in sctp_new Sasha Levin
2024-02-07 21:20 ` [PATCH AUTOSEL 6.7 24/44] drm/amdkfd: Use correct drm device for cgroup permission check Sasha Levin
2024-02-07 21:20 ` [PATCH AUTOSEL 6.7 25/44] drm/amd/display: increased min_dcfclk_mhz and min_fclk_mhz Sasha Levin
2024-02-07 21:20 ` [PATCH AUTOSEL 6.7 26/44] drm/amd/display: fix USB-C flag update after enc10 feature init Sasha Levin
2024-02-07 21:20 ` [PATCH AUTOSEL 6.7 27/44] drm/amd/display: Fix DPSTREAM CLK on and off sequence Sasha Levin
2024-02-07 21:20 ` [PATCH AUTOSEL 6.7 28/44] cifs: make sure that channel scaling is done only once Sasha Levin
2024-02-07 21:20 ` [PATCH AUTOSEL 6.7 29/44] ASoC: wm_adsp: Don't overwrite fwf_name with the default Sasha Levin
2024-02-07 21:20 ` [PATCH AUTOSEL 6.7 30/44] ALSA: usb-audio: Ignore clock selector errors for single connection Sasha Levin
2024-02-07 21:20 ` [PATCH AUTOSEL 6.7 31/44] nvme-fc: do not wait in vain when unloading module Sasha Levin
2024-02-07 21:20 ` [PATCH AUTOSEL 6.7 32/44] nvmet-fcloop: swap the list_add_tail arguments Sasha Levin
2024-02-07 21:21 ` [PATCH AUTOSEL 6.7 33/44] nvmet-fc: release reference on target port Sasha Levin
2024-02-07 21:21 ` [PATCH AUTOSEL 6.7 34/44] nvmet-fc: defer cleanup using RCU properly Sasha Levin
2024-02-07 21:21 ` [PATCH AUTOSEL 6.7 35/44] nvmet-fc: free queue and assoc directly Sasha Levin
2024-02-07 21:21 ` [PATCH AUTOSEL 6.7 36/44] nvmet-fc: hold reference on hostport match Sasha Levin
2024-02-07 21:21 ` [PATCH AUTOSEL 6.7 37/44] nvmet-fc: do not tack refs on tgtports from assoc Sasha Levin
2024-02-07 21:21 ` [PATCH AUTOSEL 6.7 38/44] nvmet-fc: abort command when there is no binding Sasha Levin
2024-02-07 21:21 ` [PATCH AUTOSEL 6.7 39/44] nvmet-fc: avoid deadlock on delete association path Sasha Levin
2024-02-07 21:21 ` [PATCH AUTOSEL 6.7 40/44] nvmet-fc: take ref count on tgtport before delete assoc Sasha Levin
2024-02-07 21:21 ` [PATCH AUTOSEL 6.7 41/44] cifs: do not search for channel if server is terminating Sasha Levin
2024-02-07 21:21 ` [PATCH AUTOSEL 6.7 42/44] smb: client: increase number of PDUs allowed in a compound request Sasha Levin
2024-02-07 21:21 ` Sasha Levin [this message]
2024-02-07 21:21 ` [PATCH AUTOSEL 6.7 44/44] Input: i8042 - add Fujitsu Lifebook U728 to i8042 quirk table Sasha Levin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240207212142.1399-43-sashal@kernel.org \
--to=sashal@kernel.org \
--cc=adilger.kernel@dilger.ca \
--cc=jack@suse.cz \
--cc=linux-ext4@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=stable@vger.kernel.org \
--cc=tytso@mit.edu \
--cc=yi.zhang@huawei.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox