aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2009-10-20 17:47:23 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2009-10-20 17:47:23 +0200
commitc708a6d000fb26d17773dfdf0bee96d433f18b08 (patch)
treeb08a3e247ee905736c5aaaec66c54c0a70699083
parent82d6433abe251d8d7a43417af392b638f868afe5 (diff)
downloadbusybox-w32-c708a6d000fb26d17773dfdf0bee96d433f18b08.tar.gz
busybox-w32-c708a6d000fb26d17773dfdf0bee96d433f18b08.tar.bz2
busybox-w32-c708a6d000fb26d17773dfdf0bee96d433f18b08.zip
mkfs_ext2: further work on small images
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--util-linux/mkfs_ext2.c31
-rwxr-xr-xutil-linux/mkfs_ext2_test.sh41
2 files changed, 37 insertions, 35 deletions
diff --git a/util-linux/mkfs_ext2.c b/util-linux/mkfs_ext2.c
index 380312bca..f3359c5fa 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)
179 uint32_t nblocks, nblocks_full, nreserved; 179 uint32_t nblocks, nblocks_full, nreserved;
180 uint32_t ngroups; 180 uint32_t ngroups;
181 uint32_t bytes_per_inode; 181 uint32_t bytes_per_inode;
182 uint32_t first_data_block; 182 uint32_t first_block;
183 uint32_t inodes_per_group; 183 uint32_t inodes_per_group;
184 uint32_t gdtsz, itsz; 184 uint32_t gdtsz, itsz;
185 time_t timestamp; 185 time_t timestamp;
@@ -247,7 +247,7 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
247 } 247 }
248 // number of bits in one block, i.e. 8*blocksize 248 // number of bits in one block, i.e. 8*blocksize
249#define blocks_per_group (8 * blocksize) 249#define blocks_per_group (8 * blocksize)
250 first_data_block = (EXT2_MIN_BLOCK_SIZE == blocksize); 250 first_block = (EXT2_MIN_BLOCK_SIZE == blocksize);
251 blocksize_log2 = int_log2(blocksize); 251 blocksize_log2 = int_log2(blocksize);
252 252
253 // Determine number of blocks 253 // Determine number of blocks
@@ -278,7 +278,7 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
278 // Note: blocksize and bytes_per_inode are never recalculated. 278 // Note: blocksize and bytes_per_inode are never recalculated.
279 retry: 279 retry:
280 // N.B. a block group can have no more than blocks_per_group blocks 280 // N.B. a block group can have no more than blocks_per_group blocks
281 ngroups = div_roundup(nblocks - first_data_block, blocks_per_group); 281 ngroups = div_roundup(nblocks - first_block, blocks_per_group);
282 if (0 == ngroups) 282 if (0 == ngroups)
283 bb_error_msg_and_die("ngroups"); 283 bb_error_msg_and_die("ngroups");
284 284
@@ -297,7 +297,7 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
297 uint32_t rgdtsz = 0xFFFFFFFF; // maximum block number 297 uint32_t rgdtsz = 0xFFFFFFFF; // maximum block number
298 if (nblocks < rgdtsz / 1024) 298 if (nblocks < rgdtsz / 1024)
299 rgdtsz = nblocks * 1024; 299 rgdtsz = nblocks * 1024;
300 rgdtsz = div_roundup(rgdtsz - first_data_block, blocks_per_group); 300 rgdtsz = div_roundup(rgdtsz - first_block, blocks_per_group);
301 rgdtsz = div_roundup(rgdtsz, blocksize / sizeof(*gd)) - gdtsz; 301 rgdtsz = div_roundup(rgdtsz, blocksize / sizeof(*gd)) - gdtsz;
302 if (rgdtsz > blocksize / sizeof(uint32_t)) 302 if (rgdtsz > blocksize / sizeof(uint32_t))
303 rgdtsz = blocksize / sizeof(uint32_t); 303 rgdtsz = blocksize / sizeof(uint32_t);
@@ -328,17 +328,20 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
328 328
329 // the last group needs more attention: isn't it too small for possible overhead? 329 // the last group needs more attention: isn't it too small for possible overhead?
330 overhead = (has_super(ngroups - 1) ? (1/*sb*/ + gdtsz) : 0) + 1/*bbmp*/ + 1/*ibmp*/ + itsz; 330 overhead = (has_super(ngroups - 1) ? (1/*sb*/ + gdtsz) : 0) + 1/*bbmp*/ + 1/*ibmp*/ + itsz;
331 remainder = (nblocks - first_data_block) % blocks_per_group; 331 remainder = (nblocks - first_block) % blocks_per_group;
332 if ((1 == ngroups) && remainder && (remainder < overhead)) 332 if ((1 == ngroups) && remainder && (remainder < overhead))
333 bb_error_msg_and_die("way small device"); 333 bb_error_msg_and_die("way small device");
334 if (remainder && (remainder < overhead + 50/* e2fsprogs hardcoded */)) { 334 // Standard mke2fs uses 50. Looks like a bug in our calculation
335 // of "remainder" or "overhead" - we dont match standard mke2fs
336 // when we transition from one group to two groups (a bit after 8M
337 // image size) and for two->three groups transition (at 16M) too.
338 if (remainder && (remainder < overhead + 50)) {
335//bb_info_msg("CHOP[%u]", remainder); 339//bb_info_msg("CHOP[%u]", remainder);
336 nblocks -= remainder; 340 nblocks -= remainder;
337 goto retry; 341 goto retry;
338 } 342 }
339 } 343 }
340 344
341 // print info
342 if (nblocks_full - nblocks) 345 if (nblocks_full - nblocks)
343 printf("warning: %u blocks unused\n\n", nblocks_full - nblocks); 346 printf("warning: %u blocks unused\n\n", nblocks_full - nblocks);
344 printf( 347 printf(
@@ -358,7 +361,7 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
358 , blocksize, blocksize_log2 - EXT2_MIN_BLOCK_LOG_SIZE 361 , blocksize, blocksize_log2 - EXT2_MIN_BLOCK_LOG_SIZE
359 , inodes_per_group * ngroups, nblocks 362 , inodes_per_group * ngroups, nblocks
360 , nreserved, reserved_percent 363 , nreserved, reserved_percent
361 , first_data_block 364 , first_block
362 , gdtsz * (blocksize / sizeof(*gd)) * blocks_per_group 365 , gdtsz * (blocksize / sizeof(*gd)) * blocks_per_group
363 , ngroups 366 , ngroups
364 , blocks_per_group, blocks_per_group 367 , blocks_per_group, blocks_per_group
@@ -367,7 +370,7 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
367 { 370 {
368 const char *fmt = "\nSuperblock backups stored on blocks:\n" 371 const char *fmt = "\nSuperblock backups stored on blocks:\n"
369 "\t%u"; 372 "\t%u";
370 pos = first_data_block; 373 pos = first_block;
371 for (i = 1; i < ngroups; i++) { 374 for (i = 1; i < ngroups; i++) {
372 pos += blocks_per_group; 375 pos += blocks_per_group;
373 if (has_super(i)) { 376 if (has_super(i)) {
@@ -399,8 +402,8 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
399 STORE_LE(sb->s_log_block_size, blocksize_log2 - EXT2_MIN_BLOCK_LOG_SIZE); 402 STORE_LE(sb->s_log_block_size, blocksize_log2 - EXT2_MIN_BLOCK_LOG_SIZE);
400 STORE_LE(sb->s_log_frag_size, blocksize_log2 - EXT2_MIN_BLOCK_LOG_SIZE); 403 STORE_LE(sb->s_log_frag_size, blocksize_log2 - EXT2_MIN_BLOCK_LOG_SIZE);
401 // first 1024 bytes of the device are for boot record. If block size is 1024 bytes, then 404 // first 1024 bytes of the device are for boot record. If block size is 1024 bytes, then
402 // the first block available for data is 1, otherwise 0 405 // the first block is 1, otherwise 0
403 STORE_LE(sb->s_first_data_block, first_data_block); // 0 or 1 406 STORE_LE(sb->s_first_data_block, first_block);
404 // block and inode bitmaps occupy no more than one block, so maximum number of blocks is 407 // block and inode bitmaps occupy no more than one block, so maximum number of blocks is
405 STORE_LE(sb->s_blocks_per_group, blocks_per_group); 408 STORE_LE(sb->s_blocks_per_group, blocks_per_group);
406 STORE_LE(sb->s_frags_per_group, blocks_per_group); 409 STORE_LE(sb->s_frags_per_group, blocks_per_group);
@@ -450,7 +453,7 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
450 gd = xzalloc(gdtsz * blocksize); 453 gd = xzalloc(gdtsz * blocksize);
451 buf = xmalloc(blocksize); 454 buf = xmalloc(blocksize);
452 sb->s_free_blocks_count = 0; 455 sb->s_free_blocks_count = 0;
453 for (i = 0, pos = first_data_block, n = nblocks - first_data_block; 456 for (i = 0, pos = first_block, n = nblocks - first_block;
454 i < ngroups; 457 i < ngroups;
455 i++, pos += blocks_per_group, n -= blocks_per_group 458 i++, pos += blocks_per_group, n -= blocks_per_group
456 ) { 459 ) {
@@ -498,11 +501,11 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
498 501
499 // dump filesystem skeleton structures 502 // dump filesystem skeleton structures
500// printf("Writing superblocks and filesystem accounting information: "); 503// printf("Writing superblocks and filesystem accounting information: ");
501 for (i = 0, pos = first_data_block; i < ngroups; i++, pos += blocks_per_group) { 504 for (i = 0, pos = first_block; i < ngroups; i++, pos += blocks_per_group) {
502 // dump superblock and group descriptors and their backups 505 // dump superblock and group descriptors and their backups
503 if (has_super(i)) { 506 if (has_super(i)) {
504 // N.B. 1024 byte blocks are special 507 // N.B. 1024 byte blocks are special
505 PUT(((uint64_t)pos * blocksize) + ((0 == i && 0 == first_data_block) ? 1024 : 0), sb, 1024);//blocksize); 508 PUT(((uint64_t)pos * blocksize) + ((0 == i && 0 == first_block) ? 1024 : 0), sb, 1024);//blocksize);
506 PUT(((uint64_t)pos * blocksize) + blocksize, gd, gdtsz * blocksize); 509 PUT(((uint64_t)pos * blocksize) + blocksize, gd, gdtsz * blocksize);
507 } 510 }
508 } 511 }
diff --git a/util-linux/mkfs_ext2_test.sh b/util-linux/mkfs_ext2_test.sh
index 4bc5f1ea9..a636de561 100755
--- a/util-linux/mkfs_ext2_test.sh
+++ b/util-linux/mkfs_ext2_test.sh
@@ -45,31 +45,30 @@ test_mke2fs() {
45 45
46# -:bbox +:standard 46# -:bbox +:standard
47 47
48# kilobytes=60 is the minimal allowed size. 48# kilobytes=60 is the minimal allowed size
49#
50# kilobytes=8378 is the first value where we differ from std:
51# +warning: 185 blocks unused
52# Filesystem label=
53# OS type: Linux
54# Block size=1024 (log=0)
55# Fragment size=1024 (log=0)
56# -2096 inodes, 8378 blocks
57# +2096 inodes, 8193 blocks
58# 418 blocks reserved for the super user
59# First data block=1
60# -2 block groups
61# +1 block groups
62# 8192 blocks per group, 8192 fragments per group
63# -1048 inodes per group
64# -Superblock backups stored on blocks:
65# -8193
66# +2096 inodes per group
67#
68kilobytes=60 49kilobytes=60
69while true; do 50while true; do
70 test_mke2fs || exit 1 51 test_mke2fs || exit 1
71 : $((kilobytes++)) 52 : $((kilobytes++))
72 test $kilobytes = 300000 && break 53 test $kilobytes = 200 && break
54done
55
56# Transition from one block group to two
57# fails in [8378..8410] range
58kilobytes=$((8*1024 - 20))
59while true; do
60 test_mke2fs #|| exit 1
61 : $((kilobytes++))
62 test $kilobytes = $((8*1024 + 300)) && break
63done
64
65# Transition from two block groups to three
66# works
67kilobytes=$((16*1024 - 40))
68while true; do
69 test_mke2fs || exit 1
70 : $((kilobytes++))
71 test $kilobytes = $((16*1024 + 500)) && break
73done 72done
74exit 73exit
75 74