summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFilipe Manana <fdmanana@suse.com>2016-06-06 06:51:25 -0400
committerFilipe Manana <fdmanana@suse.com>2016-08-01 02:32:03 -0400
commit67710892ec983aa79ad1e2a2642fe8e3a4a194ea (patch)
tree251f0feaddfbbf6e98690943d470972d7b37c3d6
parent951555856b88aa47bc238de6b4c6e97bfd9d36df (diff)
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>
-rw-r--r--fs/btrfs/inode.c27
1 files changed, 18 insertions, 9 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 3e61bd1f3f65..f9686541997b 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -3428,10 +3428,10 @@ int btrfs_orphan_cleanup(struct btrfs_root *root)
3428 found_key.offset = 0; 3428 found_key.offset = 0;
3429 inode = btrfs_iget(root->fs_info->sb, &found_key, root, NULL); 3429 inode = btrfs_iget(root->fs_info->sb, &found_key, root, NULL);
3430 ret = PTR_ERR_OR_ZERO(inode); 3430 ret = PTR_ERR_OR_ZERO(inode);
3431 if (ret && ret != -ESTALE) 3431 if (ret && ret != -ENOENT)
3432 goto out; 3432 goto out;
3433 3433
3434 if (ret == -ESTALE && root == root->fs_info->tree_root) { 3434 if (ret == -ENOENT && root == root->fs_info->tree_root) {
3435 struct btrfs_root *dead_root; 3435 struct btrfs_root *dead_root;
3436 struct btrfs_fs_info *fs_info = root->fs_info; 3436 struct btrfs_fs_info *fs_info = root->fs_info;
3437 int is_dead_root = 0; 3437 int is_dead_root = 0;
@@ -3467,7 +3467,7 @@ int btrfs_orphan_cleanup(struct btrfs_root *root)
3467 * Inode is already gone but the orphan item is still there, 3467 * Inode is already gone but the orphan item is still there,
3468 * kill the orphan item. 3468 * kill the orphan item.
3469 */ 3469 */
3470 if (ret == -ESTALE) { 3470 if (ret == -ENOENT) {
3471 trans = btrfs_start_transaction(root, 1); 3471 trans = btrfs_start_transaction(root, 1);
3472 if (IS_ERR(trans)) { 3472 if (IS_ERR(trans)) {
3473 ret = PTR_ERR(trans); 3473 ret = PTR_ERR(trans);
@@ -3626,7 +3626,7 @@ static noinline int acls_after_inode_item(struct extent_buffer *leaf,
3626/* 3626/*
3627 * read an inode from the btree into the in-memory inode 3627 * read an inode from the btree into the in-memory inode
3628 */ 3628 */
3629static void btrfs_read_locked_inode(struct inode *inode) 3629static int btrfs_read_locked_inode(struct inode *inode)
3630{ 3630{
3631 struct btrfs_path *path; 3631 struct btrfs_path *path;
3632 struct extent_buffer *leaf; 3632 struct extent_buffer *leaf;
@@ -3645,14 +3645,19 @@ static void btrfs_read_locked_inode(struct inode *inode)
3645 filled = true; 3645 filled = true;
3646 3646
3647 path = btrfs_alloc_path(); 3647 path = btrfs_alloc_path();
3648 if (!path) 3648 if (!path) {
3649 ret = -ENOMEM;
3649 goto make_bad; 3650 goto make_bad;
3651 }
3650 3652
3651 memcpy(&location, &BTRFS_I(inode)->location, sizeof(location)); 3653 memcpy(&location, &BTRFS_I(inode)->location, sizeof(location));
3652 3654
3653 ret = btrfs_lookup_inode(NULL, root, path, &location, 0); 3655 ret = btrfs_lookup_inode(NULL, root, path, &location, 0);
3654 if (ret) 3656 if (ret) {
3657 if (ret > 0)
3658 ret = -ENOENT;
3655 goto make_bad; 3659 goto make_bad;
3660 }
3656 3661
3657 leaf = path->nodes[0]; 3662 leaf = path->nodes[0];
3658 3663
@@ -3805,11 +3810,12 @@ cache_acl:
3805 } 3810 }
3806 3811
3807 btrfs_update_iflags(inode); 3812 btrfs_update_iflags(inode);
3808 return; 3813 return 0;
3809 3814
3810make_bad: 3815make_bad:
3811 btrfs_free_path(path); 3816 btrfs_free_path(path);
3812 make_bad_inode(inode); 3817 make_bad_inode(inode);
3818 return ret;
3813} 3819}
3814 3820
3815/* 3821/*
@@ -5595,7 +5601,9 @@ struct inode *btrfs_iget(struct super_block *s, struct btrfs_key *location,
5595 return ERR_PTR(-ENOMEM); 5601 return ERR_PTR(-ENOMEM);
5596 5602
5597 if (inode->i_state & I_NEW) { 5603 if (inode->i_state & I_NEW) {
5598 btrfs_read_locked_inode(inode); 5604 int ret;
5605
5606 ret = btrfs_read_locked_inode(inode);
5599 if (!is_bad_inode(inode)) { 5607 if (!is_bad_inode(inode)) {
5600 inode_tree_add(inode); 5608 inode_tree_add(inode);
5601 unlock_new_inode(inode); 5609 unlock_new_inode(inode);
@@ -5604,7 +5612,8 @@ struct inode *btrfs_iget(struct super_block *s, struct btrfs_key *location,
5604 } else { 5612 } else {
5605 unlock_new_inode(inode); 5613 unlock_new_inode(inode);
5606 iput(inode); 5614 iput(inode);
5607 inode = ERR_PTR(-ESTALE); 5615 ASSERT(ret < 0);
5616 inode = ERR_PTR(ret < 0 ? ret : -ESTALE);
5608 } 5617 }
5609 } 5618 }
5610 5619