Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

+32 -26
+14 -11
fs/ext4/extents.c
··· 725 725 struct ext4_extent_header *eh; 726 726 struct buffer_head *bh; 727 727 short int depth, i, ppos = 0, alloc = 0; 728 + int ret; 728 729 729 730 eh = ext_inode_hdr(inode); 730 731 depth = ext_depth(inode); ··· 753 752 path[ppos].p_ext = NULL; 754 753 755 754 bh = sb_getblk(inode->i_sb, path[ppos].p_block); 756 - if (unlikely(!bh)) 755 + if (unlikely(!bh)) { 756 + ret = -ENOMEM; 757 757 goto err; 758 + } 758 759 if (!bh_uptodate_or_lock(bh)) { 759 760 trace_ext4_ext_load_extent(inode, block, 760 761 path[ppos].p_block); 761 - if (bh_submit_read(bh) < 0) { 762 + ret = bh_submit_read(bh); 763 + if (ret < 0) { 762 764 put_bh(bh); 763 765 goto err; 764 766 } ··· 772 768 put_bh(bh); 773 769 EXT4_ERROR_INODE(inode, 774 770 "ppos %d > depth %d", ppos, depth); 771 + ret = -EIO; 775 772 goto err; 776 773 } 777 774 path[ppos].p_bh = bh; 778 775 path[ppos].p_hdr = eh; 779 776 i--; 780 777 781 - if (ext4_ext_check_block(inode, eh, i, bh)) 778 + ret = ext4_ext_check_block(inode, eh, i, bh); 779 + if (ret < 0) 782 780 goto err; 783 781 } 784 782 ··· 802 796 ext4_ext_drop_refs(path); 803 797 if (alloc) 804 798 kfree(path); 805 - return ERR_PTR(-EIO); 799 + return ERR_PTR(ret); 806 800 } 807 801 808 802 /* ··· 957 951 } 958 952 bh = sb_getblk(inode->i_sb, newblock); 959 953 if (!bh) { 960 - err = -EIO; 954 + err = -ENOMEM; 961 955 goto cleanup; 962 956 } 963 957 lock_buffer(bh); ··· 1030 1024 newblock = ablocks[--a]; 1031 1025 bh = sb_getblk(inode->i_sb, newblock); 1032 1026 if (!bh) { 1033 - err = -EIO; 1027 + err = -ENOMEM; 1034 1028 goto cleanup; 1035 1029 } 1036 1030 lock_buffer(bh); ··· 1142 1136 return err; 1143 1137 1144 1138 bh = sb_getblk(inode->i_sb, newblock); 1145 - if (!bh) { 1146 - err = -EIO; 1147 - ext4_std_error(inode->i_sb, err); 1148 - return err; 1149 - } 1139 + if (!bh) 1140 + return -ENOMEM; 1150 1141 lock_buffer(bh); 1151 1142 1152 1143 err = ext4_journal_get_create_access(handle, bh);
+6 -3
fs/ext4/indirect.c
··· 146 146 struct super_block *sb = inode->i_sb; 147 147 Indirect *p = chain; 148 148 struct buffer_head *bh; 149 + int ret = -EIO; 149 150 150 151 *err = 0; 151 152 /* i_data is not going away, no lock needed */ ··· 155 154 goto no_block; 156 155 while (--depth) { 157 156 bh = sb_getblk(sb, le32_to_cpu(p->key)); 158 - if (unlikely(!bh)) 157 + if (unlikely(!bh)) { 158 + ret = -ENOMEM; 159 159 goto failure; 160 + } 160 161 161 162 if (!bh_uptodate_or_lock(bh)) { 162 163 if (bh_submit_read(bh) < 0) { ··· 180 177 return NULL; 181 178 182 179 failure: 183 - *err = -EIO; 180 + *err = ret; 184 181 no_block: 185 182 return p; 186 183 } ··· 474 471 */ 475 472 bh = sb_getblk(inode->i_sb, new_blocks[n-1]); 476 473 if (unlikely(!bh)) { 477 - err = -EIO; 474 + err = -ENOMEM; 478 475 goto failed; 479 476 } 480 477
+1 -1
fs/ext4/inline.c
··· 1188 1188 1189 1189 data_bh = sb_getblk(inode->i_sb, map.m_pblk); 1190 1190 if (!data_bh) { 1191 - error = -EIO; 1191 + error = -ENOMEM; 1192 1192 goto out_restore; 1193 1193 } 1194 1194
+3 -6
fs/ext4/inode.c
··· 714 714 715 715 bh = sb_getblk(inode->i_sb, map.m_pblk); 716 716 if (!bh) { 717 - *errp = -EIO; 717 + *errp = -ENOMEM; 718 718 return NULL; 719 719 } 720 720 if (map.m_flags & EXT4_MAP_NEW) { ··· 3660 3660 iloc->offset = (inode_offset % inodes_per_block) * EXT4_INODE_SIZE(sb); 3661 3661 3662 3662 bh = sb_getblk(sb, block); 3663 - if (!bh) { 3664 - EXT4_ERROR_INODE_BLOCK(inode, block, 3665 - "unable to read itable block"); 3666 - return -EIO; 3667 - } 3663 + if (!bh) 3664 + return -ENOMEM; 3668 3665 if (!buffer_uptodate(bh)) { 3669 3666 lock_buffer(bh); 3670 3667
+2
fs/ext4/mmp.c
··· 80 80 * is not blocked in the elevator. */ 81 81 if (!*bh) 82 82 *bh = sb_getblk(sb, mmp_block); 83 + if (!*bh) 84 + return -ENOMEM; 83 85 if (*bh) { 84 86 get_bh(*bh); 85 87 lock_buffer(*bh);
+4 -4
fs/ext4/resize.c
··· 334 334 335 335 bh = sb_getblk(sb, blk); 336 336 if (!bh) 337 - return ERR_PTR(-EIO); 337 + return ERR_PTR(-ENOMEM); 338 338 if ((err = ext4_journal_get_write_access(handle, bh))) { 339 339 brelse(bh); 340 340 bh = ERR_PTR(err); ··· 411 411 412 412 bh = sb_getblk(sb, flex_gd->groups[group].block_bitmap); 413 413 if (!bh) 414 - return -EIO; 414 + return -ENOMEM; 415 415 416 416 err = ext4_journal_get_write_access(handle, bh); 417 417 if (err) ··· 501 501 502 502 gdb = sb_getblk(sb, block); 503 503 if (!gdb) { 504 - err = -EIO; 504 + err = -ENOMEM; 505 505 goto out; 506 506 } 507 507 ··· 1065 1065 1066 1066 bh = sb_getblk(sb, backup_block); 1067 1067 if (!bh) { 1068 - err = -EIO; 1068 + err = -ENOMEM; 1069 1069 break; 1070 1070 } 1071 1071 ext4_debug("update metadata backup %llu(+%llu)\n",
+2 -1
fs/ext4/xattr.c
··· 887 887 888 888 new_bh = sb_getblk(sb, block); 889 889 if (!new_bh) { 890 + error = -ENOMEM; 890 891 getblk_failed: 891 892 ext4_free_blocks(handle, inode, NULL, block, 1, 892 893 EXT4_FREE_BLOCKS_METADATA); 893 - error = -EIO; 894 894 goto cleanup; 895 895 } 896 896 lock_buffer(new_bh); 897 897 error = ext4_journal_get_create_access(handle, new_bh); 898 898 if (error) { 899 899 unlock_buffer(new_bh); 900 + error = -EIO; 900 901 goto getblk_failed; 901 902 } 902 903 memcpy(new_bh->b_data, s->base, new_bh->b_size);