diff options
author | Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> | 2009-01-05 22:19:52 -0500 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2009-01-05 22:19:52 -0500 |
commit | 5d1b1b3f492f8696ea18950a454a141381b0f926 (patch) | |
tree | e6277cd3e01c074403b9da7390de1daa6b9f248f /fs/ext4/mballoc.c | |
parent | b7be019e80da4db96d283734d55366014509911c (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.c | 30 |
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 | ||
1096 | static void mb_free_blocks(struct inode *inode, struct ext4_buddy *e4b, | 1096 | static 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 | } |