Commit 67710892 authored by Filipe Manana's avatar Filipe Manana

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: default avatarFilipe Manana <fdmanana@suse.com>
parent 95155585
...@@ -3428,10 +3428,10 @@ int btrfs_orphan_cleanup(struct btrfs_root *root) ...@@ -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) ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment