From: Chao Yu <chao@kernel.org>
To: jaegeuk@kernel.org
Cc: linux-f2fs-devel@lists.sourceforge.net,
linux-kernel@vger.kernel.org, Chao Yu <chao@kernel.org>,
stable@kernel.org
Subject: [PATCH] f2fs: compress: don't overwrite populated compress cache entry
Date: Wed, 21 Oct 2026 11:05:38 +0000 [thread overview]
Message-ID: <20261021110538.746063-1-chao@kernel.org> (raw)
From: Chao Yu <chao@kernel.org>
f2fs_cache_compressed_page() looks up the entry of blkaddr w/
f2fs_find_cache(), and then grabs it w/ f2fs_grab_cache() and
F2FS_CACHE_LOCK_CREATE. If another reader populates the entry in
between, f2fs_grab_cache() returns that uptodate entry, and we will
overwrite its ino and data.
Before the compress cache was converted to the generic cache,
add_to_page_cache_lru() failed w/ -EEXIST in this case, and the
existing page was left untouched.
Normally, the racer is a reader of the same block of the same inode,
so both copies are the same, let's just back off, as
f2fs_ra_meta_caches() does.
A block address can only be owned by one inode at a time, the block
can not be freed and reused by another inode during population, since
the reader holds the locks of the cluster's pagecache pages until
decompression completes, and truncation must lock these pages before
freeing blocks. So if the uptodate entry was cached by another inode,
it's a bug, and one of the copies must be stale, let's report the bug,
and drop the entry, then readers will load the block from disk.
Cc: stable@kernel.org
Fixes: 6a78d0488116 ("f2fs: cache: use compress cache")
Signed-off-by: Chao Yu <chao@kernel.org>
---
fs/f2fs/compress.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c
index 747141c79900..9cc77d4dc63f 100644
--- a/fs/f2fs/compress.c
+++ b/fs/f2fs/compress.c
@@ -1928,6 +1928,24 @@ static void f2fs_cache_compressed_page(struct f2fs_sb_info *sbi,
if (IS_ERR(entry))
return;
+ /* someone else has populated the entry after f2fs_find_cache() */
+ if (f2fs_cache_test_uptodate(entry)) {
+ /*
+ * a block address can only be owned by one inode, if the
+ * entry was cached by another inode, one of copies must be
+ * stale, drop it and let readers load the block from disk.
+ */
+ if (unlikely(entry->ino != ino)) {
+ f2fs_bug_on(sbi, 1);
+ f2fs_warn_ratelimited(sbi,
+ "%s: blkaddr %u was cached by ino %u, current ino %u",
+ __func__, blkaddr, entry->ino, ino);
+ f2fs_truncate_locked_cache(entry, false);
+ }
+ f2fs_put_cache(entry, true);
+ return;
+ }
+
entry->ino = ino;
memcpy(cache_address(entry), folio_address(folio), sbi->blocksize);
f2fs_cache_set_uptodate(entry);
--
2.49.0
reply other threads:[~2026-10-21 11:05 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
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=20261021110538.746063-1-chao@kernel.org \
--to=chao@kernel.org \
--cc=jaegeuk@kernel.org \
--cc=linux-f2fs-devel@lists.sourceforge.net \
--cc=linux-kernel@vger.kernel.org \
--cc=stable@kernel.org \
/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
all inboxes | Powered by JetHome®