]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - fs/ext4/mballoc.c
ext4: Fix use of uninitialized data with debug enabled.
[linux-2.6-omap-h63xx.git] / fs / ext4 / mballoc.c
index 1d7fde994521434271682c95ffd611991e287e7f..c9900aade15072821bb74e87e34d6050f2d84704 100644 (file)
@@ -2736,7 +2736,7 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
        struct ext4_sb_info *sbi;
        struct super_block *sb;
        ext4_fsblk_t block;
-       int err;
+       int err, len;
 
        BUG_ON(ac->ac_status != AC_STATUS_FOUND);
        BUG_ON(ac->ac_b_ex.fe_len <= 0);
@@ -2745,8 +2745,6 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
        sbi = EXT4_SB(sb);
        es = sbi->s_es;
 
-       ext4_debug("using block group %lu(%d)\n", ac->ac_b_ex.fe_group,
-                       gdp->bg_free_blocks_count);
 
        err = -EIO;
        bitmap_bh = read_block_bitmap(sb, ac->ac_b_ex.fe_group);
@@ -2762,6 +2760,9 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
        if (!gdp)
                goto out_err;
 
+       ext4_debug("using block group %lu(%d)\n", ac->ac_b_ex.fe_group,
+                       gdp->bg_free_blocks_count);
+
        err = ext4_journal_get_write_access(handle, gdp_bh);
        if (err)
                goto out_err;
@@ -2770,14 +2771,27 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
                + ac->ac_b_ex.fe_start
                + le32_to_cpu(es->s_first_data_block);
 
-       if (block == ext4_block_bitmap(sb, gdp) ||
-                       block == ext4_inode_bitmap(sb, gdp) ||
-                       in_range(block, ext4_inode_table(sb, gdp),
-                               EXT4_SB(sb)->s_itb_per_group)) {
-
+       len = ac->ac_b_ex.fe_len;
+       if (in_range(ext4_block_bitmap(sb, gdp), block, len) ||
+           in_range(ext4_inode_bitmap(sb, gdp), block, len) ||
+           in_range(block, ext4_inode_table(sb, gdp),
+                    EXT4_SB(sb)->s_itb_per_group) ||
+           in_range(block + len - 1, ext4_inode_table(sb, gdp),
+                    EXT4_SB(sb)->s_itb_per_group)) {
                ext4_error(sb, __func__,
                           "Allocating block in system zone - block = %llu",
                           block);
+               /* File system mounted not to panic on error
+                * Fix the bitmap and repeat the block allocation
+                * We leak some of the blocks here.
+                */
+               mb_set_bits(sb_bgl_lock(sbi, ac->ac_b_ex.fe_group),
+                               bitmap_bh->b_data, ac->ac_b_ex.fe_start,
+                               ac->ac_b_ex.fe_len);
+               err = ext4_journal_dirty_metadata(handle, bitmap_bh);
+               if (!err)
+                       err = -EAGAIN;
+               goto out_err;
        }
 #ifdef AGGRESSIVE_CHECK
        {
@@ -3081,8 +3095,7 @@ static void ext4_mb_use_inode_pa(struct ext4_allocation_context *ac,
 static void ext4_mb_use_group_pa(struct ext4_allocation_context *ac,
                                struct ext4_prealloc_space *pa)
 {
-       unsigned len = ac->ac_o_ex.fe_len;
-
+       unsigned int len = ac->ac_o_ex.fe_len;
        ext4_get_group_no_and_offset(ac->ac_sb, pa->pa_pstart,
                                        &ac->ac_b_ex.fe_group,
                                        &ac->ac_b_ex.fe_start);
@@ -4032,7 +4045,6 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
 
                ac->ac_op = EXT4_MB_HISTORY_ALLOC;
                ext4_mb_normalize_request(ac, ar);
-
 repeat:
                /* allocate space in core */
                ext4_mb_regular_allocator(ac);
@@ -4046,10 +4058,21 @@ repeat:
        }
 
        if (likely(ac->ac_status == AC_STATUS_FOUND)) {
-               ext4_mb_mark_diskspace_used(ac, handle);
-               *errp = 0;
-               block = ext4_grp_offs_to_block(sb, &ac->ac_b_ex);
-               ar->len = ac->ac_b_ex.fe_len;
+               *errp = ext4_mb_mark_diskspace_used(ac, handle);
+               if (*errp ==  -EAGAIN) {
+                       ac->ac_b_ex.fe_group = 0;
+                       ac->ac_b_ex.fe_start = 0;
+                       ac->ac_b_ex.fe_len = 0;
+                       ac->ac_status = AC_STATUS_CONTINUE;
+                       goto repeat;
+               } else if (*errp) {
+                       ac->ac_b_ex.fe_len = 0;
+                       ar->len = 0;
+                       ext4_mb_show_ac(ac);
+               } else {
+                       block = ext4_grp_offs_to_block(sb, &ac->ac_b_ex);
+                       ar->len = ac->ac_b_ex.fe_len;
+               }
        } else {
                freed  = ext4_mb_discard_preallocations(sb, ac->ac_o_ex.fe_len);
                if (freed)
@@ -4236,6 +4259,8 @@ do_more:
                ext4_error(sb, __func__,
                           "Freeing blocks in system zone - "
                           "Block = %lu, count = %lu", block, count);
+               /* err = 0. ext4_std_error should be a no op */
+               goto error_return;
        }
 
        BUFFER_TRACE(bitmap_bh, "getting write access");