mirror of
https://github.com/torvalds/linux.git
synced 2026-06-01 19:13:47 +02:00
btrfs: don't ignore inode missing when replaying log tree
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 commit5f61b96159("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:5f61b96159("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>
This commit is contained in:
parent
041c39da53
commit
7ebf381a69
|
|
@ -1416,6 +1416,8 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans,
|
|||
dir = btrfs_iget_logging(parent_objectid, root);
|
||||
if (IS_ERR(dir)) {
|
||||
ret = PTR_ERR(dir);
|
||||
if (ret == -ENOENT)
|
||||
ret = 0;
|
||||
dir = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
|
@ -1440,6 +1442,15 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans,
|
|||
if (IS_ERR(dir)) {
|
||||
ret = PTR_ERR(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;
|
||||
}
|
||||
}
|
||||
|
|
@ -2551,9 +2562,8 @@ static int replay_one_buffer(struct btrfs_root *log, struct extent_buffer *eb,
|
|||
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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user