Commit 7a4c5de27efa4c2ecca87af0a3deea63446367e2
1 parent
7e731bc9a1
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
ext4: don't call ext4_error while block group is locked
While in ext4_validate_block_bitmap(), if an block allocation bitmap is found to be invalid, we call ext4_error() while the block group is still locked. This causes ext4_commit_super() to call a function which might sleep while in an atomic context. There's no need to keep the block group locked at this point, so hoist the ext4_error() call up to ext4_validate_block_bitmap() and release the block group spinlock before calling ext4_error(). The reported stack trace can be found at: http://article.gmane.org/gmane.comp.file-systems.ext4/33731 Reported-by: Dave Jones <davej@redhat.com> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu> Cc: stable@vger.kernel.org
Showing 2 changed files with 37 additions and 26 deletions Side-by-side Diff
fs/ext4/balloc.c
... | ... | @@ -280,14 +280,18 @@ |
280 | 280 | return desc; |
281 | 281 | } |
282 | 282 | |
283 | -static int ext4_valid_block_bitmap(struct super_block *sb, | |
284 | - struct ext4_group_desc *desc, | |
285 | - unsigned int block_group, | |
286 | - struct buffer_head *bh) | |
283 | +/* | |
284 | + * Return the block number which was discovered to be invalid, or 0 if | |
285 | + * the block bitmap is valid. | |
286 | + */ | |
287 | +static ext4_fsblk_t ext4_valid_block_bitmap(struct super_block *sb, | |
288 | + struct ext4_group_desc *desc, | |
289 | + unsigned int block_group, | |
290 | + struct buffer_head *bh) | |
287 | 291 | { |
288 | 292 | ext4_grpblk_t offset; |
289 | 293 | ext4_grpblk_t next_zero_bit; |
290 | - ext4_fsblk_t bitmap_blk; | |
294 | + ext4_fsblk_t blk; | |
291 | 295 | ext4_fsblk_t group_first_block; |
292 | 296 | |
293 | 297 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) { |
294 | 298 | |
295 | 299 | |
296 | 300 | |
297 | 301 | |
298 | 302 | |
299 | 303 | |
... | ... | @@ -297,37 +301,33 @@ |
297 | 301 | * or it has to also read the block group where the bitmaps |
298 | 302 | * are located to verify they are set. |
299 | 303 | */ |
300 | - return 1; | |
304 | + return 0; | |
301 | 305 | } |
302 | 306 | group_first_block = ext4_group_first_block_no(sb, block_group); |
303 | 307 | |
304 | 308 | /* check whether block bitmap block number is set */ |
305 | - bitmap_blk = ext4_block_bitmap(sb, desc); | |
306 | - offset = bitmap_blk - group_first_block; | |
309 | + blk = ext4_block_bitmap(sb, desc); | |
310 | + offset = blk - group_first_block; | |
307 | 311 | if (!ext4_test_bit(offset, bh->b_data)) |
308 | 312 | /* bad block bitmap */ |
309 | - goto err_out; | |
313 | + return blk; | |
310 | 314 | |
311 | 315 | /* check whether the inode bitmap block number is set */ |
312 | - bitmap_blk = ext4_inode_bitmap(sb, desc); | |
313 | - offset = bitmap_blk - group_first_block; | |
316 | + blk = ext4_inode_bitmap(sb, desc); | |
317 | + offset = blk - group_first_block; | |
314 | 318 | if (!ext4_test_bit(offset, bh->b_data)) |
315 | 319 | /* bad block bitmap */ |
316 | - goto err_out; | |
320 | + return blk; | |
317 | 321 | |
318 | 322 | /* check whether the inode table block number is set */ |
319 | - bitmap_blk = ext4_inode_table(sb, desc); | |
320 | - offset = bitmap_blk - group_first_block; | |
323 | + blk = ext4_inode_table(sb, desc); | |
324 | + offset = blk - group_first_block; | |
321 | 325 | next_zero_bit = ext4_find_next_zero_bit(bh->b_data, |
322 | 326 | offset + EXT4_SB(sb)->s_itb_per_group, |
323 | 327 | offset); |
324 | - if (next_zero_bit >= offset + EXT4_SB(sb)->s_itb_per_group) | |
325 | - /* good bitmap for inode tables */ | |
326 | - return 1; | |
327 | - | |
328 | -err_out: | |
329 | - ext4_error(sb, "Invalid block bitmap - block_group = %d, block = %llu", | |
330 | - block_group, bitmap_blk); | |
328 | + if (next_zero_bit < offset + EXT4_SB(sb)->s_itb_per_group) | |
329 | + /* bad bitmap for inode tables */ | |
330 | + return blk; | |
331 | 331 | return 0; |
332 | 332 | } |
333 | 333 | |
334 | 334 | |
... | ... | @@ -336,14 +336,26 @@ |
336 | 336 | unsigned int block_group, |
337 | 337 | struct buffer_head *bh) |
338 | 338 | { |
339 | + ext4_fsblk_t blk; | |
340 | + | |
339 | 341 | if (buffer_verified(bh)) |
340 | 342 | return; |
341 | 343 | |
342 | 344 | ext4_lock_group(sb, block_group); |
343 | - if (ext4_valid_block_bitmap(sb, desc, block_group, bh) && | |
344 | - ext4_block_bitmap_csum_verify(sb, block_group, desc, bh, | |
345 | - EXT4_BLOCKS_PER_GROUP(sb) / 8)) | |
346 | - set_buffer_verified(bh); | |
345 | + blk = ext4_valid_block_bitmap(sb, desc, block_group, bh); | |
346 | + if (unlikely(blk != 0)) { | |
347 | + ext4_unlock_group(sb, block_group); | |
348 | + ext4_error(sb, "bg %u: block %llu: invalid block bitmap", | |
349 | + block_group, blk); | |
350 | + return; | |
351 | + } | |
352 | + if (unlikely(!ext4_block_bitmap_csum_verify(sb, block_group, | |
353 | + desc, bh, EXT4_BLOCKS_PER_GROUP(sb) / 8))) { | |
354 | + ext4_unlock_group(sb, block_group); | |
355 | + ext4_error(sb, "bg %u: bad block bitmap checksum", block_group); | |
356 | + return; | |
357 | + } | |
358 | + set_buffer_verified(bh); | |
347 | 359 | ext4_unlock_group(sb, block_group); |
348 | 360 | } |
349 | 361 |