update uninitialized-block-groups.patch and mballoc-core.patch

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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 majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Reiser Filesystem Development]     [Ceph FS]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux FS]     [Yosemite National Park]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Device Mapper]     [Linux Media]

  Powered by Linux