aboutsummaryrefslogtreecommitdiff
path: root/util-linux/mkfs_ext2.c
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2009-10-20 13:34:16 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2009-10-20 13:34:16 +0200
commit95484c870645ebda34c9202799f3b31111b90e4f (patch)
tree0de582e09d00aa666be04c391ec8abba41afb03d /util-linux/mkfs_ext2.c
parent69f2e2cdeba8237d51fe63aa32efbd178ce02663 (diff)
downloadbusybox-w32-95484c870645ebda34c9202799f3b31111b90e4f.tar.gz
busybox-w32-95484c870645ebda34c9202799f3b31111b90e4f.tar.bz2
busybox-w32-95484c870645ebda34c9202799f3b31111b90e4f.zip
mkfs_ext2: further work by Vladimir
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'util-linux/mkfs_ext2.c')
-rw-r--r--util-linux/mkfs_ext2.c78
1 files changed, 39 insertions, 39 deletions
diff --git a/util-linux/mkfs_ext2.c b/util-linux/mkfs_ext2.c
index e840f7810..da27dc77d 100644
--- a/util-linux/mkfs_ext2.c
+++ b/util-linux/mkfs_ext2.c
@@ -173,9 +173,9 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
173 unsigned i, pos, n; 173 unsigned i, pos, n;
174 unsigned bs, bpi; 174 unsigned bs, bpi;
175 unsigned blocksize, blocksize_log2; 175 unsigned blocksize, blocksize_log2;
176 unsigned nreserved = 5; 176 unsigned reserved_percent = 5;
177 unsigned long long kilobytes; 177 unsigned long long kilobytes;
178 uint32_t nblocks, nblocks_full; 178 uint32_t nblocks, nblocks_full, nreserved;
179 uint32_t ngroups; 179 uint32_t ngroups;
180 uint32_t bytes_per_inode; 180 uint32_t bytes_per_inode;
181 uint32_t first_data_block; 181 uint32_t first_data_block;
@@ -194,13 +194,9 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
194 opt_complementary = "-1:b+:m+:i+"; 194 opt_complementary = "-1:b+:m+:i+";
195 opts = getopt32(argv, "cl:b:f:i:I:J:G:N:m:o:g:L:M:O:r:E:T:U:jnqvFS", 195 opts = getopt32(argv, "cl:b:f:i:I:J:G:N:m:o:g:L:M:O:r:E:T:U:jnqvFS",
196 NULL, &bs, NULL, &bpi, NULL, NULL, NULL, NULL, 196 NULL, &bs, NULL, &bpi, NULL, NULL, NULL, NULL,
197 &nreserved, NULL, NULL, &label, NULL, NULL, NULL, NULL, NULL, NULL); 197 &reserved_percent, NULL, NULL, &label, NULL, NULL, NULL, NULL, NULL, NULL);
198 argv += optind; // argv[0] -- device 198 argv += optind; // argv[0] -- device
199 199
200 // reserved blocks percentage
201 if (nreserved > 50)
202 bb_error_msg_and_die("-%c is bad", 'm');
203
204 // check the device is a block device 200 // check the device is a block device
205 xmove_fd(xopen(argv[0], O_WRONLY), fd); 201 xmove_fd(xopen(argv[0], O_WRONLY), fd);
206 fstat(fd, &st); 202 fstat(fd, &st);
@@ -228,14 +224,15 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
228 if (opts & OPT_i) 224 if (opts & OPT_i)
229 bytes_per_inode = bpi; 225 bytes_per_inode = bpi;
230 226
227 // Determine block size
231 // block size is a multiple of 1024 228 // block size is a multiple of 1024
232 blocksize = 1024; 229 blocksize = 1024;
233 if (kilobytes >= 512*1024) // mke2fs 1.41.9 compat 230 if (kilobytes >= 512*1024) // mke2fs 1.41.9 compat
234 blocksize = 4096; 231 blocksize = 4096;
235 if (EXT2_MAX_BLOCK_SIZE > 4096) { 232 if (EXT2_MAX_BLOCK_SIZE > 4096) {
236 // kilobytes >> 22 == size in 4gigabyte chunks. 233 // kilobytes >> 22 == size in 4gigabyte chunks.
237 // if it is >= 16k gigs, blocksize must be increased. 234 // if size >= 16k gigs, blocksize must be increased.
238 // Try "mke2fs -F image_std $((16 * 1024*1024*1024))" 235 // Try "mke2fs -F image $((16 * 1024*1024*1024))"
239 while ((kilobytes >> 22) >= blocksize) 236 while ((kilobytes >> 22) >= blocksize)
240 blocksize *= 2; 237 blocksize *= 2;
241 } 238 }
@@ -247,28 +244,38 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
247 ) { 244 ) {
248 bb_error_msg_and_die("blocksize %u is bad", blocksize); 245 bb_error_msg_and_die("blocksize %u is bad", blocksize);
249 } 246 }
247 // number of bits in one block, i.e. 8*blocksize
248#define blocks_per_group (8 * blocksize)
249 first_data_block = (EXT2_MIN_BLOCK_SIZE == blocksize);
250 blocksize_log2 = int_log2(blocksize); 250 blocksize_log2 = int_log2(blocksize);
251
252 // Determine number of blocks
251 kilobytes >>= (blocksize_log2 - EXT2_MIN_BLOCK_LOG_SIZE); 253 kilobytes >>= (blocksize_log2 - EXT2_MIN_BLOCK_LOG_SIZE);
252 // nblocks: the total number of blocks in the filesystem
253 nblocks = kilobytes; 254 nblocks = kilobytes;
254 if (nblocks != kilobytes) 255 if (nblocks != kilobytes)
255 bb_error_msg_and_die("block count doesn't fit in 32 bits"); 256 bb_error_msg_and_die("block count doesn't fit in 32 bits");
256#define kilobytes kilobytes_unused_after_this 257#define kilobytes kilobytes_unused_after_this
257
258 if (blocksize < PAGE_SIZE) 258 if (blocksize < PAGE_SIZE)
259 nblocks &= ~((PAGE_SIZE / blocksize)-1); 259 nblocks &= ~((PAGE_SIZE >> blocksize_log2)-1);
260 // Experimentally, standard mke2fs won't work on images smaller than 60k
261 if (nblocks < 60)
262 bb_error_msg_and_die("need >= 60 blocks");
263
264 // How many reserved blocks?
265 if (reserved_percent > 50)
266 bb_error_msg_and_die("-%c is bad", 'm');
267 //nreserved = div_roundup((uint64_t) nblocks * reserved_percent, 100);
268 nreserved = (uint64_t)nblocks * reserved_percent / 100;
260 269
261 // N.B. killing e2fsprogs feature! Unused blocks don't account in calculations 270 // N.B. killing e2fsprogs feature! Unused blocks don't account in calculations
262 nblocks_full = nblocks; 271 nblocks_full = nblocks;
263 retry:
264 if (nblocks < 8)
265 bb_error_msg_and_die("need >= 8 blocks");
266
267 // number of bits in one block, i.e. 8*blocksize
268#define blocks_per_group (8 * blocksize)
269 272
273 // If last block group is too small, nblocks may be decreased in order
274 // to discard it, and control returns here to recalculate some
275 // parameters.
276 // Note: blocksize and bytes_per_inode are never recalculated.
277 retry:
270 // N.B. a block group can have no more than blocks_per_group blocks 278 // N.B. a block group can have no more than blocks_per_group blocks
271 first_data_block = (EXT2_MIN_BLOCK_SIZE == blocksize);
272 ngroups = div_roundup(nblocks - first_data_block, blocks_per_group); 279 ngroups = div_roundup(nblocks - first_data_block, blocks_per_group);
273 if (0 == ngroups) 280 if (0 == ngroups)
274 bb_error_msg_and_die("ngroups"); 281 bb_error_msg_and_die("ngroups");
@@ -308,21 +315,21 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
308 if (inodes_per_group < 16) 315 if (inodes_per_group < 16)
309 inodes_per_group = 16; 316 inodes_per_group = 16;
310 317
311 // N.B. a block group can have no more than 8*blocksize inodes 318 // a block group can have no more than 8*blocksize inodes
312 if (inodes_per_group > blocks_per_group) 319 if (inodes_per_group > blocks_per_group)
313 inodes_per_group = blocks_per_group; 320 inodes_per_group = blocks_per_group;
314 // adjust inodes per group so they completely fill the inode table blocks in the descriptor 321 // adjust inodes per group so they completely fill the inode table blocks in the descriptor
315 inodes_per_group = (div_roundup(inodes_per_group * sizeof(*inode), blocksize) << blocksize_log2) / sizeof(*inode); 322 inodes_per_group = (div_roundup(inodes_per_group * sizeof(*inode), blocksize) * blocksize) / sizeof(*inode);
316 // make sure the number of inodes per group is a multiple of 8 323 // make sure the number of inodes per group is a multiple of 8
317 inodes_per_group &= ~7; 324 inodes_per_group &= ~7;
318 itsz = div_roundup(inodes_per_group * sizeof(*inode), blocksize); 325 itsz = div_roundup(inodes_per_group * sizeof(*inode), blocksize);
319 326
320 // the last block needs more attention: doesn't it too small for possible overhead? 327 // the last group needs more attention: isn't it too small for possible overhead?
321 overhead = (has_super(ngroups - 1) ? (1/*sb*/ + gdtsz) : 0) + 1/*bbmp*/ + 1/*ibmp*/ + itsz; 328 overhead = (has_super(ngroups - 1) ? (1/*sb*/ + gdtsz) : 0) + 1/*bbmp*/ + 1/*ibmp*/ + itsz;
322 remainder = (nblocks - first_data_block) % blocks_per_group; 329 remainder = (nblocks - first_data_block) % blocks_per_group;
323 if ((1 == ngroups) && remainder && (remainder < overhead)) 330 if ((1 == ngroups) && remainder && (remainder < overhead))
324 bb_error_msg_and_die("way small device"); 331 bb_error_msg_and_die("way small device");
325 if (remainder && (remainder < overhead + 50)) { 332 if (remainder && (remainder < overhead + 50/* e2fsprogs hardcoded */)) {
326//bb_info_msg("CHOP[%u]", remainder); 333//bb_info_msg("CHOP[%u]", remainder);
327 nblocks -= remainder; 334 nblocks -= remainder;
328 goto retry; 335 goto retry;
@@ -348,8 +355,7 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
348 , blocksize, blocksize_log2 - EXT2_MIN_BLOCK_LOG_SIZE 355 , blocksize, blocksize_log2 - EXT2_MIN_BLOCK_LOG_SIZE
349 , blocksize, blocksize_log2 - EXT2_MIN_BLOCK_LOG_SIZE 356 , blocksize, blocksize_log2 - EXT2_MIN_BLOCK_LOG_SIZE
350 , inodes_per_group * ngroups, nblocks 357 , inodes_per_group * ngroups, nblocks
351 //, div_roundup((uint64_t) nblocks * nreserved, 100), nreserved 358 , nreserved, reserved_percent
352 , (unsigned)((uint64_t) nblocks_full * nreserved / 100), nreserved
353 , first_data_block 359 , first_data_block
354 , gdtsz * (blocksize / sizeof(*gd)) * blocks_per_group 360 , gdtsz * (blocksize / sizeof(*gd)) * blocks_per_group
355 , ngroups 361 , ngroups
@@ -399,7 +405,7 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
399 // blocks 405 // blocks
400 STORE_LE(sb->s_blocks_count, nblocks); 406 STORE_LE(sb->s_blocks_count, nblocks);
401 // reserve blocks for superuser 407 // reserve blocks for superuser
402 STORE_LE(sb->s_r_blocks_count, (uint32_t)((uint64_t) nblocks_full * nreserved / 100)); 408 STORE_LE(sb->s_r_blocks_count, nreserved);
403 // ninodes 409 // ninodes
404 STORE_LE(sb->s_inodes_per_group, inodes_per_group); 410 STORE_LE(sb->s_inodes_per_group, inodes_per_group);
405 STORE_LE(sb->s_inodes_count, inodes_per_group * ngroups); 411 STORE_LE(sb->s_inodes_count, inodes_per_group * ngroups);
@@ -418,7 +424,7 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
418 | (EXT2_FEATURE_COMPAT_RESIZE_INO * ENABLE_FEATURE_MKFS_EXT2_RESERVED_GDT) 424 | (EXT2_FEATURE_COMPAT_RESIZE_INO * ENABLE_FEATURE_MKFS_EXT2_RESERVED_GDT)
419 | (EXT2_FEATURE_COMPAT_DIR_INDEX * ENABLE_FEATURE_MKFS_EXT2_DIR_INDEX) 425 | (EXT2_FEATURE_COMPAT_DIR_INDEX * ENABLE_FEATURE_MKFS_EXT2_DIR_INDEX)
420 ); 426 );
421 // e2fsprogs-1.41.9 doesn't like EXT2_FEATURE_INCOMPAT_WHITEOUT 427 // e2fsck from 1.41.9 doesn't like EXT2_FEATURE_INCOMPAT_WHITEOUT
422 STORE_LE(sb->s_feature_incompat, EXT2_FEATURE_INCOMPAT_FILETYPE);// | EXT2_FEATURE_INCOMPAT_WHITEOUT; 428 STORE_LE(sb->s_feature_incompat, EXT2_FEATURE_INCOMPAT_FILETYPE);// | EXT2_FEATURE_INCOMPAT_WHITEOUT;
423 STORE_LE(sb->s_feature_ro_compat, EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER); 429 STORE_LE(sb->s_feature_ro_compat, EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER);
424 STORE_LE(sb->s_flags, EXT2_FLAGS_SIGNED_HASH * ENABLE_FEATURE_MKFS_EXT2_DIR_INDEX); 430 STORE_LE(sb->s_flags, EXT2_FLAGS_SIGNED_HASH * ENABLE_FEATURE_MKFS_EXT2_DIR_INDEX);
@@ -435,9 +441,8 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
435 STORE_LE(sb->s_max_mnt_count, EXT2_DFL_MAX_MNT_COUNT 441 STORE_LE(sb->s_max_mnt_count, EXT2_DFL_MAX_MNT_COUNT
436 + (sb->s_uuid[ARRAY_SIZE(sb->s_uuid)-1] % EXT2_DFL_MAX_MNT_COUNT)); 442 + (sb->s_uuid[ARRAY_SIZE(sb->s_uuid)-1] % EXT2_DFL_MAX_MNT_COUNT));
437 443
438 // write the label, if any 444 // write the label
439 if (label) //opts & OPT_L) 445 safe_strncpy((char *)sb->s_volume_name, label, sizeof(sb->s_volume_name));
440 safe_strncpy((char *)sb->s_volume_name, label, sizeof(sb->s_volume_name));
441 446
442 // fill group descriptors 447 // fill group descriptors
443 gd = xzalloc(gdtsz * blocksize); 448 gd = xzalloc(gdtsz * blocksize);
@@ -461,11 +466,6 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
461 STORE_LE(gd[i].bg_used_dirs_count, 2); 466 STORE_LE(gd[i].bg_used_dirs_count, 2);
462 gd[i].bg_free_inodes_count -= EXT2_GOOD_OLD_FIRST_INO; 467 gd[i].bg_free_inodes_count -= EXT2_GOOD_OLD_FIRST_INO;
463 } 468 }
464// // N.B. the following is pure heuristics!
465// // Likely to cope with 1024-byte blocks, when first block is for boot sectors
466// if (ngroups-1 == i) {
467// n -= first_data_block;
468// }
469 469
470 // mark preallocated blocks as allocated 470 // mark preallocated blocks as allocated
471 fb = (n < blocks_per_group ? n : blocks_per_group) - overhead; 471 fb = (n < blocks_per_group ? n : blocks_per_group) - overhead;
@@ -500,8 +500,8 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
500 // dump superblock and group descriptors and their backups 500 // dump superblock and group descriptors and their backups
501 if (has_super(i)) { 501 if (has_super(i)) {
502 // N.B. 1024 byte blocks are special 502 // N.B. 1024 byte blocks are special
503 PUT(((uint64_t)pos << blocksize_log2) + ((0 == i && 0 == first_data_block) ? 1024 : 0), sb, 1024);//blocksize); 503 PUT(((uint64_t)pos * blocksize) + ((0 == i && 0 == first_data_block) ? 1024 : 0), sb, 1024);//blocksize);
504 PUT(((uint64_t)pos << blocksize_log2) + blocksize, gd, gdtsz * blocksize); 504 PUT(((uint64_t)pos * blocksize) + blocksize, gd, gdtsz * blocksize);
505 } 505 }
506 } 506 }
507 507
@@ -526,12 +526,12 @@ int mkfs_ext2_main(int argc UNUSED_PARAM, char **argv)
526 // dump root dir inode 526 // dump root dir inode
527 STORE_LE(inode->i_links_count, 3); // "/.", "/..", "/lost+found/.." point to this inode 527 STORE_LE(inode->i_links_count, 3); // "/.", "/..", "/lost+found/.." point to this inode
528 STORE_LE(inode->i_block[0], FETCH_LE32(gd[0].bg_inode_table) + itsz); 528 STORE_LE(inode->i_block[0], FETCH_LE32(gd[0].bg_inode_table) + itsz);
529 PUT(((uint64_t)FETCH_LE32(gd[0].bg_inode_table) << blocksize_log2) + (EXT2_ROOT_INO-1) * sizeof(*inode), buf, sizeof(*inode)); 529 PUT(((uint64_t)FETCH_LE32(gd[0].bg_inode_table) * blocksize) + (EXT2_ROOT_INO-1) * sizeof(*inode), buf, sizeof(*inode));
530 530
531 // dump lost+found dir inode 531 // dump lost+found dir inode
532 STORE_LE(inode->i_links_count, 2); // both "/lost+found" and "/lost+found/." point to this inode 532 STORE_LE(inode->i_links_count, 2); // both "/lost+found" and "/lost+found/." point to this inode
533 STORE_LE(inode->i_block[0], inode->i_block[0]+1); // use next block 533 STORE_LE(inode->i_block[0], inode->i_block[0]+1); // use next block
534 PUT(((uint64_t)FETCH_LE32(gd[0].bg_inode_table) << blocksize_log2) + (EXT2_GOOD_OLD_FIRST_INO-1) * sizeof(*inode), buf, sizeof(*inode)); 534 PUT(((uint64_t)FETCH_LE32(gd[0].bg_inode_table) * blocksize) + (EXT2_GOOD_OLD_FIRST_INO-1) * sizeof(*inode), buf, sizeof(*inode));
535 535
536 // dump directories 536 // dump directories
537 memset(buf, 0, blocksize); 537 memset(buf, 0, blocksize);