aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/mballoc.c
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 /fs/ext4/mballoc.c
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>
Diffstat (limited to 'fs/ext4/mballoc.c')
-rw-r--r--fs/ext4/mballoc.c47
1 files changed, 36 insertions, 11 deletions
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");