Skip to content

Commit 6771089

Browse files
committed
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 <[email protected]>
1 parent 9515558 commit 6771089

File tree

1 file changed

+18
-9
lines changed

1 file changed

+18
-9
lines changed

fs/btrfs/inode.c

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3428,10 +3428,10 @@ int btrfs_orphan_cleanup(struct btrfs_root *root)
34283428
found_key.offset = 0;
34293429
inode = btrfs_iget(root->fs_info->sb, &found_key, root, NULL);
34303430
ret = PTR_ERR_OR_ZERO(inode);
3431-
if (ret && ret != -ESTALE)
3431+
if (ret && ret != -ENOENT)
34323432
goto out;
34333433

3434-
if (ret == -ESTALE && root == root->fs_info->tree_root) {
3434+
if (ret == -ENOENT && root == root->fs_info->tree_root) {
34353435
struct btrfs_root *dead_root;
34363436
struct btrfs_fs_info *fs_info = root->fs_info;
34373437
int is_dead_root = 0;
@@ -3467,7 +3467,7 @@ int btrfs_orphan_cleanup(struct btrfs_root *root)
34673467
* Inode is already gone but the orphan item is still there,
34683468
* kill the orphan item.
34693469
*/
3470-
if (ret == -ESTALE) {
3470+
if (ret == -ENOENT) {
34713471
trans = btrfs_start_transaction(root, 1);
34723472
if (IS_ERR(trans)) {
34733473
ret = PTR_ERR(trans);
@@ -3626,7 +3626,7 @@ static noinline int acls_after_inode_item(struct extent_buffer *leaf,
36263626
/*
36273627
* read an inode from the btree into the in-memory inode
36283628
*/
3629-
static void btrfs_read_locked_inode(struct inode *inode)
3629+
static int btrfs_read_locked_inode(struct inode *inode)
36303630
{
36313631
struct btrfs_path *path;
36323632
struct extent_buffer *leaf;
@@ -3645,14 +3645,19 @@ static void btrfs_read_locked_inode(struct inode *inode)
36453645
filled = true;
36463646

36473647
path = btrfs_alloc_path();
3648-
if (!path)
3648+
if (!path) {
3649+
ret = -ENOMEM;
36493650
goto make_bad;
3651+
}
36503652

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

36533655
ret = btrfs_lookup_inode(NULL, root, path, &location, 0);
3654-
if (ret)
3656+
if (ret) {
3657+
if (ret > 0)
3658+
ret = -ENOENT;
36553659
goto make_bad;
3660+
}
36563661

36573662
leaf = path->nodes[0];
36583663

@@ -3805,11 +3810,12 @@ static void btrfs_read_locked_inode(struct inode *inode)
38053810
}
38063811

38073812
btrfs_update_iflags(inode);
3808-
return;
3813+
return 0;
38093814

38103815
make_bad:
38113816
btrfs_free_path(path);
38123817
make_bad_inode(inode);
3818+
return ret;
38133819
}
38143820

38153821
/*
@@ -5595,7 +5601,9 @@ struct inode *btrfs_iget(struct super_block *s, struct btrfs_key *location,
55955601
return ERR_PTR(-ENOMEM);
55965602

55975603
if (inode->i_state & I_NEW) {
5598-
btrfs_read_locked_inode(inode);
5604+
int ret;
5605+
5606+
ret = btrfs_read_locked_inode(inode);
55995607
if (!is_bad_inode(inode)) {
56005608
inode_tree_add(inode);
56015609
unlock_new_inode(inode);
@@ -5604,7 +5612,8 @@ struct inode *btrfs_iget(struct super_block *s, struct btrfs_key *location,
56045612
} else {
56055613
unlock_new_inode(inode);
56065614
iput(inode);
5607-
inode = ERR_PTR(-ESTALE);
5615+
ASSERT(ret < 0);
5616+
inode = ERR_PTR(ret < 0 ? ret : -ESTALE);
56085617
}
56095618
}
56105619

0 commit comments

Comments
 (0)