Hi,

This contain fixes for making mballoc work with uninitialized block group. The patches can be downloaded from
http://www.radian.org/~kvaneesh/ext4/oct-3-2007/

The diff is attached below to find out what changed.

Mingming,

Can you replace the patch in the patch queue with the above two patches ?
-aneesh

diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index 321ad1e..47f70a8 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -90,8 +90,19 @@ unsigned ext4_init_block_bitmap(struct super_block *sb, 
struct buffer_head *bh,
                        bit_max += 1;
        }

-       /* Last and first groups are always initialized */
-       free_blocks = EXT4_BLOCKS_PER_GROUP(sb) - bit_max;
+       if (block_group == sbi->s_gdb_count - 1) {
+               /*
+                * Even though mke2fs always initialize first and last group
+                * if some other tool enabled the EXT4_BG_BLOCK_UNINIT we need
+                * to make sure we calculate the right free blocks
+                */
+               free_blocks = ext4_blocks_count(sbi->s_es) -
+                               le32_to_cpu(sbi->s_es->s_first_data_block) -
+                               (EXT4_BLOCKS_PER_GROUP(sb) * 
sbi->s_groups_count) -
+                               bit_max;
+       } else {
+               free_blocks = EXT4_BLOCKS_PER_GROUP(sb) - bit_max;
+       }

        if (bh) {
                for (bit = 0; bit < bit_max; bit++)
@@ -106,11 +117,20 @@ unsigned ext4_init_block_bitmap(struct super_block *sb, 
struct buffer_head *bh,
                for (bit = (ext4_inode_table(sb, gdp) - start),
                     bit_max = bit + sbi->s_itb_per_group; bit < bit_max; bit++)
                        ext4_set_bit(bit, bh->b_data);
+
+               /*
+                * Also if the number of blocks within the group is less than 
the
+                * blocksize * 8 ( which is the size of bitmap ), set rest of 
the
+                * block bitmap to 1
+                */
+               mark_bitmap_end(EXT4_BLOCKS_PER_GROUP(sb),
+                                       sb->s_blocksize * 8, bh->b_data);
        }

        return free_blocks - sbi->s_itb_per_group - 2;
}

+
/*
 * The free blocks are managed by bitmaps.  A file system contains several
 * blocks groups.  Each group contains 1 bitmap block for blocks, 1 bitmap
diff --git a/fs/ext4/group.h b/fs/ext4/group.h
index 9310979..1577910 100644
--- a/fs/ext4/group.h
+++ b/fs/ext4/group.h
@@ -8,9 +8,6 @@

#ifndef _LINUX_EXT4_GROUP_H
#define _LINUX_EXT4_GROUP_H
-#if defined(CONFIG_CRC16)
-#include <linux/crc16.h>
-#endif

extern __le16 ext4_group_desc_csum(struct ext4_sb_info *sbi, __u32 group,
                                   struct ext4_group_desc *gdp);
@@ -26,4 +23,5 @@ extern unsigned ext4_init_block_bitmap(struct super_block *sb,
extern unsigned ext4_init_inode_bitmap(struct super_block *sb,
                                       struct buffer_head *bh, int group,
                                       struct ext4_group_desc *desc);
+extern void mark_bitmap_end(int start_bit, int end_bit, char *bitmap);
#endif /* _LINUX_EXT4_GROUP_H */
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index 1fa418c..e4c421e 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -49,7 +49,7 @@
 * need to use it within a single byte (to ensure we get endianness right).
 * We can use memset for the rest of the bitmap as there are no other users.
 */
-static void mark_bitmap_end(int start_bit, int end_bit, char *bitmap)
+void mark_bitmap_end(int start_bit, int end_bit, char *bitmap)
{
        int i;

diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index 5ffc80b..4409c0c 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -34,6 +34,7 @@
#include <linux/pagemap.h>
#include <linux/seq_file.h>
#include <linux/version.h>
+#include "group.h"

/*
 * MUSTDO:
@@ -893,6 +894,13 @@ static int ext4_mb_init_cache(struct page *page, char 
*incore)
                        continue;
                }

+               if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
+                       ext4_init_block_bitmap(sb, bh[i],
+                                               first_group + i, desc);
+                       set_buffer_uptodate(bh[i]);
+                       unlock_buffer(bh[i]);
+                       continue;
+               }
                get_bh(bh[i]);
                bh[i]->b_end_io = end_buffer_read_sync;
                submit_bh(READ, bh[i]);
@@ -1702,11 +1710,10 @@ static void ext4_mb_scan_aligned(struct 
ext4_allocation_context *ac,
static int ext4_mb_good_group(struct ext4_allocation_context *ac,
                                int group, int cr)
{
+       unsigned free, fragments;
+       unsigned i, bits;
+       struct ext4_group_desc *desc;
        struct ext4_group_info *grp = EXT4_GROUP_INFO(ac->ac_sb, group);
-       unsigned free;
-       unsigned fragments;
-       unsigned i;
-       unsigned bits;

        BUG_ON(cr < 0 || cr >= 4);
        BUG_ON(EXT4_MB_GRP_NEED_INIT(grp));
@@ -1721,6 +1728,11 @@ static int ext4_mb_good_group(struct 
ext4_allocation_context *ac,
        switch (cr) {
        case 0:
                BUG_ON(ac->ac_2order == 0);
+               /* If this group is uninitialized, skip it initially */
+               desc = ext4_get_group_desc(ac->ac_sb, group, NULL);
+               if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT))
+                       return 0;
+
                bits = ac->ac_sb->s_blocksize_bits + 1;
                for (i = ac->ac_2order; i <= bits; i++)
                        if (grp->bb_counters[i] > 0)
@@ -1805,6 +1817,7 @@ repeat:
                ac->ac_criteria = cr;
                for (i = 0; i < EXT4_SB(sb)->s_groups_count; group++, i++) {
                        struct ext4_group_info *grp;
+                       struct ext4_group_desc *desc;

                        if (group == EXT4_SB(sb)->s_groups_count)
                                group = 0;
@@ -1844,12 +1857,16 @@ repeat:
                        }

                        ac->ac_groups_scanned++;
-                       if (cr == 0)
+                       desc = ext4_get_group_desc(sb, group, NULL);
+                       if (cr == 0 || (desc->bg_flags &
+                                       cpu_to_le16(EXT4_BG_BLOCK_UNINIT) &&
+                                       ac->ac_2order != 0)) {
                                ext4_mb_simple_scan_group(ac, &e4b);
-                       else if (cr == 1 && ac->ac_g_ex.fe_len == sbi->s_stripe)
+                       } else if (cr == 1 && ac->ac_g_ex.fe_len == 
sbi->s_stripe) {
                                ext4_mb_scan_aligned(ac, &e4b);
-                       else
+                       } else {
                                ext4_mb_complex_scan_group(ac, &e4b);
+                       }

                        ext4_unlock_group(sb, group);
                        ext4_mb_release_desc(&e4b);
@@ -2267,11 +2284,8 @@ static void ext4_mb_store_history(struct 
ext4_allocation_context *ac)

static int ext4_mb_init_backend(struct super_block *sb)
{
+       int i, j, len, metalen;
        struct ext4_sb_info *sbi = EXT4_SB(sb);
-       int i;
-       int j;
-       int len;
-       int metalen;
        int num_meta_group_infos =
                (sbi->s_groups_count + EXT4_DESC_PER_BLOCK(sb) - 1) >>
                        EXT4_DESC_PER_BLOCK_BITS(sb);
@@ -2321,7 +2335,7 @@ static int ext4_mb_init_backend(struct super_block *sb)
                        sbi->s_group_info[i >> EXT4_DESC_PER_BLOCK_BITS(sb)];
                j = i & (EXT4_DESC_PER_BLOCK(sb) - 1);

-               meta_group_info[j] = kmalloc(len, GFP_KERNEL);
+               meta_group_info[j] = kzalloc(len, GFP_KERNEL);
                if (meta_group_info[j] == NULL) {
                        printk(KERN_ERR "EXT4-fs: can't allocate buddy mem\n");
                        i--;
@@ -2333,14 +2347,20 @@ static int ext4_mb_init_backend(struct super_block *sb)
                                "EXT4-fs: can't read descriptor %u\n", i);
                        goto err_freebuddy;
                }
-               memset(meta_group_info[j], 0, len);
                set_bit(EXT4_GROUP_INFO_NEED_INIT_BIT,
                        &meta_group_info[j]->bb_state);

-               /* initialize bb_free to be able to skip
-                * empty groups without initialization */
-               meta_group_info[j]->bb_free =
-                       le16_to_cpu(desc->bg_free_blocks_count);
+               /*
+                * initialize bb_free to be able to skip
+                * empty groups without initialization
+                */
+               if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
+                       meta_group_info[j]->bb_free =
+                               ext4_free_blocks_after_init(sb, i, desc);
+               } else {
+                       meta_group_info[j]->bb_free =
+                               le16_to_cpu(desc->bg_free_blocks_count);
+               }

                INIT_LIST_HEAD(&meta_group_info[j]->bb_prealloc_list);

@@ -2919,9 +2939,17 @@ static int ext4_mb_mark_diskspace_used(struct 
ext4_allocation_context *ac,
                    ac->ac_b_ex.fe_len);

        spin_lock(sb_bgl_lock(sbi, ac->ac_b_ex.fe_group));
+       if (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
+               gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT);
+               gdp->bg_free_blocks_count =
+                       cpu_to_le16(ext4_free_blocks_after_init(sb,
+                                               ac->ac_b_ex.fe_group,
+                                               gdp));
+       }
        gdp->bg_free_blocks_count =
                cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count)
                                - ac->ac_b_ex.fe_len);
+       gdp->bg_checksum = ext4_group_desc_csum(sbi, ac->ac_b_ex.fe_group, gdp);
        spin_unlock(sb_bgl_lock(sbi, ac->ac_b_ex.fe_group));
        percpu_counter_mod(&sbi->s_freeblocks_counter, - ac->ac_b_ex.fe_len);

@@ -4066,7 +4094,7 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
#if 0
                static int ext4_mballoc_warning = 0;
                if (ext4_mballoc_warning++ == 0)
-                       printk(KERN_ERR "EXT3-fs: multiblock request with "
+                       printk(KERN_ERR "EXT4-fs: multiblock request with "
                                        "mballoc disabled!\n");
                ar->len = 1;
#endif
@@ -4353,6 +4381,7 @@ do_more:
        spin_lock(sb_bgl_lock(sbi, block_group));
        gdp->bg_free_blocks_count =
                cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count) + count);
+       gdp->bg_checksum = ext4_group_desc_csum(sbi, block_group, gdp);
        spin_unlock(sb_bgl_lock(sbi, block_group));
        percpu_counter_mod(&sbi->s_freeblocks_counter, count);

diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
index 3359450..19ff743 100644
--- a/fs/ext4/resize.c
+++ b/fs/ext4/resize.c
@@ -141,25 +141,6 @@ static struct buffer_head *bclean(handle_t *handle, struct 
super_block *sb,
}

/*
- * To avoid calling the atomic setbit hundreds or thousands of times, we only
- * need to use it within a single byte (to ensure we get endianness right).
- * We can use memset for the rest of the bitmap as there are no other users.
- */
-static void mark_bitmap_end(int start_bit, int end_bit, char *bitmap)
-{
-       int i;
-
-       if (start_bit >= end_bit)
-               return;
-
-       ext4_debug("mark end bits +%d through +%d used\n", start_bit, end_bit);
-       for (i = start_bit; i < ((start_bit + 7) & ~7UL); i++)
-               ext4_set_bit(i, bitmap);
-       if (i < end_bit)
-               memset(bitmap + (i >> 3), 0xff, (end_bit - i) >> 3);
-}
-
-/*
 * Set up the block and inode bitmaps, and the inode table for the new group.
 * This doesn't need to be part of the main transaction, since we are only
 * changing blocks outside the actual filesystem.  We still do journaling to
-
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to