linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Zhang Yi <yi.zhang@huaweicloud.com>
To: linux-ext4@vger.kernel.org
Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org,
	tytso@mit.edu, adilger.kernel@dilger.ca, jack@suse.cz,
	yi.zhang@huawei.com, yi.zhang@huaweicloud.com,
	libaokun1@huawei.com, yangerkun@huawei.com
Subject: [PATCH 2/4] ext4: check for conflicts when caching extents
Date: Fri, 31 Oct 2025 14:29:03 +0800	[thread overview]
Message-ID: <20251031062905.4135909-3-yi.zhang@huaweicloud.com> (raw)
In-Reply-To: <20251031062905.4135909-1-yi.zhang@huaweicloud.com>

From: Zhang Yi <yi.zhang@huawei.com>

Since ext4_es_cache_extent() can only be used to load on-disk extents
and does not permit modifying extents, it is not possible to overwrite
an extent of a different type. To prevent misuse of the interface, the
current implementation checks only the first existing extent but does
not verify all extents within the range to be inserted, as doing so
would be time-consuming in highly fragmented scenarios. Furthermore,
adding such checks to __es_remove_extent() would complicate its logic.
Therefore, a full check can be performed in debug mode to ensure that
the function does not overwrite any valuable extents.

Signed-off-by: Zhang Yi <yi.zhang@huawei.com>
---
 fs/ext4/extents_status.c | 50 +++++++++++++++++++++++++++++++++++++---
 1 file changed, 47 insertions(+), 3 deletions(-)

diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c
index f9546ecf7340..55103c331b6b 100644
--- a/fs/ext4/extents_status.c
+++ b/fs/ext4/extents_status.c
@@ -985,6 +985,48 @@ void ext4_es_insert_extent(struct inode *inode, ext4_lblk_t lblk,
 	return;
 }
 
+#ifdef CONFIG_EXT4_DEBUG
+/*
+ * If we find an extent that already exists during caching extents, its
+ * status must match the one to be cached. Otherwise, the extent status
+ * tree may have been corrupted.
+ */
+static void ext4_es_cache_extent_check(struct inode *inode,
+		struct extent_status *es, struct extent_status *newes)
+{
+	unsigned int status = ext4_es_type(newes);
+	struct rb_node *node;
+
+	if (ext4_es_type(es) != status)
+		goto conflict;
+
+	while ((node = rb_next(&es->rb_node)) != NULL) {
+		es = rb_entry(node, struct extent_status, rb_node);
+
+		if (es->es_lblk >= newes->es_lblk + newes->es_len)
+			break;
+		if (ext4_es_type(es) != status)
+			goto conflict;
+	}
+	return;
+
+conflict:
+	ext4_warning_inode(inode,
+			   "ES cache extent failed: add [%d,%d,%llu,0x%x] conflict with existing [%d,%d,%llu,0x%x]\n",
+			   newes->es_lblk, newes->es_len, ext4_es_pblock(newes),
+			   ext4_es_status(newes), es->es_lblk, es->es_len,
+			   ext4_es_pblock(es), ext4_es_status(es));
+
+	WARN_ON_ONCE(1);
+}
+#else
+static void ext4_es_cache_extent_check(struct inode __maybe_unused *inode,
+		struct extent_status *es, struct extent_status *newes)
+{
+	WARN_ON_ONCE(ext4_es_type(es) != ext4_es_type(newes));
+}
+#endif
+
 /*
  * ext4_es_cache_extent() inserts extent information into the extent status
  * tree. If 'overwrite' is not set, it inserts extent only if there isn't
@@ -1022,9 +1064,11 @@ void ext4_es_cache_extent(struct inode *inode, ext4_lblk_t lblk,
 	if (es && es->es_lblk <= end) {
 		if (!overwrite)
 			goto unlock;
-
-		/* Only extents of the same type can be overwritten. */
-		WARN_ON_ONCE(ext4_es_type(es) != status);
+		/*
+		 * Check whether the overwrites are safe. Only extents
+		 * of the same type can be overwritten.
+		 */
+		ext4_es_cache_extent_check(inode, es, &newes);
 		if (__es_remove_extent(inode, lblk, end, NULL, NULL))
 			goto unlock;
 	}
-- 
2.46.1


  parent reply	other threads:[~2025-10-31  6:31 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-10-31  6:29 [PATCH 0/4] ext4: replace ext4_es_insert_extent() when caching on-disk extents Zhang Yi
2025-10-31  6:29 ` [PATCH 1/4] ext4: make ext4_es_cache_extent() support overwrite existing extents Zhang Yi
2025-11-06  9:15   ` Jan Kara
2025-11-06 13:02     ` Zhang Yi
2025-11-11 10:33       ` Jan Kara
2025-11-19  9:36         ` Zhang Yi
2025-10-31  6:29 ` Zhang Yi [this message]
2025-10-31  6:29 ` [PATCH 3/4] ext4: adjust the debug info in ext4_es_cache_extent() Zhang Yi
2025-10-31  6:29 ` [PATCH 4/4] ext4: replace ext4_es_insert_extent() when caching on-disk extents Zhang Yi

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=20251031062905.4135909-3-yi.zhang@huaweicloud.com \
    --to=yi.zhang@huaweicloud.com \
    --cc=adilger.kernel@dilger.ca \
    --cc=jack@suse.cz \
    --cc=libaokun1@huawei.com \
    --cc=linux-ext4@vger.kernel.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=tytso@mit.edu \
    --cc=yangerkun@huawei.com \
    --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;
as well as URLs for NNTP newsgroup(s).