diff options
author | Liu Bo <bo.li.liu@oracle.com> | 2015-05-25 05:30:15 -0400 |
---|---|---|
committer | Chris Mason <clm@fb.com> | 2015-06-03 07:03:08 -0400 |
commit | 64c043de466d5746e7ca306dab9d418cd871cefc (patch) | |
tree | fcce36cbfdc022f24b5b847152d6b17c967a1b64 | |
parent | 8635eda91ee11690bd8f73b2504ee19431fd6380 (diff) |
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>
-rw-r--r-- | fs/btrfs/backref.c | 9 | ||||
-rw-r--r-- | fs/btrfs/ctree.c | 16 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 28 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 11 | ||||
-rw-r--r-- | fs/btrfs/relocation.c | 19 |
5 files changed, 54 insertions, 29 deletions
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c index 614aaa1969bd..679dc97354be 100644 --- a/fs/btrfs/backref.c +++ b/fs/btrfs/backref.c | |||
@@ -491,7 +491,9 @@ static int __add_missing_keys(struct btrfs_fs_info *fs_info, | |||
491 | BUG_ON(!ref->wanted_disk_byte); | 491 | BUG_ON(!ref->wanted_disk_byte); |
492 | eb = read_tree_block(fs_info->tree_root, ref->wanted_disk_byte, | 492 | eb = read_tree_block(fs_info->tree_root, ref->wanted_disk_byte, |
493 | 0); | 493 | 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)) { | ||
495 | free_extent_buffer(eb); | 497 | free_extent_buffer(eb); |
496 | return -EIO; | 498 | return -EIO; |
497 | } | 499 | } |
@@ -1034,7 +1036,10 @@ again: | |||
1034 | 1036 | ||
1035 | eb = read_tree_block(fs_info->extent_root, | 1037 | eb = read_tree_block(fs_info->extent_root, |
1036 | ref->parent, 0); | 1038 | 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)) { | ||
1038 | free_extent_buffer(eb); | 1043 | free_extent_buffer(eb); |
1039 | ret = -EIO; | 1044 | ret = -EIO; |
1040 | goto out; | 1045 | goto out; |
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 0f11ebc92f02..54114b4887dd 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -1439,8 +1439,9 @@ get_old_root(struct btrfs_root *root, u64 time_seq) | |||
1439 | btrfs_tree_read_unlock(eb_root); | 1439 | btrfs_tree_read_unlock(eb_root); |
1440 | free_extent_buffer(eb_root); | 1440 | free_extent_buffer(eb_root); |
1441 | old = read_tree_block(root, logical, 0); | 1441 | old = read_tree_block(root, logical, 0); |
1442 | if (WARN_ON(!old || !extent_buffer_uptodate(old))) { | 1442 | if (WARN_ON(IS_ERR(old) || !extent_buffer_uptodate(old))) { |
1443 | free_extent_buffer(old); | 1443 | if (!IS_ERR(old)) |
1444 | free_extent_buffer(old); | ||
1444 | btrfs_warn(root->fs_info, | 1445 | btrfs_warn(root->fs_info, |
1445 | "failed to read tree block %llu from get_old_root", logical); | 1446 | "failed to read tree block %llu from get_old_root", logical); |
1446 | } else { | 1447 | } else { |
@@ -1685,7 +1686,9 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans, | |||
1685 | if (!cur || !uptodate) { | 1686 | if (!cur || !uptodate) { |
1686 | if (!cur) { | 1687 | if (!cur) { |
1687 | cur = read_tree_block(root, blocknr, gen); | 1688 | 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)) { | ||
1689 | free_extent_buffer(cur); | 1692 | free_extent_buffer(cur); |
1690 | return -EIO; | 1693 | return -EIO; |
1691 | } | 1694 | } |
@@ -1864,8 +1867,9 @@ static noinline struct extent_buffer *read_node_slot(struct btrfs_root *root, | |||
1864 | 1867 | ||
1865 | eb = read_tree_block(root, btrfs_node_blockptr(parent, slot), | 1868 | eb = read_tree_block(root, btrfs_node_blockptr(parent, slot), |
1866 | btrfs_node_ptr_generation(parent, slot)); | 1869 | btrfs_node_ptr_generation(parent, slot)); |
1867 | if (eb && !extent_buffer_uptodate(eb)) { | 1870 | if (IS_ERR(eb) || !extent_buffer_uptodate(eb)) { |
1868 | free_extent_buffer(eb); | 1871 | if (!IS_ERR(eb)) |
1872 | free_extent_buffer(eb); | ||
1869 | eb = NULL; | 1873 | eb = NULL; |
1870 | } | 1874 | } |
1871 | 1875 | ||
@@ -2494,7 +2498,7 @@ read_block_for_search(struct btrfs_trans_handle *trans, | |||
2494 | 2498 | ||
2495 | ret = -EAGAIN; | 2499 | ret = -EAGAIN; |
2496 | tmp = read_tree_block(root, blocknr, 0); | 2500 | tmp = read_tree_block(root, blocknr, 0); |
2497 | if (tmp) { | 2501 | if (!IS_ERR(tmp)) { |
2498 | /* | 2502 | /* |
2499 | * If the read above didn't mark this buffer up to date, | 2503 | * If the read above didn't mark this buffer up to date, |
2500 | * it will never end up being up to date. Set ret to EIO now | 2504 | * it will never end up being up to date. Set ret to EIO now |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 2ef9a4b72d06..7f8377871283 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -1149,12 +1149,12 @@ struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr, | |||
1149 | 1149 | ||
1150 | buf = btrfs_find_create_tree_block(root, bytenr); | 1150 | buf = btrfs_find_create_tree_block(root, bytenr); |
1151 | if (!buf) | 1151 | if (!buf) |
1152 | return NULL; | 1152 | return ERR_PTR(-ENOMEM); |
1153 | 1153 | ||
1154 | ret = btree_read_extent_buffer_pages(root, buf, 0, parent_transid); | 1154 | ret = btree_read_extent_buffer_pages(root, buf, 0, parent_transid); |
1155 | if (ret) { | 1155 | if (ret) { |
1156 | free_extent_buffer(buf); | 1156 | free_extent_buffer(buf); |
1157 | return NULL; | 1157 | return ERR_PTR(ret); |
1158 | } | 1158 | } |
1159 | return buf; | 1159 | return buf; |
1160 | 1160 | ||
@@ -1509,20 +1509,19 @@ static struct btrfs_root *btrfs_read_tree_root(struct btrfs_root *tree_root, | |||
1509 | generation = btrfs_root_generation(&root->root_item); | 1509 | generation = btrfs_root_generation(&root->root_item); |
1510 | root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item), | 1510 | root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item), |
1511 | generation); | 1511 | generation); |
1512 | if (!root->node) { | 1512 | if (IS_ERR(root->node)) { |
1513 | ret = -ENOMEM; | 1513 | ret = PTR_ERR(root->node); |
1514 | goto find_fail; | 1514 | goto find_fail; |
1515 | } else if (!btrfs_buffer_uptodate(root->node, generation, 0)) { | 1515 | } else if (!btrfs_buffer_uptodate(root->node, generation, 0)) { |
1516 | ret = -EIO; | 1516 | ret = -EIO; |
1517 | goto read_fail; | 1517 | free_extent_buffer(root->node); |
1518 | goto find_fail; | ||
1518 | } | 1519 | } |
1519 | root->commit_root = btrfs_root_node(root); | 1520 | root->commit_root = btrfs_root_node(root); |
1520 | out: | 1521 | out: |
1521 | btrfs_free_path(path); | 1522 | btrfs_free_path(path); |
1522 | return root; | 1523 | return root; |
1523 | 1524 | ||
1524 | read_fail: | ||
1525 | free_extent_buffer(root->node); | ||
1526 | find_fail: | 1525 | find_fail: |
1527 | kfree(root); | 1526 | kfree(root); |
1528 | alloc_fail: | 1527 | alloc_fail: |
@@ -2320,8 +2319,11 @@ static int btrfs_replay_log(struct btrfs_fs_info *fs_info, | |||
2320 | 2319 | ||
2321 | log_tree_root->node = read_tree_block(tree_root, bytenr, | 2320 | log_tree_root->node = read_tree_block(tree_root, bytenr, |
2322 | fs_info->generation + 1); | 2321 | fs_info->generation + 1); |
2323 | if (!log_tree_root->node || | 2322 | if (IS_ERR(log_tree_root->node)) { |
2324 | !extent_buffer_uptodate(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)) { | ||
2325 | printk(KERN_ERR "BTRFS: failed to read log tree\n"); | 2327 | printk(KERN_ERR "BTRFS: failed to read log tree\n"); |
2326 | free_extent_buffer(log_tree_root->node); | 2328 | free_extent_buffer(log_tree_root->node); |
2327 | kfree(log_tree_root); | 2329 | kfree(log_tree_root); |
@@ -2797,8 +2799,8 @@ int open_ctree(struct super_block *sb, | |||
2797 | chunk_root->node = read_tree_block(chunk_root, | 2799 | chunk_root->node = read_tree_block(chunk_root, |
2798 | btrfs_super_chunk_root(disk_super), | 2800 | btrfs_super_chunk_root(disk_super), |
2799 | generation); | 2801 | generation); |
2800 | if (!chunk_root->node || | 2802 | if (IS_ERR(chunk_root->node) || |
2801 | !test_bit(EXTENT_BUFFER_UPTODATE, &chunk_root->node->bflags)) { | 2803 | !extent_buffer_uptodate(chunk_root->node)) { |
2802 | printk(KERN_ERR "BTRFS: failed to read chunk root on %s\n", | 2804 | printk(KERN_ERR "BTRFS: failed to read chunk root on %s\n", |
2803 | sb->s_id); | 2805 | sb->s_id); |
2804 | goto fail_tree_roots; | 2806 | goto fail_tree_roots; |
@@ -2834,8 +2836,8 @@ retry_root_backup: | |||
2834 | tree_root->node = read_tree_block(tree_root, | 2836 | tree_root->node = read_tree_block(tree_root, |
2835 | btrfs_super_root(disk_super), | 2837 | btrfs_super_root(disk_super), |
2836 | generation); | 2838 | generation); |
2837 | if (!tree_root->node || | 2839 | if (IS_ERR(tree_root->node) || |
2838 | !test_bit(EXTENT_BUFFER_UPTODATE, &tree_root->node->bflags)) { | 2840 | !extent_buffer_uptodate(tree_root->node)) { |
2839 | printk(KERN_WARNING "BTRFS: failed to read tree root on %s\n", | 2841 | printk(KERN_WARNING "BTRFS: failed to read tree root on %s\n", |
2840 | sb->s_id); | 2842 | sb->s_id); |
2841 | 2843 | ||
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 076fd7484a82..f1d1216f7feb 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -7979,9 +7979,12 @@ walk_down: | |||
7979 | child_gen = btrfs_node_ptr_generation(eb, parent_slot); | 7979 | child_gen = btrfs_node_ptr_generation(eb, parent_slot); |
7980 | 7980 | ||
7981 | eb = read_tree_block(root, child_bytenr, child_gen); | 7981 | eb = read_tree_block(root, child_bytenr, child_gen); |
7982 | if (!eb || !extent_buffer_uptodate(eb)) { | 7982 | if (IS_ERR(eb)) { |
7983 | ret = -EIO; | 7983 | ret = PTR_ERR(eb); |
7984 | goto out; | ||
7985 | } else if (!extent_buffer_uptodate(eb)) { | ||
7984 | free_extent_buffer(eb); | 7986 | free_extent_buffer(eb); |
7987 | ret = -EIO; | ||
7985 | goto out; | 7988 | goto out; |
7986 | } | 7989 | } |
7987 | 7990 | ||
@@ -8211,7 +8214,9 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans, | |||
8211 | if (reada && level == 1) | 8214 | if (reada && level == 1) |
8212 | reada_walk_down(trans, root, wc, path); | 8215 | reada_walk_down(trans, root, wc, path); |
8213 | next = read_tree_block(root, bytenr, generation); | 8216 | 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)) { | ||
8215 | free_extent_buffer(next); | 8220 | free_extent_buffer(next); |
8216 | return -EIO; | 8221 | return -EIO; |
8217 | } | 8222 | } |
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index 74b24b01d574..827951fbf7fc 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c | |||
@@ -1847,8 +1847,10 @@ again: | |||
1847 | } | 1847 | } |
1848 | 1848 | ||
1849 | eb = read_tree_block(dest, old_bytenr, old_ptr_gen); | 1849 | eb = read_tree_block(dest, old_bytenr, old_ptr_gen); |
1850 | if (!eb || !extent_buffer_uptodate(eb)) { | 1850 | if (IS_ERR(eb)) { |
1851 | ret = (!eb) ? -ENOMEM : -EIO; | 1851 | ret = PTR_ERR(eb); |
1852 | } else if (!extent_buffer_uptodate(eb)) { | ||
1853 | ret = -EIO; | ||
1852 | free_extent_buffer(eb); | 1854 | free_extent_buffer(eb); |
1853 | break; | 1855 | break; |
1854 | } | 1856 | } |
@@ -2002,7 +2004,9 @@ int walk_down_reloc_tree(struct btrfs_root *root, struct btrfs_path *path, | |||
2002 | 2004 | ||
2003 | bytenr = btrfs_node_blockptr(eb, path->slots[i]); | 2005 | bytenr = btrfs_node_blockptr(eb, path->slots[i]); |
2004 | eb = read_tree_block(root, bytenr, ptr_gen); | 2006 | 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)) { | ||
2006 | free_extent_buffer(eb); | 2010 | free_extent_buffer(eb); |
2007 | return -EIO; | 2011 | return -EIO; |
2008 | } | 2012 | } |
@@ -2710,7 +2714,10 @@ static int do_relocation(struct btrfs_trans_handle *trans, | |||
2710 | blocksize = root->nodesize; | 2714 | blocksize = root->nodesize; |
2711 | generation = btrfs_node_ptr_generation(upper->eb, slot); | 2715 | generation = btrfs_node_ptr_generation(upper->eb, slot); |
2712 | eb = read_tree_block(root, bytenr, generation); | 2716 | 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)) { | ||
2714 | free_extent_buffer(eb); | 2721 | free_extent_buffer(eb); |
2715 | err = -EIO; | 2722 | err = -EIO; |
2716 | goto next; | 2723 | goto next; |
@@ -2873,7 +2880,9 @@ static int get_tree_block_key(struct reloc_control *rc, | |||
2873 | BUG_ON(block->key_ready); | 2880 | BUG_ON(block->key_ready); |
2874 | eb = read_tree_block(rc->extent_root, block->bytenr, | 2881 | eb = read_tree_block(rc->extent_root, block->bytenr, |
2875 | block->key.offset); | 2882 | 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)) { | ||
2877 | free_extent_buffer(eb); | 2886 | free_extent_buffer(eb); |
2878 | return -EIO; | 2887 | return -EIO; |
2879 | } | 2888 | } |