aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/mballoc.c
diff options
context:
space:
mode:
authorAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>2009-01-05 22:19:52 -0500
committerTheodore Ts'o <tytso@mit.edu>2009-01-05 22:19:52 -0500
commit5d1b1b3f492f8696ea18950a454a141381b0f926 (patch)
treee6277cd3e01c074403b9da7390de1daa6b9f248f /fs/ext4/mballoc.c
parentb7be019e80da4db96d283734d55366014509911c (diff)
ext4: fix BUG when calling ext4_error with locked block group
The mballoc code likes to call ext4_error while it is holding locked block groups. This can causes a scheduling in atomic context BUG. We can't just unlock the block group and relock it after/if ext4_error returns since that might result in race conditions in the case where the filesystem is set to continue after finding errors. Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/mballoc.c')
-rw-r--r--fs/ext4/mballoc.c30
1 files changed, 15 insertions, 15 deletions
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index 0bf4c4c06b19..cda69632eea3 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -457,8 +457,8 @@ static void mb_free_blocks_double(struct inode *inode, struct ext4_buddy *e4b,
457 blocknr += first + i; 457 blocknr += first + i;
458 blocknr += 458 blocknr +=
459 le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block); 459 le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block);
460 460 ext4_grp_locked_error(sb, e4b->bd_group,
461 ext4_error(sb, __func__, "double-free of inode" 461 __func__, "double-free of inode"
462 " %lu's block %llu(bit %u in group %u)", 462 " %lu's block %llu(bit %u in group %u)",
463 inode ? inode->i_ino : 0, blocknr, 463 inode ? inode->i_ino : 0, blocknr,
464 first + i, e4b->bd_group); 464 first + i, e4b->bd_group);
@@ -702,7 +702,7 @@ static void ext4_mb_generate_buddy(struct super_block *sb,
702 grp->bb_fragments = fragments; 702 grp->bb_fragments = fragments;
703 703
704 if (free != grp->bb_free) { 704 if (free != grp->bb_free) {
705 ext4_error(sb, __func__, 705 ext4_grp_locked_error(sb, group, __func__,
706 "EXT4-fs: group %u: %u blocks in bitmap, %u in gd", 706 "EXT4-fs: group %u: %u blocks in bitmap, %u in gd",
707 group, free, grp->bb_free); 707 group, free, grp->bb_free);
708 /* 708 /*
@@ -1095,8 +1095,6 @@ static void mb_set_bits(spinlock_t *lock, void *bm, int cur, int len)
1095 1095
1096static void mb_free_blocks(struct inode *inode, struct ext4_buddy *e4b, 1096static void mb_free_blocks(struct inode *inode, struct ext4_buddy *e4b,
1097 int first, int count) 1097 int first, int count)
1098__releases(bitlock)
1099__acquires(bitlock)
1100{ 1098{
1101 int block = 0; 1099 int block = 0;
1102 int max = 0; 1100 int max = 0;
@@ -1135,12 +1133,11 @@ __acquires(bitlock)
1135 blocknr += block; 1133 blocknr += block;
1136 blocknr += 1134 blocknr +=
1137 le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block); 1135 le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block);
1138 ext4_unlock_group(sb, e4b->bd_group); 1136 ext4_grp_locked_error(sb, e4b->bd_group,
1139 ext4_error(sb, __func__, "double-free of inode" 1137 __func__, "double-free of inode"
1140 " %lu's block %llu(bit %u in group %u)", 1138 " %lu's block %llu(bit %u in group %u)",
1141 inode ? inode->i_ino : 0, blocknr, block, 1139 inode ? inode->i_ino : 0, blocknr, block,
1142 e4b->bd_group); 1140 e4b->bd_group);
1143 ext4_lock_group(sb, e4b->bd_group);
1144 } 1141 }
1145 mb_clear_bit(block, EXT4_MB_BITMAP(e4b)); 1142 mb_clear_bit(block, EXT4_MB_BITMAP(e4b));
1146 e4b->bd_info->bb_counters[order]++; 1143 e4b->bd_info->bb_counters[order]++;
@@ -1623,7 +1620,8 @@ static void ext4_mb_complex_scan_group(struct ext4_allocation_context *ac,
1623 * free blocks even though group info says we 1620 * free blocks even though group info says we
1624 * we have free blocks 1621 * we have free blocks
1625 */ 1622 */
1626 ext4_error(sb, __func__, "%d free blocks as per " 1623 ext4_grp_locked_error(sb, e4b->bd_group,
1624 __func__, "%d free blocks as per "
1627 "group info. But bitmap says 0", 1625 "group info. But bitmap says 0",
1628 free); 1626 free);
1629 break; 1627 break;
@@ -1632,7 +1630,8 @@ static void ext4_mb_complex_scan_group(struct ext4_allocation_context *ac,
1632 mb_find_extent(e4b, 0, i, ac->ac_g_ex.fe_len, &ex); 1630 mb_find_extent(e4b, 0, i, ac->ac_g_ex.fe_len, &ex);
1633 BUG_ON(ex.fe_len <= 0); 1631 BUG_ON(ex.fe_len <= 0);
1634 if (free < ex.fe_len) { 1632 if (free < ex.fe_len) {
1635 ext4_error(sb, __func__, "%d free blocks as per " 1633 ext4_grp_locked_error(sb, e4b->bd_group,
1634 __func__, "%d free blocks as per "
1636 "group info. But got %d blocks", 1635 "group info. But got %d blocks",
1637 free, ex.fe_len); 1636 free, ex.fe_len);
1638 /* 1637 /*
@@ -3822,8 +3821,9 @@ ext4_mb_release_inode_pa(struct ext4_buddy *e4b, struct buffer_head *bitmap_bh,
3822 pa, (unsigned long) pa->pa_lstart, 3821 pa, (unsigned long) pa->pa_lstart,
3823 (unsigned long) pa->pa_pstart, 3822 (unsigned long) pa->pa_pstart,
3824 (unsigned long) pa->pa_len); 3823 (unsigned long) pa->pa_len);
3825 ext4_error(sb, __func__, "free %u, pa_free %u", 3824 ext4_grp_locked_error(sb, group,
3826 free, pa->pa_free); 3825 __func__, "free %u, pa_free %u",
3826 free, pa->pa_free);
3827 /* 3827 /*
3828 * pa is already deleted so we use the value obtained 3828 * pa is already deleted so we use the value obtained
3829 * from the bitmap and continue. 3829 * from the bitmap and continue.
@@ -4633,9 +4633,9 @@ ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b,
4633 else if (block >= (entry->start_blk + entry->count)) 4633 else if (block >= (entry->start_blk + entry->count))
4634 n = &(*n)->rb_right; 4634 n = &(*n)->rb_right;
4635 else { 4635 else {
4636 ext4_error(sb, __func__, 4636 ext4_grp_locked_error(sb, e4b->bd_group, __func__,
4637 "Double free of blocks %d (%d %d)", 4637 "Double free of blocks %d (%d %d)",
4638 block, entry->start_blk, entry->count); 4638 block, entry->start_blk, entry->count);
4639 return 0; 4639 return 0;
4640 } 4640 }
4641 } 4641 }