Commit 7a4c5de27efa4c2ecca87af0a3deea63446367e2

Authored by Theodore Ts'o
1 parent 7e731bc9a1

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

... ... @@ -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  
... ... @@ -79,7 +79,6 @@
79 79 if (provided == calculated)
80 80 return 1;
81 81  
82   - ext4_error(sb, "Bad block bitmap checksum: block_group = %u", group);
83 82 return 0;
84 83 }
85 84