diff options
| author | Theodore Ts'o <tytso@mit.edu> | 2013-01-12 16:19:36 -0500 |
|---|---|---|
| committer | Theodore Ts'o <tytso@mit.edu> | 2013-01-12 16:19:36 -0500 |
| commit | 860d21e2c585f7ee8a4ecc06f474fdc33c9474f4 (patch) | |
| tree | f4b8f664599f043b7aa7b86a9a135aa275f0a5e2 /fs/ext4 | |
| parent | 9931faca02c604c22335f5a935a501bb2ace6e20 (diff) | |
ext4: return ENOMEM if sb_getblk() fails
The only reason for sb_getblk() failing is if it can't allocate the
buffer_head. So ENOMEM is more appropriate than EIO. In addition,
make sure that the file system is marked as being inconsistent if
sb_getblk() fails.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Cc: stable@vger.kernel.org
Diffstat (limited to 'fs/ext4')
| -rw-r--r-- | fs/ext4/extents.c | 25 | ||||
| -rw-r--r-- | fs/ext4/indirect.c | 9 | ||||
| -rw-r--r-- | fs/ext4/inline.c | 2 | ||||
| -rw-r--r-- | fs/ext4/inode.c | 9 | ||||
| -rw-r--r-- | fs/ext4/mmp.c | 2 | ||||
| -rw-r--r-- | fs/ext4/resize.c | 8 | ||||
| -rw-r--r-- | fs/ext4/xattr.c | 3 |
7 files changed, 32 insertions, 26 deletions
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 5ae1674ec12f..d42a8c49ad69 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
| @@ -725,6 +725,7 @@ ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block, | |||
| 725 | struct ext4_extent_header *eh; | 725 | struct ext4_extent_header *eh; |
| 726 | struct buffer_head *bh; | 726 | struct buffer_head *bh; |
| 727 | short int depth, i, ppos = 0, alloc = 0; | 727 | short int depth, i, ppos = 0, alloc = 0; |
| 728 | int ret; | ||
| 728 | 729 | ||
| 729 | eh = ext_inode_hdr(inode); | 730 | eh = ext_inode_hdr(inode); |
| 730 | depth = ext_depth(inode); | 731 | depth = ext_depth(inode); |
| @@ -752,12 +753,15 @@ ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block, | |||
| 752 | path[ppos].p_ext = NULL; | 753 | path[ppos].p_ext = NULL; |
| 753 | 754 | ||
| 754 | bh = sb_getblk(inode->i_sb, path[ppos].p_block); | 755 | bh = sb_getblk(inode->i_sb, path[ppos].p_block); |
| 755 | if (unlikely(!bh)) | 756 | if (unlikely(!bh)) { |
| 757 | ret = -ENOMEM; | ||
| 756 | goto err; | 758 | goto err; |
| 759 | } | ||
| 757 | if (!bh_uptodate_or_lock(bh)) { | 760 | if (!bh_uptodate_or_lock(bh)) { |
| 758 | trace_ext4_ext_load_extent(inode, block, | 761 | trace_ext4_ext_load_extent(inode, block, |
| 759 | path[ppos].p_block); | 762 | path[ppos].p_block); |
| 760 | if (bh_submit_read(bh) < 0) { | 763 | ret = bh_submit_read(bh); |
| 764 | if (ret < 0) { | ||
| 761 | put_bh(bh); | 765 | put_bh(bh); |
| 762 | goto err; | 766 | goto err; |
| 763 | } | 767 | } |
| @@ -768,13 +772,15 @@ ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block, | |||
| 768 | put_bh(bh); | 772 | put_bh(bh); |
| 769 | EXT4_ERROR_INODE(inode, | 773 | EXT4_ERROR_INODE(inode, |
| 770 | "ppos %d > depth %d", ppos, depth); | 774 | "ppos %d > depth %d", ppos, depth); |
| 775 | ret = -EIO; | ||
| 771 | goto err; | 776 | goto err; |
| 772 | } | 777 | } |
| 773 | path[ppos].p_bh = bh; | 778 | path[ppos].p_bh = bh; |
| 774 | path[ppos].p_hdr = eh; | 779 | path[ppos].p_hdr = eh; |
| 775 | i--; | 780 | i--; |
| 776 | 781 | ||
| 777 | if (ext4_ext_check_block(inode, eh, i, bh)) | 782 | ret = ext4_ext_check_block(inode, eh, i, bh); |
| 783 | if (ret < 0) | ||
| 778 | goto err; | 784 | goto err; |
| 779 | } | 785 | } |
| 780 | 786 | ||
| @@ -796,7 +802,7 @@ err: | |||
| 796 | ext4_ext_drop_refs(path); | 802 | ext4_ext_drop_refs(path); |
| 797 | if (alloc) | 803 | if (alloc) |
| 798 | kfree(path); | 804 | kfree(path); |
| 799 | return ERR_PTR(-EIO); | 805 | return ERR_PTR(ret); |
| 800 | } | 806 | } |
| 801 | 807 | ||
| 802 | /* | 808 | /* |
| @@ -951,7 +957,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode, | |||
| 951 | } | 957 | } |
| 952 | bh = sb_getblk(inode->i_sb, newblock); | 958 | bh = sb_getblk(inode->i_sb, newblock); |
| 953 | if (!bh) { | 959 | if (!bh) { |
| 954 | err = -EIO; | 960 | err = -ENOMEM; |
| 955 | goto cleanup; | 961 | goto cleanup; |
| 956 | } | 962 | } |
| 957 | lock_buffer(bh); | 963 | lock_buffer(bh); |
| @@ -1024,7 +1030,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode, | |||
| 1024 | newblock = ablocks[--a]; | 1030 | newblock = ablocks[--a]; |
| 1025 | bh = sb_getblk(inode->i_sb, newblock); | 1031 | bh = sb_getblk(inode->i_sb, newblock); |
| 1026 | if (!bh) { | 1032 | if (!bh) { |
| 1027 | err = -EIO; | 1033 | err = -ENOMEM; |
| 1028 | goto cleanup; | 1034 | goto cleanup; |
| 1029 | } | 1035 | } |
| 1030 | lock_buffer(bh); | 1036 | lock_buffer(bh); |
| @@ -1136,11 +1142,8 @@ static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode, | |||
| 1136 | return err; | 1142 | return err; |
| 1137 | 1143 | ||
| 1138 | bh = sb_getblk(inode->i_sb, newblock); | 1144 | bh = sb_getblk(inode->i_sb, newblock); |
| 1139 | if (!bh) { | 1145 | if (!bh) |
| 1140 | err = -EIO; | 1146 | return -ENOMEM; |
| 1141 | ext4_std_error(inode->i_sb, err); | ||
| 1142 | return err; | ||
| 1143 | } | ||
| 1144 | lock_buffer(bh); | 1147 | lock_buffer(bh); |
| 1145 | 1148 | ||
| 1146 | err = ext4_journal_get_create_access(handle, bh); | 1149 | err = ext4_journal_get_create_access(handle, bh); |
diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c index 20862f96e8ae..8d83d1e508e4 100644 --- a/fs/ext4/indirect.c +++ b/fs/ext4/indirect.c | |||
| @@ -146,6 +146,7 @@ static Indirect *ext4_get_branch(struct inode *inode, int depth, | |||
| 146 | struct super_block *sb = inode->i_sb; | 146 | struct super_block *sb = inode->i_sb; |
| 147 | Indirect *p = chain; | 147 | Indirect *p = chain; |
| 148 | struct buffer_head *bh; | 148 | struct buffer_head *bh; |
| 149 | int ret = -EIO; | ||
| 149 | 150 | ||
| 150 | *err = 0; | 151 | *err = 0; |
| 151 | /* i_data is not going away, no lock needed */ | 152 | /* i_data is not going away, no lock needed */ |
| @@ -154,8 +155,10 @@ static Indirect *ext4_get_branch(struct inode *inode, int depth, | |||
| 154 | goto no_block; | 155 | goto no_block; |
| 155 | while (--depth) { | 156 | while (--depth) { |
| 156 | bh = sb_getblk(sb, le32_to_cpu(p->key)); | 157 | bh = sb_getblk(sb, le32_to_cpu(p->key)); |
| 157 | if (unlikely(!bh)) | 158 | if (unlikely(!bh)) { |
| 159 | ret = -ENOMEM; | ||
| 158 | goto failure; | 160 | goto failure; |
| 161 | } | ||
| 159 | 162 | ||
| 160 | if (!bh_uptodate_or_lock(bh)) { | 163 | if (!bh_uptodate_or_lock(bh)) { |
| 161 | if (bh_submit_read(bh) < 0) { | 164 | if (bh_submit_read(bh) < 0) { |
| @@ -177,7 +180,7 @@ static Indirect *ext4_get_branch(struct inode *inode, int depth, | |||
| 177 | return NULL; | 180 | return NULL; |
| 178 | 181 | ||
| 179 | failure: | 182 | failure: |
| 180 | *err = -EIO; | 183 | *err = ret; |
| 181 | no_block: | 184 | no_block: |
| 182 | return p; | 185 | return p; |
| 183 | } | 186 | } |
| @@ -471,7 +474,7 @@ static int ext4_alloc_branch(handle_t *handle, struct inode *inode, | |||
| 471 | */ | 474 | */ |
| 472 | bh = sb_getblk(inode->i_sb, new_blocks[n-1]); | 475 | bh = sb_getblk(inode->i_sb, new_blocks[n-1]); |
| 473 | if (unlikely(!bh)) { | 476 | if (unlikely(!bh)) { |
| 474 | err = -EIO; | 477 | err = -ENOMEM; |
| 475 | goto failed; | 478 | goto failed; |
| 476 | } | 479 | } |
| 477 | 480 | ||
diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c index 387c47c6cda9..93a3408fc89b 100644 --- a/fs/ext4/inline.c +++ b/fs/ext4/inline.c | |||
| @@ -1188,7 +1188,7 @@ static int ext4_convert_inline_data_nolock(handle_t *handle, | |||
| 1188 | 1188 | ||
| 1189 | data_bh = sb_getblk(inode->i_sb, map.m_pblk); | 1189 | data_bh = sb_getblk(inode->i_sb, map.m_pblk); |
| 1190 | if (!data_bh) { | 1190 | if (!data_bh) { |
| 1191 | error = -EIO; | 1191 | error = -ENOMEM; |
| 1192 | goto out_restore; | 1192 | goto out_restore; |
| 1193 | } | 1193 | } |
| 1194 | 1194 | ||
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index cbfe13bf5b2a..9ccc140b82d2 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
| @@ -714,7 +714,7 @@ struct buffer_head *ext4_getblk(handle_t *handle, struct inode *inode, | |||
| 714 | 714 | ||
| 715 | bh = sb_getblk(inode->i_sb, map.m_pblk); | 715 | bh = sb_getblk(inode->i_sb, map.m_pblk); |
| 716 | if (!bh) { | 716 | if (!bh) { |
| 717 | *errp = -EIO; | 717 | *errp = -ENOMEM; |
| 718 | return NULL; | 718 | return NULL; |
| 719 | } | 719 | } |
| 720 | if (map.m_flags & EXT4_MAP_NEW) { | 720 | if (map.m_flags & EXT4_MAP_NEW) { |
| @@ -3660,11 +3660,8 @@ static int __ext4_get_inode_loc(struct inode *inode, | |||
| 3660 | iloc->offset = (inode_offset % inodes_per_block) * EXT4_INODE_SIZE(sb); | 3660 | iloc->offset = (inode_offset % inodes_per_block) * EXT4_INODE_SIZE(sb); |
| 3661 | 3661 | ||
| 3662 | bh = sb_getblk(sb, block); | 3662 | bh = sb_getblk(sb, block); |
| 3663 | if (!bh) { | 3663 | if (!bh) |
| 3664 | EXT4_ERROR_INODE_BLOCK(inode, block, | 3664 | return -ENOMEM; |
| 3665 | "unable to read itable block"); | ||
| 3666 | return -EIO; | ||
| 3667 | } | ||
| 3668 | if (!buffer_uptodate(bh)) { | 3665 | if (!buffer_uptodate(bh)) { |
| 3669 | lock_buffer(bh); | 3666 | lock_buffer(bh); |
| 3670 | 3667 | ||
diff --git a/fs/ext4/mmp.c b/fs/ext4/mmp.c index fe7c63f4717e..44734f1ca554 100644 --- a/fs/ext4/mmp.c +++ b/fs/ext4/mmp.c | |||
| @@ -80,6 +80,8 @@ static int read_mmp_block(struct super_block *sb, struct buffer_head **bh, | |||
| 80 | * is not blocked in the elevator. */ | 80 | * is not blocked in the elevator. */ |
| 81 | if (!*bh) | 81 | if (!*bh) |
| 82 | *bh = sb_getblk(sb, mmp_block); | 82 | *bh = sb_getblk(sb, mmp_block); |
| 83 | if (!*bh) | ||
| 84 | return -ENOMEM; | ||
| 83 | if (*bh) { | 85 | if (*bh) { |
| 84 | get_bh(*bh); | 86 | get_bh(*bh); |
| 85 | lock_buffer(*bh); | 87 | lock_buffer(*bh); |
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index d99387b89edd..02824dc2ff3b 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c | |||
| @@ -334,7 +334,7 @@ static struct buffer_head *bclean(handle_t *handle, struct super_block *sb, | |||
| 334 | 334 | ||
| 335 | bh = sb_getblk(sb, blk); | 335 | bh = sb_getblk(sb, blk); |
| 336 | if (!bh) | 336 | if (!bh) |
| 337 | return ERR_PTR(-EIO); | 337 | return ERR_PTR(-ENOMEM); |
| 338 | if ((err = ext4_journal_get_write_access(handle, bh))) { | 338 | if ((err = ext4_journal_get_write_access(handle, bh))) { |
| 339 | brelse(bh); | 339 | brelse(bh); |
| 340 | bh = ERR_PTR(err); | 340 | bh = ERR_PTR(err); |
| @@ -411,7 +411,7 @@ static int set_flexbg_block_bitmap(struct super_block *sb, handle_t *handle, | |||
| 411 | 411 | ||
| 412 | bh = sb_getblk(sb, flex_gd->groups[group].block_bitmap); | 412 | bh = sb_getblk(sb, flex_gd->groups[group].block_bitmap); |
| 413 | if (!bh) | 413 | if (!bh) |
| 414 | return -EIO; | 414 | return -ENOMEM; |
| 415 | 415 | ||
| 416 | err = ext4_journal_get_write_access(handle, bh); | 416 | err = ext4_journal_get_write_access(handle, bh); |
| 417 | if (err) | 417 | if (err) |
| @@ -501,7 +501,7 @@ static int setup_new_flex_group_blocks(struct super_block *sb, | |||
| 501 | 501 | ||
| 502 | gdb = sb_getblk(sb, block); | 502 | gdb = sb_getblk(sb, block); |
| 503 | if (!gdb) { | 503 | if (!gdb) { |
| 504 | err = -EIO; | 504 | err = -ENOMEM; |
| 505 | goto out; | 505 | goto out; |
| 506 | } | 506 | } |
| 507 | 507 | ||
| @@ -1065,7 +1065,7 @@ static void update_backups(struct super_block *sb, int blk_off, char *data, | |||
| 1065 | 1065 | ||
| 1066 | bh = sb_getblk(sb, backup_block); | 1066 | bh = sb_getblk(sb, backup_block); |
| 1067 | if (!bh) { | 1067 | if (!bh) { |
| 1068 | err = -EIO; | 1068 | err = -ENOMEM; |
| 1069 | break; | 1069 | break; |
| 1070 | } | 1070 | } |
| 1071 | ext4_debug("update metadata backup %llu(+%llu)\n", | 1071 | ext4_debug("update metadata backup %llu(+%llu)\n", |
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index 3a91ebc2b66f..07d684a4e523 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c | |||
| @@ -887,16 +887,17 @@ inserted: | |||
| 887 | 887 | ||
| 888 | new_bh = sb_getblk(sb, block); | 888 | new_bh = sb_getblk(sb, block); |
| 889 | if (!new_bh) { | 889 | if (!new_bh) { |
| 890 | error = -ENOMEM; | ||
| 890 | getblk_failed: | 891 | getblk_failed: |
| 891 | ext4_free_blocks(handle, inode, NULL, block, 1, | 892 | ext4_free_blocks(handle, inode, NULL, block, 1, |
| 892 | EXT4_FREE_BLOCKS_METADATA); | 893 | EXT4_FREE_BLOCKS_METADATA); |
| 893 | error = -EIO; | ||
| 894 | goto cleanup; | 894 | goto cleanup; |
| 895 | } | 895 | } |
| 896 | lock_buffer(new_bh); | 896 | lock_buffer(new_bh); |
| 897 | error = ext4_journal_get_create_access(handle, new_bh); | 897 | error = ext4_journal_get_create_access(handle, new_bh); |
| 898 | if (error) { | 898 | if (error) { |
| 899 | unlock_buffer(new_bh); | 899 | unlock_buffer(new_bh); |
| 900 | error = -EIO; | ||
| 900 | goto getblk_failed; | 901 | goto getblk_failed; |
| 901 | } | 902 | } |
| 902 | memcpy(new_bh->b_data, s->base, new_bh->b_size); | 903 | memcpy(new_bh->b_data, s->base, new_bh->b_size); |
