From 8cc569696dac51fc62bb39b3b8f530582b916d29 Mon Sep 17 00:00:00 2001 From: Yichong Chen Date: Wed, 22 Jul 2026 10:54:35 +0800 Subject: [PATCH] btrfs: retry verity reads for not-uptodate Merkle folios btrfs_read_merkle_tree_page() can find a folio in the mapping that is not uptodate. After taking the folio lock, the current code treats that state as a read error and returns -EIO. That can make a previous transient read failure sticky. If the failed read left a not-uptodate folio in the mapping, later callers find that folio and fail instead of retrying the read. Keep the existing page-cache insertion and locking order, but retry the Merkle item read when a not-uptodate folio is found in the mapping. Also unlock the folio when read_key_bytes() fails so that a later caller can lock it and retry the read. Fixes: 06ed09351b67 ("btrfs: convert btrfs_read_merkle_tree_page() to use a folio") Reviewed-by: Boris Burkov Signed-off-by: Yichong Chen Signed-off-by: David Sterba --- fs/btrfs/verity.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/fs/btrfs/verity.c b/fs/btrfs/verity.c index ebada817bd33..4e0ab5842274 100644 --- a/fs/btrfs/verity.c +++ b/fs/btrfs/verity.c @@ -720,14 +720,18 @@ static struct page *btrfs_read_merkle_tree_page(struct inode *inode, goto out; folio_lock(folio); - /* If it's not uptodate after we have the lock, we got a read error. */ - if (!folio_test_uptodate(folio)) { + /* Folio was truncated from mapping. */ + if (!folio->mapping) { folio_unlock(folio); folio_put(folio); - return ERR_PTR(-EIO); + goto again; } - folio_unlock(folio); - goto out; + /* Another reader may have filled the folio while we waited. */ + if (folio_test_uptodate(folio)) { + folio_unlock(folio); + goto out; + } + goto read_folio; } folio = filemap_alloc_folio(mapping_gfp_constraint(inode->i_mapping, ~__GFP_FS), @@ -744,6 +748,7 @@ static struct page *btrfs_read_merkle_tree_page(struct inode *inode, return ERR_PTR(ret); } +read_folio: /* * Merkle item keys are indexed from byte 0 in the merkle tree. * They have the form: @@ -753,6 +758,7 @@ static struct page *btrfs_read_merkle_tree_page(struct inode *inode, ret = read_key_bytes(BTRFS_I(inode), BTRFS_VERITY_MERKLE_ITEM_KEY, off, folio_address(folio), PAGE_SIZE, folio); if (ret < 0) { + folio_unlock(folio); folio_put(folio); return ERR_PTR(ret); }