[git commit master] mkfs_ext2: further work on small images

Denys Vlasenko vda.linux at googlemail.com
Tue Oct 20 15:47:23 UTC 2009


commit: http://git.busybox.net/busybox/commit/?id=c708a6d000fb26d17773dfdf0bee96d433f18b08
branch: http://git.busybox.net/busybox/commit/?id=refs/heads/master

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 util-linux/mkfs_ext2.c       |   31 +++++++++++++++++--------------
 util-linux/mkfs_ext2_test.sh |   41 ++++++++++++++++++++---------------------
 2 files changed, 37 insertions(+), 35 deletions(-)

diff --git a/util-linux/mkfs_ext2.c b/util-linux/mkfs_ext2.c
index 380312b..f3359c5 100644
--- a/util-linux/mkfs_ext2.c
+++ b/util-linux/mkfs_ext2.c
@@ -179,7 +179,7 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
 	uint32_t nblocks, nblocks_full, nreserved;
 	uint32_t ngroups;
 	uint32_t bytes_per_inode;
-	uint32_t first_data_block;
+	uint32_t first_block;
 	uint32_t inodes_per_group;
 	uint32_t gdtsz, itsz;
 	time_t timestamp;
@@ -247,7 +247,7 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
 	}
 	// number of bits in one block, i.e. 8*blocksize
 #define blocks_per_group (8 * blocksize)
-	first_data_block = (EXT2_MIN_BLOCK_SIZE == blocksize);
+	first_block = (EXT2_MIN_BLOCK_SIZE == blocksize);
 	blocksize_log2 = int_log2(blocksize);
 
 	// Determine number of blocks
@@ -278,7 +278,7 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
 	// Note: blocksize and bytes_per_inode are never recalculated.
  retry:
 	// N.B. a block group can have no more than blocks_per_group blocks
-	ngroups = div_roundup(nblocks - first_data_block, blocks_per_group);
+	ngroups = div_roundup(nblocks - first_block, blocks_per_group);
 	if (0 == ngroups)
 		bb_error_msg_and_die("ngroups");
 
@@ -297,7 +297,7 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
 		uint32_t rgdtsz = 0xFFFFFFFF; // maximum block number
 		if (nblocks < rgdtsz / 1024)
 			rgdtsz = nblocks * 1024;
-		rgdtsz = div_roundup(rgdtsz - first_data_block, blocks_per_group);
+		rgdtsz = div_roundup(rgdtsz - first_block, blocks_per_group);
 		rgdtsz = div_roundup(rgdtsz, blocksize / sizeof(*gd)) - gdtsz;
 		if (rgdtsz > blocksize / sizeof(uint32_t))
 			rgdtsz = blocksize / sizeof(uint32_t);
@@ -328,17 +328,20 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
 
 		// the last group needs more attention: isn't it too small for possible overhead?
 		overhead = (has_super(ngroups - 1) ? (1/*sb*/ + gdtsz) : 0) + 1/*bbmp*/ + 1/*ibmp*/ + itsz;
-		remainder = (nblocks - first_data_block) % blocks_per_group;
+		remainder = (nblocks - first_block) % blocks_per_group;
 		if ((1 == ngroups) && remainder && (remainder < overhead))
 			bb_error_msg_and_die("way small device");
-		if (remainder && (remainder < overhead + 50/* e2fsprogs hardcoded */)) {
+		// Standard mke2fs uses 50. Looks like a bug in our calculation
+		// of "remainder" or "overhead" - we dont match standard mke2fs
+		// when we transition from one group to two groups (a bit after 8M
+		// image size) and for two->three groups transition (at 16M) too.
+		if (remainder && (remainder < overhead + 50)) {
 //bb_info_msg("CHOP[%u]", remainder);
 			nblocks -= remainder;
 			goto retry;
 		}
 	}
 
-	// print info
 	if (nblocks_full - nblocks)
 		printf("warning: %u blocks unused\n\n", nblocks_full - nblocks);
 	printf(
@@ -358,7 +361,7 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
 		, blocksize, blocksize_log2 - EXT2_MIN_BLOCK_LOG_SIZE
 		, inodes_per_group * ngroups, nblocks
 		, nreserved, reserved_percent
-		, first_data_block
+		, first_block
 		, gdtsz * (blocksize / sizeof(*gd)) * blocks_per_group
 		, ngroups
 		, blocks_per_group, blocks_per_group
@@ -367,7 +370,7 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
 	{
 		const char *fmt = "\nSuperblock backups stored on blocks:\n"
 			"\t%u";
-		pos = first_data_block;
+		pos = first_block;
 		for (i = 1; i < ngroups; i++) {
 			pos += blocks_per_group;
 			if (has_super(i)) {
@@ -399,8 +402,8 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
 	STORE_LE(sb->s_log_block_size, blocksize_log2 - EXT2_MIN_BLOCK_LOG_SIZE);
 	STORE_LE(sb->s_log_frag_size, blocksize_log2 - EXT2_MIN_BLOCK_LOG_SIZE);
 	// first 1024 bytes of the device are for boot record. If block size is 1024 bytes, then
-	// the first block available for data is 1, otherwise 0
-	STORE_LE(sb->s_first_data_block, first_data_block); // 0 or 1
+	// the first block is 1, otherwise 0
+	STORE_LE(sb->s_first_data_block, first_block);
 	// block and inode bitmaps occupy no more than one block, so maximum number of blocks is
 	STORE_LE(sb->s_blocks_per_group, blocks_per_group);
 	STORE_LE(sb->s_frags_per_group, blocks_per_group);
@@ -450,7 +453,7 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
 	gd = xzalloc(gdtsz * blocksize);
 	buf = xmalloc(blocksize);
 	sb->s_free_blocks_count = 0;
-	for (i = 0, pos = first_data_block, n = nblocks - first_data_block;
+	for (i = 0, pos = first_block, n = nblocks - first_block;
 		i < ngroups;
 		i++, pos += blocks_per_group, n -= blocks_per_group
 	) {
@@ -498,11 +501,11 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
 
 	// dump filesystem skeleton structures
 //	printf("Writing superblocks and filesystem accounting information: ");
-	for (i = 0, pos = first_data_block; i < ngroups; i++, pos += blocks_per_group) {
+	for (i = 0, pos = first_block; i < ngroups; i++, pos += blocks_per_group) {
 		// dump superblock and group descriptors and their backups
 		if (has_super(i)) {
 			// N.B. 1024 byte blocks are special
-			PUT(((uint64_t)pos * blocksize) + ((0 == i && 0 == first_data_block) ? 1024 : 0), sb, 1024);//blocksize);
+			PUT(((uint64_t)pos * blocksize) + ((0 == i && 0 == first_block) ? 1024 : 0), sb, 1024);//blocksize);
 			PUT(((uint64_t)pos * blocksize) + blocksize, gd, gdtsz * blocksize);
 		}
 	}
diff --git a/util-linux/mkfs_ext2_test.sh b/util-linux/mkfs_ext2_test.sh
index 4bc5f1e..a636de5 100755
--- a/util-linux/mkfs_ext2_test.sh
+++ b/util-linux/mkfs_ext2_test.sh
@@ -45,31 +45,30 @@ test_mke2fs() {
 
 # -:bbox +:standard
 
-# kilobytes=60 is the minimal allowed size.
-#
-# kilobytes=8378 is the first value where we differ from std:
-# +warning: 185 blocks unused
-#  Filesystem label=
-#  OS type: Linux
-#  Block size=1024 (log=0)
-#  Fragment size=1024 (log=0)
-# -2096 inodes, 8378 blocks
-# +2096 inodes, 8193 blocks
-#  418 blocks reserved for the super user
-#  First data block=1
-# -2 block groups
-# +1 block groups
-#  8192 blocks per group, 8192 fragments per group
-# -1048 inodes per group
-# -Superblock backups stored on blocks:
-# -8193
-# +2096 inodes per group
-#
+# kilobytes=60 is the minimal allowed size
 kilobytes=60
 while true; do
     test_mke2fs || exit 1
     : $((kilobytes++))
-    test $kilobytes = 300000 && break
+    test $kilobytes = 200 && break
+done
+
+# Transition from one block group to two
+# fails in [8378..8410] range
+kilobytes=$((8*1024 - 20))
+while true; do
+    test_mke2fs #|| exit 1
+    : $((kilobytes++))
+    test $kilobytes = $((8*1024 + 300)) && break
+done
+
+# Transition from two block groups to three
+# works
+kilobytes=$((16*1024 - 40))
+while true; do
+    test_mke2fs || exit 1
+    : $((kilobytes++))
+    test $kilobytes = $((16*1024 + 500)) && break
 done
 exit
 
-- 
1.6.3.3



More information about the busybox-cvs mailing list