--- busybox.orig/include/usage.h	Tue Oct 20 06:03:08 2009
+++ busybox/include/usage.h	Tue Oct 20 08:05:41 2009
@@ -2733,6 +2733,7 @@
 /*   "\n	-F		Force (ignore sanity checks)" */ \
 /*   "\n	-g num		Number of blocks in a block group" */ \
      "\n	-i BYTES	The bytes/inode ratio" \
+     "\n	-I BYTES	Inode size in bytes" \
 /*   "\n	-j		Create a journal (ext3)" */ \
 /*   "\n	-J opts		Set journal options (size/device)" */ \
 /*   "\n	-l file		Read bad blocks list from file" */ \
--- busybox.orig/util-linux/mkfs_ext2.c	Tue Oct 20 06:03:08 2009
+++ busybox/util-linux/mkfs_ext2.c	Tue Oct 20 08:34:35 2009
@@ -159,7 +159,7 @@
 	OPT_b = 1 << 2,		// block size, in bytes
 	OPT_f = 1 << 3,
 	OPT_i = 1 << 4,		// bytes per inode
-	OPT_I = 1 << 5,
+	OPT_I = 1 << 5,		// custom inode size, in bytes
 	OPT_J = 1 << 6,
 	OPT_G = 1 << 7,
 	OPT_N = 1 << 8,
@@ -188,6 +188,7 @@
 	unsigned i, pos, n;
 	unsigned bs, bpi;
 	unsigned blocksize, blocksize_log2;
+	unsigned inodesize = sizeof(struct ext2_inode);
 	unsigned reserved_percent = 5;
 	unsigned long long kilobytes;
 	uint32_t nblocks, nblocks_full;
@@ -211,7 +212,7 @@
 
 	opt_complementary = "-1:b+:m+:i+";
 	opts = getopt32(argv, "cl:b:f:i:I:J:G:N:m:o:g:L:M:O:r:E:T:U:jnqvFS",
-		NULL, &bs, NULL, &bpi, NULL, NULL, NULL, NULL,
+		NULL, &bs, NULL, &bpi, &inodesize, NULL, NULL, NULL,
 		&reserved_percent, NULL, NULL, &label, NULL, NULL, NULL, NULL, NULL, NULL);
 	argv += optind; // argv[0] -- device
 
@@ -241,6 +242,15 @@
 		kilobytes = (uoff_t)xlseek(fd, 0, SEEK_END) / 1024;
 	}
 
+	// check inode size sanity
+	if (inodesize < sizeof(*inode)
+	 || (inodesize & (inodesize - 1)) // not power of 2
+	) {
+		bb_error_msg("-%c is bad", 'I');
+		opts &= ~OPT_I; // fall back to default
+	}
+
+	// setup default parameters
 	bytes_per_inode = 16384;
 	if (kilobytes < 512*1024)
 		bytes_per_inode = 4096;
@@ -252,8 +262,11 @@
 	// Determine block size
 	// block size is a multiple of 1024
 	blocksize = 1024;
-	if (kilobytes >= 512*1024) // mke2fs 1.41.9 compat
+	if (kilobytes >= 512*1024) { // mke2fs 1.41.9 compat
 		blocksize = 4096;
+		if (!(opts & OPT_I))
+			inodesize = 256;
+	}
 	if (EXT2_MAX_BLOCK_SIZE > 4096) {
 		// kilobytes >> 22 == size in 4gigabyte chunks.
 		// if size >= 16k gigs, blocksize must be increased.
@@ -269,6 +282,7 @@
 	) {
 		bb_error_msg_and_die("blocksize %u is bad", blocksize);
 	}
+
 	if ((int32_t)bytes_per_inode < blocksize)
 		bb_error_msg_and_die("-%c is bad", 'i');
 	// number of bits in one block, i.e. 8*blocksize
@@ -340,14 +354,10 @@
 		if (inodes_per_group > blocks_per_group)
 			inodes_per_group = blocks_per_group;
 		// adjust inodes per group so they completely fill the inode table blocks in the descriptor
-//incompatibility on images >= 0.5GB:
-//difference in sizeof(*inode) sometimes
-//results in slightly bigger inodes_per_group here
-//compared to standard mke2fs:
-		inodes_per_group = (div_roundup(inodes_per_group * sizeof(*inode), blocksize) * blocksize) / sizeof(*inode);
+		inodes_per_group = (div_roundup(inodes_per_group * inodesize, blocksize) * blocksize) / inodesize;
 		// make sure the number of inodes per group is a multiple of 8
 		inodes_per_group &= ~7;
-		inode_table_blocks = div_roundup(inodes_per_group * sizeof(*inode), blocksize);
+		inode_table_blocks = div_roundup(inodes_per_group * inodesize, blocksize);
 
 		// to be useful, lost+found should occupy at least 2 blocks (but not exceeding 16*1024 bytes),
 		// and at most EXT2_NDIR_BLOCKS. So reserve these blocks right now
@@ -434,12 +444,11 @@
 
 	// fill the superblock
 	sb = xzalloc(1024);
-	STORE_LE(sb->s_rev_level, 1); // revision 1 filesystem
+	STORE_LE(sb->s_rev_level, EXT2_DYNAMIC_REV); // revision 1 filesystem
 	STORE_LE(sb->s_magic, EXT2_SUPER_MAGIC);
-//incompatibility:
-//on images > 0.5GB, standard mke2fs uses 256 byte inodes.
-//we always use 128 byte ones:
-	STORE_LE(sb->s_inode_size, sizeof(*inode));
+	STORE_LE(sb->s_inode_size, inodesize);
+	if (inodesize != sizeof(*inode))
+		STORE_LE(sb->s_reserved[21], 0x001C001C); // 28 extra bytes for "large" inode
 	STORE_LE(sb->s_first_ino, EXT2_GOOD_OLD_FIRST_INO);
 	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);
@@ -592,8 +601,8 @@
 	// dump root dir inode
 	STORE_LE(inode->i_links_count, 3); // "/.", "/..", "/lost+found/.." point to this inode
 	STORE_LE(inode->i_block[0], FETCH_LE32(gd[0].bg_inode_table) + inode_table_blocks);
-	PUT(((uint64_t)FETCH_LE32(gd[0].bg_inode_table) * blocksize) + (EXT2_ROOT_INO-1) * sizeof(*inode),
-				buf, sizeof(*inode));
+	PUT(((uint64_t)FETCH_LE32(gd[0].bg_inode_table) * blocksize) + (EXT2_ROOT_INO-1) * inodesize,
+				buf, inodesize);
 
 	// dump lost+found dir inode
 	STORE_LE(inode->i_links_count, 2); // both "/lost+found" and "/lost+found/." point to this inode
@@ -603,8 +612,8 @@
 	for (i = 0; i < lost_and_found_blocks; ++i)
 		STORE_LE(inode->i_block[i], i + n); // use next block
 //bb_info_msg("LAST BLOCK USED[%u]", i + n);
-	PUT(((uint64_t)FETCH_LE32(gd[0].bg_inode_table) * blocksize) + (EXT2_GOOD_OLD_FIRST_INO-1) * sizeof(*inode),
-				buf, sizeof(*inode));
+	PUT(((uint64_t)FETCH_LE32(gd[0].bg_inode_table) * blocksize) + (EXT2_GOOD_OLD_FIRST_INO-1) * inodesize,
+				buf, inodesize);
 
 	// dump directories
 	memset(buf, 0, blocksize);
