Skip to content

Commit

Permalink
Btrfs: be more precise on errors when getting an inode from disk
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Filipe Manana committed Aug 1, 2016
1 parent 9515558 commit 6771089
Showing 1 changed file with 18 additions and 9 deletions.
27 changes: 18 additions & 9 deletions fs/btrfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -3428,10 +3428,10 @@ int btrfs_orphan_cleanup(struct btrfs_root *root)
found_key.offset = 0;
inode = btrfs_iget(root->fs_info->sb, &found_key, root, NULL);
ret = PTR_ERR_OR_ZERO(inode);
if (ret && ret != -ESTALE)
if (ret && ret != -ENOENT)
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_fs_info *fs_info = root->fs_info;
int is_dead_root = 0;
Expand Down Expand Up @@ -3467,7 +3467,7 @@ int btrfs_orphan_cleanup(struct btrfs_root *root)
* Inode is already gone but the orphan item is still there,
* kill the orphan item.
*/
if (ret == -ESTALE) {
if (ret == -ENOENT) {
trans = btrfs_start_transaction(root, 1);
if (IS_ERR(trans)) {
ret = PTR_ERR(trans);
Expand Down Expand Up @@ -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
*/
static void btrfs_read_locked_inode(struct inode *inode)
static int btrfs_read_locked_inode(struct inode *inode)
{
struct btrfs_path *path;
struct extent_buffer *leaf;
Expand All @@ -3645,14 +3645,19 @@ static void btrfs_read_locked_inode(struct inode *inode)
filled = true;

path = btrfs_alloc_path();
if (!path)
if (!path) {
ret = -ENOMEM;
goto make_bad;
}

memcpy(&location, &BTRFS_I(inode)->location, sizeof(location));

ret = btrfs_lookup_inode(NULL, root, path, &location, 0);
if (ret)
if (ret) {
if (ret > 0)
ret = -ENOENT;
goto make_bad;
}

leaf = path->nodes[0];

Expand Down Expand Up @@ -3805,11 +3810,12 @@ static void btrfs_read_locked_inode(struct inode *inode)
}

btrfs_update_iflags(inode);
return;
return 0;

make_bad:
btrfs_free_path(path);
make_bad_inode(inode);
return ret;
}

/*
Expand Down Expand Up @@ -5595,7 +5601,9 @@ struct inode *btrfs_iget(struct super_block *s, struct btrfs_key *location,
return ERR_PTR(-ENOMEM);

if (inode->i_state & I_NEW) {
btrfs_read_locked_inode(inode);
int ret;

ret = btrfs_read_locked_inode(inode);
if (!is_bad_inode(inode)) {
inode_tree_add(inode);
unlock_new_inode(inode);
Expand All @@ -5604,7 +5612,8 @@ struct inode *btrfs_iget(struct super_block *s, struct btrfs_key *location,
} else {
unlock_new_inode(inode);
iput(inode);
inode = ERR_PTR(-ESTALE);
ASSERT(ret < 0);
inode = ERR_PTR(ret < 0 ? ret : -ESTALE);
}
}

Expand Down

0 comments on commit 6771089

Please sign in to comment.