aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>2008-05-15 14:43:20 -0400
committerTheodore Ts'o <tytso@mit.edu>2008-05-15 14:43:20 -0400
commit519deca0496a4df07d15acf3181ca5d573bffdec (patch)
treede86a407e1ea429fde16bc85d4587ebe4aa8194b
parent1930479c4b6bbcb6f164a5b3498e0d98329967f4 (diff)
ext4: Retry block allocation if new blocks are allocated from system zone.
If the block allocator gets blocks out of system zone ext4 calls ext4_error. But if the file system is mounted with errors=continue retry block allocation. We need to mark the system zone blocks as in use to make sure retry don't pick them again System zone is the block range mapping block bitmap, inode bitmap and inode table. Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> Signed-off-by: Mingming Cao <cmm@us.ibm.com> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
-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");