blob: 26516fdd726867682fb33af901f165aa387eb3ed [file] [log] [blame]
From stable+bounces-171678-greg=kroah.com@vger.kernel.org Tue Aug 19 01:48:19 2025
From: Sasha Levin <sashal@kernel.org>
Date: Mon, 18 Aug 2025 19:47:23 -0400
Subject: btrfs: don't ignore inode missing when replaying log tree
To: stable@vger.kernel.org
Cc: Filipe Manana <fdmanana@suse.com>, Boris Burkov <boris@bur.io>, David Sterba <dsterba@suse.com>, Sasha Levin <sashal@kernel.org>
Message-ID: <20250818234723.154435-1-sashal@kernel.org>
From: Filipe Manana <fdmanana@suse.com>
[ Upstream commit 7ebf381a69421a88265d3c49cd0f007ba7336c9d ]
During log replay, at add_inode_ref(), we return -ENOENT if our current
inode isn't found on the subvolume tree or if a parent directory isn't
found. The error comes from btrfs_iget_logging() <- btrfs_iget() <-
btrfs_read_locked_inode().
The single caller of add_inode_ref(), replay_one_buffer(), ignores an
-ENOENT error because it expects that error to mean only that a parent
directory wasn't found and that is ok.
Before commit 5f61b961599a ("btrfs: fix inode lookup error handling during
log replay") we were converting any error when getting a parent directory
to -ENOENT and any error when getting the current inode to -EIO, so our
caller would fail log replay in case we can't find the current inode.
After that commit however in case the current inode is not found we return
-ENOENT to the caller and therefore it ignores the critical fact that the
current inode was not found in the subvolume tree.
Fix this by converting -ENOENT to 0 when we don't find a parent directory,
returning -ENOENT when we don't find the current inode and making the
caller, replay_one_buffer(), not ignore -ENOENT anymore.
Fixes: 5f61b961599a ("btrfs: fix inode lookup error handling during log replay")
CC: stable@vger.kernel.org # 6.16
Reviewed-by: Boris Burkov <boris@bur.io>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
[ adapted btrfs_inode pointer usage to older inode API ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/btrfs/tree-log.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -1422,6 +1422,8 @@ static noinline int add_inode_ref(struct
btrfs_dir = btrfs_iget_logging(parent_objectid, root);
if (IS_ERR(btrfs_dir)) {
ret = PTR_ERR(btrfs_dir);
+ if (ret == -ENOENT)
+ ret = 0;
dir = NULL;
goto out;
}
@@ -1455,6 +1457,15 @@ static noinline int add_inode_ref(struct
if (IS_ERR(btrfs_dir)) {
ret = PTR_ERR(btrfs_dir);
dir = NULL;
+ /*
+ * A new parent dir may have not been
+ * logged and not exist in the subvolume
+ * tree, see the comment above before
+ * the loop when getting the first
+ * parent dir.
+ */
+ if (ret == -ENOENT)
+ ret = 0;
goto out;
}
dir = &btrfs_dir->vfs_inode;
@@ -2623,9 +2634,8 @@ static int replay_one_buffer(struct btrf
key.type == BTRFS_INODE_EXTREF_KEY) {
ret = add_inode_ref(wc->trans, root, log, path,
eb, i, &key);
- if (ret && ret != -ENOENT)
+ if (ret)
break;
- ret = 0;
} else if (key.type == BTRFS_EXTENT_DATA_KEY) {
ret = replay_one_extent(wc->trans, root, path,
eb, i, &key);