mkfs_ext2: further work on small images

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2009-10-20 17:47:23 +02:00
parent 82d6433abe
commit c708a6d000
2 changed files with 37 additions and 35 deletions

View File

@ -179,7 +179,7 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
uint32_t nblocks, nblocks_full, nreserved; uint32_t nblocks, nblocks_full, nreserved;
uint32_t ngroups; uint32_t ngroups;
uint32_t bytes_per_inode; uint32_t bytes_per_inode;
uint32_t first_data_block; uint32_t first_block;
uint32_t inodes_per_group; uint32_t inodes_per_group;
uint32_t gdtsz, itsz; uint32_t gdtsz, itsz;
time_t timestamp; 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 // number of bits in one block, i.e. 8*blocksize
#define blocks_per_group (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); blocksize_log2 = int_log2(blocksize);
// Determine number of blocks // 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. // Note: blocksize and bytes_per_inode are never recalculated.
retry: retry:
// N.B. a block group can have no more than blocks_per_group blocks // 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) if (0 == ngroups)
bb_error_msg_and_die("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 uint32_t rgdtsz = 0xFFFFFFFF; // maximum block number
if (nblocks < rgdtsz / 1024) if (nblocks < rgdtsz / 1024)
rgdtsz = nblocks * 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; rgdtsz = div_roundup(rgdtsz, blocksize / sizeof(*gd)) - gdtsz;
if (rgdtsz > blocksize / sizeof(uint32_t)) if (rgdtsz > blocksize / sizeof(uint32_t))
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? // 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; 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)) if ((1 == ngroups) && remainder && (remainder < overhead))
bb_error_msg_and_die("way small device"); 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); //bb_info_msg("CHOP[%u]", remainder);
nblocks -= remainder; nblocks -= remainder;
goto retry; goto retry;
} }
} }
// print info
if (nblocks_full - nblocks) if (nblocks_full - nblocks)
printf("warning: %u blocks unused\n\n", nblocks_full - nblocks); printf("warning: %u blocks unused\n\n", nblocks_full - nblocks);
printf( printf(
@ -358,7 +361,7 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
, blocksize, blocksize_log2 - EXT2_MIN_BLOCK_LOG_SIZE , blocksize, blocksize_log2 - EXT2_MIN_BLOCK_LOG_SIZE
, inodes_per_group * ngroups, nblocks , inodes_per_group * ngroups, nblocks
, nreserved, reserved_percent , nreserved, reserved_percent
, first_data_block , first_block
, gdtsz * (blocksize / sizeof(*gd)) * blocks_per_group , gdtsz * (blocksize / sizeof(*gd)) * blocks_per_group
, ngroups , ngroups
, blocks_per_group, blocks_per_group , 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" const char *fmt = "\nSuperblock backups stored on blocks:\n"
"\t%u"; "\t%u";
pos = first_data_block; pos = first_block;
for (i = 1; i < ngroups; i++) { for (i = 1; i < ngroups; i++) {
pos += blocks_per_group; pos += blocks_per_group;
if (has_super(i)) { 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_block_size, blocksize_log2 - EXT2_MIN_BLOCK_LOG_SIZE);
STORE_LE(sb->s_log_frag_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 // 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 // the first block is 1, otherwise 0
STORE_LE(sb->s_first_data_block, first_data_block); // 0 or 1 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 // 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_blocks_per_group, blocks_per_group);
STORE_LE(sb->s_frags_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); gd = xzalloc(gdtsz * blocksize);
buf = xmalloc(blocksize); buf = xmalloc(blocksize);
sb->s_free_blocks_count = 0; 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 < ngroups;
i++, pos += blocks_per_group, n -= blocks_per_group 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 // dump filesystem skeleton structures
// printf("Writing superblocks and filesystem accounting information: "); // 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 // dump superblock and group descriptors and their backups
if (has_super(i)) { if (has_super(i)) {
// N.B. 1024 byte blocks are special // 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); PUT(((uint64_t)pos * blocksize) + blocksize, gd, gdtsz * blocksize);
} }
} }

View File

@ -45,31 +45,30 @@ test_mke2fs() {
# -:bbox +:standard # -:bbox +:standard
# kilobytes=60 is the minimal allowed size. # 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 kilobytes=60
while true; do while true; do
test_mke2fs || exit 1 test_mke2fs || exit 1
: $((kilobytes++)) : $((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 done
exit exit