aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ext4/balloc.c17
-rw-r--r--fs/ext4/mballoc.c47
2 files changed, 47 insertions, 17 deletions
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index da994374ec3b..30494c5da843 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -287,11 +287,11 @@ read_block_bitmap(struct super_block *sb, ext4_group_t block_group)
287 (int)block_group, (unsigned long long)bitmap_blk); 287 (int)block_group, (unsigned long long)bitmap_blk);
288 return NULL; 288 return NULL;
289 } 289 }
290 if (!ext4_valid_block_bitmap(sb, desc, block_group, bh)) { 290 ext4_valid_block_bitmap(sb, desc, block_group, bh);
291 put_bh(bh); 291 /*
292 return NULL; 292 * file system mounted not to panic on error,
293 } 293 * continue with corrupt bitmap
294 294 */
295 return bh; 295 return bh;
296} 296}
297/* 297/*
@@ -1770,7 +1770,12 @@ allocated:
1770 "Allocating block in system zone - " 1770 "Allocating block in system zone - "
1771 "blocks from %llu, length %lu", 1771 "blocks from %llu, length %lu",
1772 ret_block, num); 1772 ret_block, num);
1773 goto out; 1773 /*
1774 * claim_block marked the blocks we allocated
1775 * as in use. So we may want to selectively
1776 * mark some of the blocks as free
1777 */
1778 goto retry_alloc;
1774 } 1779 }
1775 1780
1776 performed_allocation = 1; 1781 performed_allocation = 1;
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index 1d7fde994521..873ad9b3418c 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -2736,7 +2736,7 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
2736 struct ext4_sb_info *sbi; 2736 struct ext4_sb_info *sbi;
2737 struct super_block *sb; 2737 struct super_block *sb;
2738 ext4_fsblk_t block; 2738 ext4_fsblk_t block;
2739 int err; 2739 int err, len;
2740 2740
2741 BUG_ON(ac->ac_status != AC_STATUS_FOUND); 2741 BUG_ON(ac->ac_status != AC_STATUS_FOUND);
2742 BUG_ON(ac->ac_b_ex.fe_len <= 0); 2742 BUG_ON(ac->ac_b_ex.fe_len <= 0);
@@ -2770,14 +2770,27 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
2770 + ac->ac_b_ex.fe_start 2770 + ac->ac_b_ex.fe_start
2771 + le32_to_cpu(es->s_first_data_block); 2771 + le32_to_cpu(es->s_first_data_block);
2772 2772
2773 if (block == ext4_block_bitmap(sb, gdp) || 2773 len = ac->ac_b_ex.fe_len;
2774 block == ext4_inode_bitmap(sb, gdp) || 2774 if (in_range(ext4_block_bitmap(sb, gdp), block, len) ||
2775 in_range(block, ext4_inode_table(sb, gdp), 2775 in_range(ext4_inode_bitmap(sb, gdp), block, len) ||
2776 EXT4_SB(sb)->s_itb_per_group)) { 2776 in_range(block, ext4_inode_table(sb, gdp),
2777 2777 EXT4_SB(sb)->s_itb_per_group) ||
2778 in_range(block + len - 1, ext4_inode_table(sb, gdp),
2779 EXT4_SB(sb)->s_itb_per_group)) {
2778 ext4_error(sb, __func__, 2780 ext4_error(sb, __func__,
2779 "Allocating block in system zone - block = %llu", 2781 "Allocating block in system zone - block = %llu",
2780 block); 2782 block);
2783 /* File system mounted not to panic on error
2784 * Fix the bitmap and repeat the block allocation
2785 * We leak some of the blocks here.
2786 */
2787 mb_set_bits(sb_bgl_lock(sbi, ac->ac_b_ex.fe_group),
2788 bitmap_bh->b_data, ac->ac_b_ex.fe_start,
2789 ac->ac_b_ex.fe_len);
2790 err = ext4_journal_dirty_metadata(handle, bitmap_bh);
2791 if (!err)
2792 err = -EAGAIN;
2793 goto out_err;
2781 } 2794 }
2782#ifdef AGGRESSIVE_CHECK 2795#ifdef AGGRESSIVE_CHECK
2783 { 2796 {
@@ -4032,7 +4045,6 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
4032 4045
4033 ac->ac_op = EXT4_MB_HISTORY_ALLOC; 4046 ac->ac_op = EXT4_MB_HISTORY_ALLOC;
4034 ext4_mb_normalize_request(ac, ar); 4047 ext4_mb_normalize_request(ac, ar);
4035
4036repeat: 4048repeat:
4037 /* allocate space in core */ 4049 /* allocate space in core */
4038 ext4_mb_regular_allocator(ac); 4050 ext4_mb_regular_allocator(ac);
@@ -4046,10 +4058,21 @@ repeat:
4046 } 4058 }
4047 4059
4048 if (likely(ac->ac_status == AC_STATUS_FOUND)) { 4060 if (likely(ac->ac_status == AC_STATUS_FOUND)) {
4049 ext4_mb_mark_diskspace_used(ac, handle); 4061 *errp = ext4_mb_mark_diskspace_used(ac, handle);
4050 *errp = 0; 4062 if (*errp == -EAGAIN) {
4051 block = ext4_grp_offs_to_block(sb, &ac->ac_b_ex); 4063 ac->ac_b_ex.fe_group = 0;
4052 ar->len = ac->ac_b_ex.fe_len; 4064 ac->ac_b_ex.fe_start = 0;
4065 ac->ac_b_ex.fe_len = 0;
4066 ac->ac_status = AC_STATUS_CONTINUE;
4067 goto repeat;
4068 } else if (*errp) {
4069 ac->ac_b_ex.fe_len = 0;
4070 ar->len = 0;
4071 ext4_mb_show_ac(ac);
4072 } else {
4073 block = ext4_grp_offs_to_block(sb, &ac->ac_b_ex);
4074 ar->len = ac->ac_b_ex.fe_len;
4075 }
4053 } else { 4076 } else {
4054 freed = ext4_mb_discard_preallocations(sb, ac->ac_o_ex.fe_len); 4077 freed = ext4_mb_discard_preallocations(sb, ac->ac_o_ex.fe_len);
4055 if (freed) 4078 if (freed)
@@ -4236,6 +4259,8 @@ do_more:
4236 ext4_error(sb, __func__, 4259 ext4_error(sb, __func__,
4237 "Freeing blocks in system zone - " 4260 "Freeing blocks in system zone - "
4238 "Block = %lu, count = %lu", block, count); 4261 "Block = %lu, count = %lu", block, count);
4262 /* err = 0. ext4_std_error should be a no op */
4263 goto error_return;
4239 } 4264 }
4240 4265
4241 BUFFER_TRACE(bitmap_bh, "getting write access"); 4266 BUFFER_TRACE(bitmap_bh, "getting write access");