diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2009-10-20 17:47:23 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2009-10-20 17:47:23 +0200 |
commit | c708a6d000fb26d17773dfdf0bee96d433f18b08 (patch) | |
tree | b08a3e247ee905736c5aaaec66c54c0a70699083 | |
parent | 82d6433abe251d8d7a43417af392b638f868afe5 (diff) | |
download | busybox-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.c | 31 | ||||
-rwxr-xr-x | 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 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 | # | ||
68 | kilobytes=60 | 49 | kilobytes=60 |
69 | while true; do | 50 | while 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 |
54 | done | ||
55 | |||
56 | # Transition from one block group to two | ||
57 | # fails in [8378..8410] range | ||
58 | kilobytes=$((8*1024 - 20)) | ||
59 | while true; do | ||
60 | test_mke2fs #|| exit 1 | ||
61 | : $((kilobytes++)) | ||
62 | test $kilobytes = $((8*1024 + 300)) && break | ||
63 | done | ||
64 | |||
65 | # Transition from two block groups to three | ||
66 | # works | ||
67 | kilobytes=$((16*1024 - 40)) | ||
68 | while true; do | ||
69 | test_mke2fs || exit 1 | ||
70 | : $((kilobytes++)) | ||
71 | test $kilobytes = $((16*1024 + 500)) && break | ||
73 | done | 72 | done |
74 | exit | 73 | exit |
75 | 74 | ||