aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/ialloc.c
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2015-10-17 21:33:24 -0400
committerTheodore Ts'o <tytso@mit.edu>2015-10-17 21:33:24 -0400
commit9008a58e5dcee014f5de69d154e2620870f9224e (patch)
tree0959450c94f921c0080a5f9ee2f62e3ea9bfcf6e /fs/ext4/ialloc.c
parent56316a0d28f251dae6a3bc2b6d50e7c25389871f (diff)
ext4: make the bitmap read routines return real error codes
Make the bitmap reaading routines return real error codes (EIO, EFSCORRUPTED, EFSBADCRC) which can then be reflected back to userspace for more precise diagnosis work. In particular, this means that mballoc no longer claims that we're out of memory if the block bitmaps become corrupt. Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/ialloc.c')
-rw-r--r--fs/ext4/ialloc.c108
1 files changed, 72 insertions, 36 deletions
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index 0d7f06ed7ee2..1b8024d26f65 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -64,7 +64,7 @@ void ext4_mark_bitmap_end(int start_bit, int end_bit, char *bitmap)
64} 64}
65 65
66/* Initializes an uninitialized inode bitmap */ 66/* Initializes an uninitialized inode bitmap */
67static unsigned ext4_init_inode_bitmap(struct super_block *sb, 67static int ext4_init_inode_bitmap(struct super_block *sb,
68 struct buffer_head *bh, 68 struct buffer_head *bh,
69 ext4_group_t block_group, 69 ext4_group_t block_group,
70 struct ext4_group_desc *gdp) 70 struct ext4_group_desc *gdp)
@@ -89,7 +89,7 @@ static unsigned ext4_init_inode_bitmap(struct super_block *sb,
89 count); 89 count);
90 } 90 }
91 set_bit(EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT, &grp->bb_state); 91 set_bit(EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT, &grp->bb_state);
92 return 0; 92 return -EFSBADCRC;
93 } 93 }
94 94
95 memset(bh->b_data, 0, (EXT4_INODES_PER_GROUP(sb) + 7) / 8); 95 memset(bh->b_data, 0, (EXT4_INODES_PER_GROUP(sb) + 7) / 8);
@@ -99,7 +99,7 @@ static unsigned ext4_init_inode_bitmap(struct super_block *sb,
99 EXT4_INODES_PER_GROUP(sb) / 8); 99 EXT4_INODES_PER_GROUP(sb) / 8);
100 ext4_group_desc_csum_set(sb, block_group, gdp); 100 ext4_group_desc_csum_set(sb, block_group, gdp);
101 101
102 return EXT4_INODES_PER_GROUP(sb); 102 return 0;
103} 103}
104 104
105void ext4_end_bitmap_read(struct buffer_head *bh, int uptodate) 105void ext4_end_bitmap_read(struct buffer_head *bh, int uptodate)
@@ -112,6 +112,42 @@ void ext4_end_bitmap_read(struct buffer_head *bh, int uptodate)
112 put_bh(bh); 112 put_bh(bh);
113} 113}
114 114
115static int ext4_validate_inode_bitmap(struct super_block *sb,
116 struct ext4_group_desc *desc,
117 ext4_group_t block_group,
118 struct buffer_head *bh)
119{
120 ext4_fsblk_t blk;
121 struct ext4_group_info *grp = ext4_get_group_info(sb, block_group);
122 struct ext4_sb_info *sbi = EXT4_SB(sb);
123
124 if (buffer_verified(bh))
125 return 0;
126 if (EXT4_MB_GRP_IBITMAP_CORRUPT(grp))
127 return -EFSCORRUPTED;
128
129 ext4_lock_group(sb, block_group);
130 blk = ext4_inode_bitmap(sb, desc);
131 if (!ext4_inode_bitmap_csum_verify(sb, block_group, desc, bh,
132 EXT4_INODES_PER_GROUP(sb) / 8)) {
133 ext4_unlock_group(sb, block_group);
134 ext4_error(sb, "Corrupt inode bitmap - block_group = %u, "
135 "inode_bitmap = %llu", block_group, blk);
136 grp = ext4_get_group_info(sb, block_group);
137 if (!EXT4_MB_GRP_IBITMAP_CORRUPT(grp)) {
138 int count;
139 count = ext4_free_inodes_count(sb, desc);
140 percpu_counter_sub(&sbi->s_freeinodes_counter,
141 count);
142 }
143 set_bit(EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT, &grp->bb_state);
144 return -EFSBADCRC;
145 }
146 set_buffer_verified(bh);
147 ext4_unlock_group(sb, block_group);
148 return 0;
149}
150
115/* 151/*
116 * Read the inode allocation bitmap for a given block_group, reading 152 * Read the inode allocation bitmap for a given block_group, reading
117 * into the specified slot in the superblock's bitmap cache. 153 * into the specified slot in the superblock's bitmap cache.
@@ -124,12 +160,11 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group)
124 struct ext4_group_desc *desc; 160 struct ext4_group_desc *desc;
125 struct buffer_head *bh = NULL; 161 struct buffer_head *bh = NULL;
126 ext4_fsblk_t bitmap_blk; 162 ext4_fsblk_t bitmap_blk;
127 struct ext4_group_info *grp; 163 int err;
128 struct ext4_sb_info *sbi = EXT4_SB(sb);
129 164
130 desc = ext4_get_group_desc(sb, block_group, NULL); 165 desc = ext4_get_group_desc(sb, block_group, NULL);
131 if (!desc) 166 if (!desc)
132 return NULL; 167 return ERR_PTR(-EFSCORRUPTED);
133 168
134 bitmap_blk = ext4_inode_bitmap(sb, desc); 169 bitmap_blk = ext4_inode_bitmap(sb, desc);
135 bh = sb_getblk(sb, bitmap_blk); 170 bh = sb_getblk(sb, bitmap_blk);
@@ -137,7 +172,7 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group)
137 ext4_error(sb, "Cannot read inode bitmap - " 172 ext4_error(sb, "Cannot read inode bitmap - "
138 "block_group = %u, inode_bitmap = %llu", 173 "block_group = %u, inode_bitmap = %llu",
139 block_group, bitmap_blk); 174 block_group, bitmap_blk);
140 return NULL; 175 return ERR_PTR(-EIO);
141 } 176 }
142 if (bitmap_uptodate(bh)) 177 if (bitmap_uptodate(bh))
143 goto verify; 178 goto verify;
@@ -150,12 +185,14 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group)
150 185
151 ext4_lock_group(sb, block_group); 186 ext4_lock_group(sb, block_group);
152 if (desc->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)) { 187 if (desc->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)) {
153 ext4_init_inode_bitmap(sb, bh, block_group, desc); 188 err = ext4_init_inode_bitmap(sb, bh, block_group, desc);
154 set_bitmap_uptodate(bh); 189 set_bitmap_uptodate(bh);
155 set_buffer_uptodate(bh); 190 set_buffer_uptodate(bh);
156 set_buffer_verified(bh); 191 set_buffer_verified(bh);
157 ext4_unlock_group(sb, block_group); 192 ext4_unlock_group(sb, block_group);
158 unlock_buffer(bh); 193 unlock_buffer(bh);
194 if (err)
195 goto out;
159 return bh; 196 return bh;
160 } 197 }
161 ext4_unlock_group(sb, block_group); 198 ext4_unlock_group(sb, block_group);
@@ -182,31 +219,17 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group)
182 ext4_error(sb, "Cannot read inode bitmap - " 219 ext4_error(sb, "Cannot read inode bitmap - "
183 "block_group = %u, inode_bitmap = %llu", 220 "block_group = %u, inode_bitmap = %llu",
184 block_group, bitmap_blk); 221 block_group, bitmap_blk);
185 return NULL; 222 return ERR_PTR(-EIO);
186 } 223 }
187 224
188verify: 225verify:
189 ext4_lock_group(sb, block_group); 226 err = ext4_validate_inode_bitmap(sb, desc, block_group, bh);
190 if (!buffer_verified(bh) && 227 if (err)
191 !ext4_inode_bitmap_csum_verify(sb, block_group, desc, bh, 228 goto out;
192 EXT4_INODES_PER_GROUP(sb) / 8)) {
193 ext4_unlock_group(sb, block_group);
194 put_bh(bh);
195 ext4_error(sb, "Corrupt inode bitmap - block_group = %u, "
196 "inode_bitmap = %llu", block_group, bitmap_blk);
197 grp = ext4_get_group_info(sb, block_group);
198 if (!EXT4_MB_GRP_IBITMAP_CORRUPT(grp)) {
199 int count;
200 count = ext4_free_inodes_count(sb, desc);
201 percpu_counter_sub(&sbi->s_freeinodes_counter,
202 count);
203 }
204 set_bit(EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT, &grp->bb_state);
205 return NULL;
206 }
207 ext4_unlock_group(sb, block_group);
208 set_buffer_verified(bh);
209 return bh; 229 return bh;
230out:
231 put_bh(bh);
232 return ERR_PTR(err);
210} 233}
211 234
212/* 235/*
@@ -286,8 +309,15 @@ void ext4_free_inode(handle_t *handle, struct inode *inode)
286 bitmap_bh = ext4_read_inode_bitmap(sb, block_group); 309 bitmap_bh = ext4_read_inode_bitmap(sb, block_group);
287 /* Don't bother if the inode bitmap is corrupt. */ 310 /* Don't bother if the inode bitmap is corrupt. */
288 grp = ext4_get_group_info(sb, block_group); 311 grp = ext4_get_group_info(sb, block_group);
289 if (unlikely(EXT4_MB_GRP_IBITMAP_CORRUPT(grp)) || !bitmap_bh) 312 if (IS_ERR(bitmap_bh)) {
313 fatal = PTR_ERR(bitmap_bh);
314 bitmap_bh = NULL;
315 goto error_return;
316 }
317 if (unlikely(EXT4_MB_GRP_IBITMAP_CORRUPT(grp))) {
318 fatal = -EFSCORRUPTED;
290 goto error_return; 319 goto error_return;
320 }
291 321
292 BUFFER_TRACE(bitmap_bh, "get_write_access"); 322 BUFFER_TRACE(bitmap_bh, "get_write_access");
293 fatal = ext4_journal_get_write_access(handle, bitmap_bh); 323 fatal = ext4_journal_get_write_access(handle, bitmap_bh);
@@ -826,7 +856,9 @@ got_group:
826 brelse(inode_bitmap_bh); 856 brelse(inode_bitmap_bh);
827 inode_bitmap_bh = ext4_read_inode_bitmap(sb, group); 857 inode_bitmap_bh = ext4_read_inode_bitmap(sb, group);
828 /* Skip groups with suspicious inode tables */ 858 /* Skip groups with suspicious inode tables */
829 if (EXT4_MB_GRP_IBITMAP_CORRUPT(grp) || !inode_bitmap_bh) { 859 if (EXT4_MB_GRP_IBITMAP_CORRUPT(grp) ||
860 IS_ERR(inode_bitmap_bh)) {
861 inode_bitmap_bh = NULL;
830 if (++group == ngroups) 862 if (++group == ngroups)
831 group = 0; 863 group = 0;
832 continue; 864 continue;
@@ -902,8 +934,8 @@ got:
902 struct buffer_head *block_bitmap_bh; 934 struct buffer_head *block_bitmap_bh;
903 935
904 block_bitmap_bh = ext4_read_block_bitmap(sb, group); 936 block_bitmap_bh = ext4_read_block_bitmap(sb, group);
905 if (!block_bitmap_bh) { 937 if (IS_ERR(block_bitmap_bh)) {
906 err = -EIO; 938 err = PTR_ERR(block_bitmap_bh);
907 goto out; 939 goto out;
908 } 940 }
909 BUFFER_TRACE(block_bitmap_bh, "get block bitmap access"); 941 BUFFER_TRACE(block_bitmap_bh, "get block bitmap access");
@@ -1123,8 +1155,10 @@ struct inode *ext4_orphan_get(struct super_block *sb, unsigned long ino)
1123 block_group = (ino - 1) / EXT4_INODES_PER_GROUP(sb); 1155 block_group = (ino - 1) / EXT4_INODES_PER_GROUP(sb);
1124 bit = (ino - 1) % EXT4_INODES_PER_GROUP(sb); 1156 bit = (ino - 1) % EXT4_INODES_PER_GROUP(sb);
1125 bitmap_bh = ext4_read_inode_bitmap(sb, block_group); 1157 bitmap_bh = ext4_read_inode_bitmap(sb, block_group);
1126 if (!bitmap_bh) { 1158 if (IS_ERR(bitmap_bh)) {
1127 ext4_warning(sb, "inode bitmap error for orphan %lu", ino); 1159 err = PTR_ERR(bitmap_bh);
1160 ext4_warning(sb, "inode bitmap error %ld for orphan %lu",
1161 ino, err);
1128 goto error; 1162 goto error;
1129 } 1163 }
1130 1164
@@ -1199,8 +1233,10 @@ unsigned long ext4_count_free_inodes(struct super_block *sb)
1199 desc_count += ext4_free_inodes_count(sb, gdp); 1233 desc_count += ext4_free_inodes_count(sb, gdp);
1200 brelse(bitmap_bh); 1234 brelse(bitmap_bh);
1201 bitmap_bh = ext4_read_inode_bitmap(sb, i); 1235 bitmap_bh = ext4_read_inode_bitmap(sb, i);
1202 if (!bitmap_bh) 1236 if (IS_ERR(bitmap_bh)) {
1237 bitmap_bh = NULL;
1203 continue; 1238 continue;
1239 }
1204 1240
1205 x = ext4_count_free(bitmap_bh->b_data, 1241 x = ext4_count_free(bitmap_bh->b_data,
1206 EXT4_INODES_PER_GROUP(sb) / 8); 1242 EXT4_INODES_PER_GROUP(sb) / 8);