mirror of https://gitee.com/openkylin/linux.git
Btrfs: be more precise on errors when getting an inode from disk
When we attempt to read an inode from disk, we end up always returning an -ESTALE error to the caller regardless of the actual failure reason, which can be an out of memory problem (when allocating a path), some error found when reading from the fs/subvolume btree (like a genuine IO error) or the inode does not exists. So lets start returning the real error code to the callers so that they don't treat all -ESTALE errors as meaning that the inode does not exists (such as during orphan cleanup). This will also be needed for a subsequent patch in the same series dealing with a special fsync case. Signed-off-by: Filipe Manana <fdmanana@suse.com>
This commit is contained in:
parent
951555856b
commit
67710892ec
|
@ -3428,10 +3428,10 @@ int btrfs_orphan_cleanup(struct btrfs_root *root)
|
||||||
found_key.offset = 0;
|
found_key.offset = 0;
|
||||||
inode = btrfs_iget(root->fs_info->sb, &found_key, root, NULL);
|
inode = btrfs_iget(root->fs_info->sb, &found_key, root, NULL);
|
||||||
ret = PTR_ERR_OR_ZERO(inode);
|
ret = PTR_ERR_OR_ZERO(inode);
|
||||||
if (ret && ret != -ESTALE)
|
if (ret && ret != -ENOENT)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (ret == -ESTALE && root == root->fs_info->tree_root) {
|
if (ret == -ENOENT && root == root->fs_info->tree_root) {
|
||||||
struct btrfs_root *dead_root;
|
struct btrfs_root *dead_root;
|
||||||
struct btrfs_fs_info *fs_info = root->fs_info;
|
struct btrfs_fs_info *fs_info = root->fs_info;
|
||||||
int is_dead_root = 0;
|
int is_dead_root = 0;
|
||||||
|
@ -3467,7 +3467,7 @@ int btrfs_orphan_cleanup(struct btrfs_root *root)
|
||||||
* Inode is already gone but the orphan item is still there,
|
* Inode is already gone but the orphan item is still there,
|
||||||
* kill the orphan item.
|
* kill the orphan item.
|
||||||
*/
|
*/
|
||||||
if (ret == -ESTALE) {
|
if (ret == -ENOENT) {
|
||||||
trans = btrfs_start_transaction(root, 1);
|
trans = btrfs_start_transaction(root, 1);
|
||||||
if (IS_ERR(trans)) {
|
if (IS_ERR(trans)) {
|
||||||
ret = PTR_ERR(trans);
|
ret = PTR_ERR(trans);
|
||||||
|
@ -3626,7 +3626,7 @@ static noinline int acls_after_inode_item(struct extent_buffer *leaf,
|
||||||
/*
|
/*
|
||||||
* read an inode from the btree into the in-memory inode
|
* read an inode from the btree into the in-memory inode
|
||||||
*/
|
*/
|
||||||
static void btrfs_read_locked_inode(struct inode *inode)
|
static int btrfs_read_locked_inode(struct inode *inode)
|
||||||
{
|
{
|
||||||
struct btrfs_path *path;
|
struct btrfs_path *path;
|
||||||
struct extent_buffer *leaf;
|
struct extent_buffer *leaf;
|
||||||
|
@ -3645,14 +3645,19 @@ static void btrfs_read_locked_inode(struct inode *inode)
|
||||||
filled = true;
|
filled = true;
|
||||||
|
|
||||||
path = btrfs_alloc_path();
|
path = btrfs_alloc_path();
|
||||||
if (!path)
|
if (!path) {
|
||||||
|
ret = -ENOMEM;
|
||||||
goto make_bad;
|
goto make_bad;
|
||||||
|
}
|
||||||
|
|
||||||
memcpy(&location, &BTRFS_I(inode)->location, sizeof(location));
|
memcpy(&location, &BTRFS_I(inode)->location, sizeof(location));
|
||||||
|
|
||||||
ret = btrfs_lookup_inode(NULL, root, path, &location, 0);
|
ret = btrfs_lookup_inode(NULL, root, path, &location, 0);
|
||||||
if (ret)
|
if (ret) {
|
||||||
|
if (ret > 0)
|
||||||
|
ret = -ENOENT;
|
||||||
goto make_bad;
|
goto make_bad;
|
||||||
|
}
|
||||||
|
|
||||||
leaf = path->nodes[0];
|
leaf = path->nodes[0];
|
||||||
|
|
||||||
|
@ -3805,11 +3810,12 @@ static void btrfs_read_locked_inode(struct inode *inode)
|
||||||
}
|
}
|
||||||
|
|
||||||
btrfs_update_iflags(inode);
|
btrfs_update_iflags(inode);
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
make_bad:
|
make_bad:
|
||||||
btrfs_free_path(path);
|
btrfs_free_path(path);
|
||||||
make_bad_inode(inode);
|
make_bad_inode(inode);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -5595,7 +5601,9 @@ struct inode *btrfs_iget(struct super_block *s, struct btrfs_key *location,
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
if (inode->i_state & I_NEW) {
|
if (inode->i_state & I_NEW) {
|
||||||
btrfs_read_locked_inode(inode);
|
int ret;
|
||||||
|
|
||||||
|
ret = btrfs_read_locked_inode(inode);
|
||||||
if (!is_bad_inode(inode)) {
|
if (!is_bad_inode(inode)) {
|
||||||
inode_tree_add(inode);
|
inode_tree_add(inode);
|
||||||
unlock_new_inode(inode);
|
unlock_new_inode(inode);
|
||||||
|
@ -5604,7 +5612,8 @@ struct inode *btrfs_iget(struct super_block *s, struct btrfs_key *location,
|
||||||
} else {
|
} else {
|
||||||
unlock_new_inode(inode);
|
unlock_new_inode(inode);
|
||||||
iput(inode);
|
iput(inode);
|
||||||
inode = ERR_PTR(-ESTALE);
|
ASSERT(ret < 0);
|
||||||
|
inode = ERR_PTR(ret < 0 ? ret : -ESTALE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue