Skip to content

Commit 64c043d

Browse files
Liu Bomasoncl
authored andcommitted
Btrfs: fix up read_tree_block to return proper error
The return value of read_tree_block() can confuse callers as it always returns NULL for either -ENOMEM or -EIO, so it's likely that callers parse it to a wrong error, for instance, in btrfs_read_tree_root(). This fixes the above issue. Signed-off-by: Liu Bo <bo.li.liu@oracle.com> Reviewed-by: David Sterba <dsterba@suse.cz> Signed-off-by: Chris Mason <clm@fb.com>
1 parent 8635eda commit 64c043d

File tree

5 files changed

+54
-29
lines changed

5 files changed

+54
-29
lines changed

fs/btrfs/backref.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -491,7 +491,9 @@ static int __add_missing_keys(struct btrfs_fs_info *fs_info,
491491
BUG_ON(!ref->wanted_disk_byte);
492492
eb = read_tree_block(fs_info->tree_root, ref->wanted_disk_byte,
493493
0);
494-
if (!eb || !extent_buffer_uptodate(eb)) {
494+
if (IS_ERR(eb)) {
495+
return PTR_ERR(eb);
496+
} else if (!extent_buffer_uptodate(eb)) {
495497
free_extent_buffer(eb);
496498
return -EIO;
497499
}
@@ -1034,7 +1036,10 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans,
10341036

10351037
eb = read_tree_block(fs_info->extent_root,
10361038
ref->parent, 0);
1037-
if (!eb || !extent_buffer_uptodate(eb)) {
1039+
if (IS_ERR(eb)) {
1040+
ret = PTR_ERR(eb);
1041+
goto out;
1042+
} else if (!extent_buffer_uptodate(eb)) {
10381043
free_extent_buffer(eb);
10391044
ret = -EIO;
10401045
goto out;

fs/btrfs/ctree.c

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1439,8 +1439,9 @@ get_old_root(struct btrfs_root *root, u64 time_seq)
14391439
btrfs_tree_read_unlock(eb_root);
14401440
free_extent_buffer(eb_root);
14411441
old = read_tree_block(root, logical, 0);
1442-
if (WARN_ON(!old || !extent_buffer_uptodate(old))) {
1443-
free_extent_buffer(old);
1442+
if (WARN_ON(IS_ERR(old) || !extent_buffer_uptodate(old))) {
1443+
if (!IS_ERR(old))
1444+
free_extent_buffer(old);
14441445
btrfs_warn(root->fs_info,
14451446
"failed to read tree block %llu from get_old_root", logical);
14461447
} else {
@@ -1685,7 +1686,9 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
16851686
if (!cur || !uptodate) {
16861687
if (!cur) {
16871688
cur = read_tree_block(root, blocknr, gen);
1688-
if (!cur || !extent_buffer_uptodate(cur)) {
1689+
if (IS_ERR(cur)) {
1690+
return PTR_ERR(cur);
1691+
} else if (!extent_buffer_uptodate(cur)) {
16891692
free_extent_buffer(cur);
16901693
return -EIO;
16911694
}
@@ -1864,8 +1867,9 @@ static noinline struct extent_buffer *read_node_slot(struct btrfs_root *root,
18641867

18651868
eb = read_tree_block(root, btrfs_node_blockptr(parent, slot),
18661869
btrfs_node_ptr_generation(parent, slot));
1867-
if (eb && !extent_buffer_uptodate(eb)) {
1868-
free_extent_buffer(eb);
1870+
if (IS_ERR(eb) || !extent_buffer_uptodate(eb)) {
1871+
if (!IS_ERR(eb))
1872+
free_extent_buffer(eb);
18691873
eb = NULL;
18701874
}
18711875

@@ -2494,7 +2498,7 @@ read_block_for_search(struct btrfs_trans_handle *trans,
24942498

24952499
ret = -EAGAIN;
24962500
tmp = read_tree_block(root, blocknr, 0);
2497-
if (tmp) {
2501+
if (!IS_ERR(tmp)) {
24982502
/*
24992503
* If the read above didn't mark this buffer up to date,
25002504
* it will never end up being up to date. Set ret to EIO now

fs/btrfs/disk-io.c

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1149,12 +1149,12 @@ struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr,
11491149

11501150
buf = btrfs_find_create_tree_block(root, bytenr);
11511151
if (!buf)
1152-
return NULL;
1152+
return ERR_PTR(-ENOMEM);
11531153

11541154
ret = btree_read_extent_buffer_pages(root, buf, 0, parent_transid);
11551155
if (ret) {
11561156
free_extent_buffer(buf);
1157-
return NULL;
1157+
return ERR_PTR(ret);
11581158
}
11591159
return buf;
11601160

@@ -1509,20 +1509,19 @@ static struct btrfs_root *btrfs_read_tree_root(struct btrfs_root *tree_root,
15091509
generation = btrfs_root_generation(&root->root_item);
15101510
root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item),
15111511
generation);
1512-
if (!root->node) {
1513-
ret = -ENOMEM;
1512+
if (IS_ERR(root->node)) {
1513+
ret = PTR_ERR(root->node);
15141514
goto find_fail;
15151515
} else if (!btrfs_buffer_uptodate(root->node, generation, 0)) {
15161516
ret = -EIO;
1517-
goto read_fail;
1517+
free_extent_buffer(root->node);
1518+
goto find_fail;
15181519
}
15191520
root->commit_root = btrfs_root_node(root);
15201521
out:
15211522
btrfs_free_path(path);
15221523
return root;
15231524

1524-
read_fail:
1525-
free_extent_buffer(root->node);
15261525
find_fail:
15271526
kfree(root);
15281527
alloc_fail:
@@ -2320,8 +2319,11 @@ static int btrfs_replay_log(struct btrfs_fs_info *fs_info,
23202319

23212320
log_tree_root->node = read_tree_block(tree_root, bytenr,
23222321
fs_info->generation + 1);
2323-
if (!log_tree_root->node ||
2324-
!extent_buffer_uptodate(log_tree_root->node)) {
2322+
if (IS_ERR(log_tree_root->node)) {
2323+
printk(KERN_ERR "BTRFS: failed to read log tree\n");
2324+
kfree(log_tree_root);
2325+
return PTR_ERR(log_tree_root->node);
2326+
} else if (!extent_buffer_uptodate(log_tree_root->node)) {
23252327
printk(KERN_ERR "BTRFS: failed to read log tree\n");
23262328
free_extent_buffer(log_tree_root->node);
23272329
kfree(log_tree_root);
@@ -2797,8 +2799,8 @@ int open_ctree(struct super_block *sb,
27972799
chunk_root->node = read_tree_block(chunk_root,
27982800
btrfs_super_chunk_root(disk_super),
27992801
generation);
2800-
if (!chunk_root->node ||
2801-
!test_bit(EXTENT_BUFFER_UPTODATE, &chunk_root->node->bflags)) {
2802+
if (IS_ERR(chunk_root->node) ||
2803+
!extent_buffer_uptodate(chunk_root->node)) {
28022804
printk(KERN_ERR "BTRFS: failed to read chunk root on %s\n",
28032805
sb->s_id);
28042806
goto fail_tree_roots;
@@ -2834,8 +2836,8 @@ int open_ctree(struct super_block *sb,
28342836
tree_root->node = read_tree_block(tree_root,
28352837
btrfs_super_root(disk_super),
28362838
generation);
2837-
if (!tree_root->node ||
2838-
!test_bit(EXTENT_BUFFER_UPTODATE, &tree_root->node->bflags)) {
2839+
if (IS_ERR(tree_root->node) ||
2840+
!extent_buffer_uptodate(tree_root->node)) {
28392841
printk(KERN_WARNING "BTRFS: failed to read tree root on %s\n",
28402842
sb->s_id);
28412843

fs/btrfs/extent-tree.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7979,9 +7979,12 @@ static int account_shared_subtree(struct btrfs_trans_handle *trans,
79797979
child_gen = btrfs_node_ptr_generation(eb, parent_slot);
79807980

79817981
eb = read_tree_block(root, child_bytenr, child_gen);
7982-
if (!eb || !extent_buffer_uptodate(eb)) {
7983-
ret = -EIO;
7982+
if (IS_ERR(eb)) {
7983+
ret = PTR_ERR(eb);
7984+
goto out;
7985+
} else if (!extent_buffer_uptodate(eb)) {
79847986
free_extent_buffer(eb);
7987+
ret = -EIO;
79857988
goto out;
79867989
}
79877990

@@ -8211,7 +8214,9 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans,
82118214
if (reada && level == 1)
82128215
reada_walk_down(trans, root, wc, path);
82138216
next = read_tree_block(root, bytenr, generation);
8214-
if (!next || !extent_buffer_uptodate(next)) {
8217+
if (IS_ERR(next)) {
8218+
return PTR_ERR(next);
8219+
} else if (!extent_buffer_uptodate(next)) {
82158220
free_extent_buffer(next);
82168221
return -EIO;
82178222
}

fs/btrfs/relocation.c

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1847,8 +1847,10 @@ int replace_path(struct btrfs_trans_handle *trans,
18471847
}
18481848

18491849
eb = read_tree_block(dest, old_bytenr, old_ptr_gen);
1850-
if (!eb || !extent_buffer_uptodate(eb)) {
1851-
ret = (!eb) ? -ENOMEM : -EIO;
1850+
if (IS_ERR(eb)) {
1851+
ret = PTR_ERR(eb);
1852+
} else if (!extent_buffer_uptodate(eb)) {
1853+
ret = -EIO;
18521854
free_extent_buffer(eb);
18531855
break;
18541856
}
@@ -2002,7 +2004,9 @@ int walk_down_reloc_tree(struct btrfs_root *root, struct btrfs_path *path,
20022004

20032005
bytenr = btrfs_node_blockptr(eb, path->slots[i]);
20042006
eb = read_tree_block(root, bytenr, ptr_gen);
2005-
if (!eb || !extent_buffer_uptodate(eb)) {
2007+
if (IS_ERR(eb)) {
2008+
return PTR_ERR(eb);
2009+
} else if (!extent_buffer_uptodate(eb)) {
20062010
free_extent_buffer(eb);
20072011
return -EIO;
20082012
}
@@ -2710,7 +2714,10 @@ static int do_relocation(struct btrfs_trans_handle *trans,
27102714
blocksize = root->nodesize;
27112715
generation = btrfs_node_ptr_generation(upper->eb, slot);
27122716
eb = read_tree_block(root, bytenr, generation);
2713-
if (!eb || !extent_buffer_uptodate(eb)) {
2717+
if (IS_ERR(eb)) {
2718+
err = PTR_ERR(eb);
2719+
goto next;
2720+
} else if (!extent_buffer_uptodate(eb)) {
27142721
free_extent_buffer(eb);
27152722
err = -EIO;
27162723
goto next;
@@ -2873,7 +2880,9 @@ static int get_tree_block_key(struct reloc_control *rc,
28732880
BUG_ON(block->key_ready);
28742881
eb = read_tree_block(rc->extent_root, block->bytenr,
28752882
block->key.offset);
2876-
if (!eb || !extent_buffer_uptodate(eb)) {
2883+
if (IS_ERR(eb)) {
2884+
return PTR_ERR(eb);
2885+
} else if (!extent_buffer_uptodate(eb)) {
28772886
free_extent_buffer(eb);
28782887
return -EIO;
28792888
}

0 commit comments

Comments
 (0)