aboutsummaryrefslogtreecommitdiff
path: root/util-linux
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-03-15 19:52:42 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-03-15 19:52:42 +0000
commit4efeaee387eb9c20afcf5576802755a646adb776 (patch)
tree306d8ad4c9a20e971356afc3b3a76abc15263458 /util-linux
parent5e892bae51a1f4414006a70f37d87b339e943cba (diff)
downloadbusybox-w32-4efeaee387eb9c20afcf5576802755a646adb776.tar.gz
busybox-w32-4efeaee387eb9c20afcf5576802755a646adb776.tar.bz2
busybox-w32-4efeaee387eb9c20afcf5576802755a646adb776.zip
mkfs_minix: stop using lots of bss/data.
data -3500 bytes, code -300 bytes keep_data_small: expand/fix
Diffstat (limited to 'util-linux')
-rw-r--r--util-linux/mkfs_minix.c368
1 files changed, 190 insertions, 178 deletions
diff --git a/util-linux/mkfs_minix.c b/util-linux/mkfs_minix.c
index e9ac9350d..2ba9233df 100644
--- a/util-linux/mkfs_minix.c
+++ b/util-linux/mkfs_minix.c
@@ -85,42 +85,49 @@ enum {
85 TEST_BUFFER_BLOCKS = 16, 85 TEST_BUFFER_BLOCKS = 16,
86}; 86};
87 87
88#if ENABLE_FEATURE_MINIX2 88#if !ENABLE_FEATURE_MINIX2
89static int version2;
90#else
91enum { version2 = 0 }; 89enum { version2 = 0 };
92#endif 90#endif
93 91
94static char *device_name; 92struct globals {
95static int dev_fd = -1;
96static uint32_t total_blocks;
97static int badblocks;
98/* default (changed to 30, per Linus's suggestion, Sun Nov 21 08:05:07 1993) */
99static int namelen = 30;
100static int dirsize = 32;
101static int magic = MINIX1_SUPER_MAGIC2;
102 93
103static char root_block[BLOCK_SIZE]; 94 int dev_fd;
104static char super_block_buffer[BLOCK_SIZE];
105static char boot_block_buffer[512];
106static char *inode_buffer;
107 95
108static char *inode_map; 96#if ENABLE_FEATURE_MINIX2
109static char *zone_map; 97 int version2;
98#define version2 G.version2
99#endif
100 char *device_name;
101 uint32_t total_blocks;
102 int badblocks;
103 int namelen;
104 int dirsize;
105 int magic;
106 char *inode_buffer;
107 char *inode_map;
108 char *zone_map;
109 int used_good_blocks;
110 unsigned long req_nr_inodes;
111 unsigned currently_testing;
112
113
114 char root_block[BLOCK_SIZE];
115 char super_block_buffer[BLOCK_SIZE];
116 char boot_block_buffer[512];
117 unsigned short good_blocks_table[MAX_GOOD_BLOCKS];
118};
110 119
111static int used_good_blocks; 120#define G (*ptr_to_globals)
112static unsigned short good_blocks_table[MAX_GOOD_BLOCKS];
113static unsigned long req_nr_inodes;
114 121
115static ATTRIBUTE_ALWAYS_INLINE unsigned div_roundup(unsigned size, unsigned n) 122static ATTRIBUTE_ALWAYS_INLINE unsigned div_roundup(unsigned size, unsigned n)
116{ 123{
117 return (size + n-1) / n; 124 return (size + n-1) / n;
118} 125}
119 126
120#define INODE_BUF1 (((struct minix1_inode*)inode_buffer) - 1) 127#define INODE_BUF1 (((struct minix1_inode*)G.inode_buffer) - 1)
121#define INODE_BUF2 (((struct minix2_inode*)inode_buffer) - 1) 128#define INODE_BUF2 (((struct minix2_inode*)G.inode_buffer) - 1)
122 129
123#define SB (*(struct minix_super_block*)super_block_buffer) 130#define SB (*(struct minix_super_block*)G.super_block_buffer)
124 131
125#define SB_INODES (SB.s_ninodes) 132#define SB_INODES (SB.s_ninodes)
126#define SB_IMAPS (SB.s_imap_blocks) 133#define SB_IMAPS (SB.s_imap_blocks)
@@ -160,13 +167,13 @@ static void minix_clrbit(char *a, unsigned i)
160} 167}
161 168
162/* Note: do not assume 0/1, it is 0/nonzero */ 169/* Note: do not assume 0/1, it is 0/nonzero */
163#define zone_in_use(x) minix_bit(zone_map,(x)-SB_FIRSTZONE+1) 170#define zone_in_use(x) minix_bit(G.zone_map,(x)-SB_FIRSTZONE+1)
164/*#define inode_in_use(x) minix_bit(inode_map,(x))*/ 171/*#define inode_in_use(x) minix_bit(G.inode_map,(x))*/
165 172
166#define mark_inode(x) minix_setbit(inode_map,(x)) 173#define mark_inode(x) minix_setbit(G.inode_map,(x))
167#define unmark_inode(x) minix_clrbit(inode_map,(x)) 174#define unmark_inode(x) minix_clrbit(G.inode_map,(x))
168#define mark_zone(x) minix_setbit(zone_map,(x)-SB_FIRSTZONE+1) 175#define mark_zone(x) minix_setbit(G.zone_map,(x)-SB_FIRSTZONE+1)
169#define unmark_zone(x) minix_clrbit(zone_map,(x)-SB_FIRSTZONE+1) 176#define unmark_zone(x) minix_clrbit(G.zone_map,(x)-SB_FIRSTZONE+1)
170 177
171#ifndef BLKGETSIZE 178#ifndef BLKGETSIZE
172# define BLKGETSIZE _IO(0x12,96) /* return device size */ 179# define BLKGETSIZE _IO(0x12,96) /* return device size */
@@ -227,51 +234,51 @@ static void write_tables(void)
227 SB.s_state &= ~MINIX_ERROR_FS; 234 SB.s_state &= ~MINIX_ERROR_FS;
228 235
229 msg_eol = "seek to 0 failed"; 236 msg_eol = "seek to 0 failed";
230 xlseek(dev_fd, 0, SEEK_SET); 237 xlseek(G.dev_fd, 0, SEEK_SET);
231 238
232 msg_eol = "cannot clear boot sector"; 239 msg_eol = "cannot clear boot sector";
233 xwrite(dev_fd, boot_block_buffer, 512); 240 xwrite(G.dev_fd, G.boot_block_buffer, 512);
234 241
235 msg_eol = "seek to BLOCK_SIZE failed"; 242 msg_eol = "seek to BLOCK_SIZE failed";
236 xlseek(dev_fd, BLOCK_SIZE, SEEK_SET); 243 xlseek(G.dev_fd, BLOCK_SIZE, SEEK_SET);
237 244
238 msg_eol = "cannot write superblock"; 245 msg_eol = "cannot write superblock";
239 xwrite(dev_fd, super_block_buffer, BLOCK_SIZE); 246 xwrite(G.dev_fd, G.super_block_buffer, BLOCK_SIZE);
240 247
241 msg_eol = "cannot write inode map"; 248 msg_eol = "cannot write inode map";
242 xwrite(dev_fd, inode_map, SB_IMAPS * BLOCK_SIZE); 249 xwrite(G.dev_fd, G.inode_map, SB_IMAPS * BLOCK_SIZE);
243 250
244 msg_eol = "cannot write zone map"; 251 msg_eol = "cannot write zone map";
245 xwrite(dev_fd, zone_map, SB_ZMAPS * BLOCK_SIZE); 252 xwrite(G.dev_fd, G.zone_map, SB_ZMAPS * BLOCK_SIZE);
246 253
247 msg_eol = "cannot write inodes"; 254 msg_eol = "cannot write inodes";
248 xwrite(dev_fd, inode_buffer, INODE_BUFFER_SIZE); 255 xwrite(G.dev_fd, G.inode_buffer, INODE_BUFFER_SIZE);
249 256
250 msg_eol = "\n"; 257 msg_eol = "\n";
251} 258}
252 259
253static void write_block(int blk, char *buffer) 260static void write_block(int blk, char *buffer)
254{ 261{
255 xlseek(dev_fd, blk * BLOCK_SIZE, SEEK_SET); 262 xlseek(G.dev_fd, blk * BLOCK_SIZE, SEEK_SET);
256 xwrite(dev_fd, buffer, BLOCK_SIZE); 263 xwrite(G.dev_fd, buffer, BLOCK_SIZE);
257} 264}
258 265
259static int get_free_block(void) 266static int get_free_block(void)
260{ 267{
261 int blk; 268 int blk;
262 269
263 if (used_good_blocks + 1 >= MAX_GOOD_BLOCKS) 270 if (G.used_good_blocks + 1 >= MAX_GOOD_BLOCKS)
264 bb_error_msg_and_die("too many bad blocks"); 271 bb_error_msg_and_die("too many bad blocks");
265 if (used_good_blocks) 272 if (G.used_good_blocks)
266 blk = good_blocks_table[used_good_blocks - 1] + 1; 273 blk = G.good_blocks_table[G.used_good_blocks - 1] + 1;
267 else 274 else
268 blk = SB_FIRSTZONE; 275 blk = SB_FIRSTZONE;
269 while (blk < SB_ZONES && zone_in_use(blk)) 276 while (blk < SB_ZONES && zone_in_use(blk))
270 blk++; 277 blk++;
271 if (blk >= SB_ZONES) 278 if (blk >= SB_ZONES)
272 bb_error_msg_and_die("not enough good blocks"); 279 bb_error_msg_and_die("not enough good blocks");
273 good_blocks_table[used_good_blocks] = blk; 280 G.good_blocks_table[G.used_good_blocks] = blk;
274 used_good_blocks++; 281 G.used_good_blocks++;
275 return blk; 282 return blk;
276} 283}
277 284
@@ -279,8 +286,8 @@ static void mark_good_blocks(void)
279{ 286{
280 int blk; 287 int blk;
281 288
282 for (blk = 0; blk < used_good_blocks; blk++) 289 for (blk = 0; blk < G.used_good_blocks; blk++)
283 mark_zone(good_blocks_table[blk]); 290 mark_zone(G.good_blocks_table[blk]);
284} 291}
285 292
286static int next(int zone) 293static int next(int zone)
@@ -303,7 +310,7 @@ static void make_bad_inode(void)
303 310
304#define NEXT_BAD (zone = next(zone)) 311#define NEXT_BAD (zone = next(zone))
305 312
306 if (!badblocks) 313 if (!G.badblocks)
307 return; 314 return;
308 mark_inode(MINIX_BAD_INO); 315 mark_inode(MINIX_BAD_INO);
309 inode->i_nlinks = 1; 316 inode->i_nlinks = 1;
@@ -311,7 +318,7 @@ static void make_bad_inode(void)
311 /* it's harder to check for bugs then - diff isn't helpful :(... */ 318 /* it's harder to check for bugs then - diff isn't helpful :(... */
312 inode->i_time = CUR_TIME; 319 inode->i_time = CUR_TIME;
313 inode->i_mode = S_IFREG + 0000; 320 inode->i_mode = S_IFREG + 0000;
314 inode->i_size = badblocks * BLOCK_SIZE; 321 inode->i_size = G.badblocks * BLOCK_SIZE;
315 zone = next(0); 322 zone = next(0);
316 for (i = 0; i < 7; i++) { 323 for (i = 0; i < 7; i++) {
317 inode->i_zone[i] = zone; 324 inode->i_zone[i] = zone;
@@ -354,13 +361,13 @@ static void make_bad_inode2(void)
354 unsigned long ind_block[BLOCK_SIZE >> 2]; 361 unsigned long ind_block[BLOCK_SIZE >> 2];
355 unsigned long dind_block[BLOCK_SIZE >> 2]; 362 unsigned long dind_block[BLOCK_SIZE >> 2];
356 363
357 if (!badblocks) 364 if (!G.badblocks)
358 return; 365 return;
359 mark_inode(MINIX_BAD_INO); 366 mark_inode(MINIX_BAD_INO);
360 inode->i_nlinks = 1; 367 inode->i_nlinks = 1;
361 inode->i_atime = inode->i_mtime = inode->i_ctime = CUR_TIME; 368 inode->i_atime = inode->i_mtime = inode->i_ctime = CUR_TIME;
362 inode->i_mode = S_IFREG + 0000; 369 inode->i_mode = S_IFREG + 0000;
363 inode->i_size = badblocks * BLOCK_SIZE; 370 inode->i_size = G.badblocks * BLOCK_SIZE;
364 zone = next(0); 371 zone = next(0);
365 for (i = 0; i < 7; i++) { 372 for (i = 0; i < 7; i++) {
366 inode->i_zone[i] = zone; 373 inode->i_zone[i] = zone;
@@ -406,18 +413,18 @@ static void make_root_inode(void)
406 inode->i_zone[0] = get_free_block(); 413 inode->i_zone[0] = get_free_block();
407 inode->i_nlinks = 2; 414 inode->i_nlinks = 2;
408 inode->i_time = CUR_TIME; 415 inode->i_time = CUR_TIME;
409 if (badblocks) 416 if (G.badblocks)
410 inode->i_size = 3 * dirsize; 417 inode->i_size = 3 * G.dirsize;
411 else { 418 else {
412 root_block[2 * dirsize] = '\0'; 419 G.root_block[2 * G.dirsize] = '\0';
413 root_block[2 * dirsize + 1] = '\0'; 420 G.root_block[2 * G.dirsize + 1] = '\0';
414 inode->i_size = 2 * dirsize; 421 inode->i_size = 2 * G.dirsize;
415 } 422 }
416 inode->i_mode = S_IFDIR + 0755; 423 inode->i_mode = S_IFDIR + 0755;
417 inode->i_uid = GETUID; 424 inode->i_uid = GETUID;
418 if (inode->i_uid) 425 if (inode->i_uid)
419 inode->i_gid = GETGID; 426 inode->i_gid = GETGID;
420 write_block(inode->i_zone[0], root_block); 427 write_block(inode->i_zone[0], G.root_block);
421} 428}
422 429
423#if ENABLE_FEATURE_MINIX2 430#if ENABLE_FEATURE_MINIX2
@@ -429,94 +436,23 @@ static void make_root_inode2(void)
429 inode->i_zone[0] = get_free_block(); 436 inode->i_zone[0] = get_free_block();
430 inode->i_nlinks = 2; 437 inode->i_nlinks = 2;
431 inode->i_atime = inode->i_mtime = inode->i_ctime = CUR_TIME; 438 inode->i_atime = inode->i_mtime = inode->i_ctime = CUR_TIME;
432 if (badblocks) 439 if (G.badblocks)
433 inode->i_size = 3 * dirsize; 440 inode->i_size = 3 * G.dirsize;
434 else { 441 else {
435 root_block[2 * dirsize] = '\0'; 442 G.root_block[2 * G.dirsize] = '\0';
436 root_block[2 * dirsize + 1] = '\0'; 443 G.root_block[2 * G.dirsize + 1] = '\0';
437 inode->i_size = 2 * dirsize; 444 inode->i_size = 2 * G.dirsize;
438 } 445 }
439 inode->i_mode = S_IFDIR + 0755; 446 inode->i_mode = S_IFDIR + 0755;
440 inode->i_uid = GETUID; 447 inode->i_uid = GETUID;
441 if (inode->i_uid) 448 if (inode->i_uid)
442 inode->i_gid = GETGID; 449 inode->i_gid = GETGID;
443 write_block(inode->i_zone[0], root_block); 450 write_block(inode->i_zone[0], G.root_block);
444} 451}
445#else 452#else
446void make_root_inode2(void); 453void make_root_inode2(void);
447#endif 454#endif
448 455
449static void setup_tables(void)
450{
451 unsigned long inodes;
452 unsigned norm_firstzone;
453 unsigned sb_zmaps;
454 unsigned i;
455
456 memset(super_block_buffer, 0, BLOCK_SIZE);
457 memset(boot_block_buffer, 0, 512);
458 SB_MAGIC = magic;
459 SB_ZONE_SIZE = 0;
460 SB_MAXSIZE = version2 ? 0x7fffffff : (7 + 512 + 512 * 512) * 1024;
461 if (version2)
462 SB.s_zones = total_blocks;
463 else
464 SB.s_nzones = total_blocks;
465
466 /* some magic nrs: 1 inode / 3 blocks */
467 if (req_nr_inodes == 0)
468 inodes = total_blocks / 3;
469 else
470 inodes = req_nr_inodes;
471 /* Round up inode count to fill block size */
472 if (version2)
473 inodes = (inodes + MINIX2_INODES_PER_BLOCK - 1) &
474 ~(MINIX2_INODES_PER_BLOCK - 1);
475 else
476 inodes = (inodes + MINIX1_INODES_PER_BLOCK - 1) &
477 ~(MINIX1_INODES_PER_BLOCK - 1);
478 if (inodes > 65535)
479 inodes = 65535;
480 SB_INODES = inodes;
481 SB_IMAPS = div_roundup(SB_INODES + 1, BITS_PER_BLOCK);
482
483 /* Real bad hack but overwise mkfs.minix can be thrown
484 * in infinite loop...
485 * try:
486 * dd if=/dev/zero of=test.fs count=10 bs=1024
487 * mkfs.minix -i 200 test.fs
488 */
489 /* This code is not insane: NORM_FIRSTZONE is not a constant,
490 * it is calculated from SB_INODES, SB_IMAPS and SB_ZMAPS */
491 i = 999;
492 SB_ZMAPS = 0;
493 do {
494 norm_firstzone = NORM_FIRSTZONE;
495 sb_zmaps = div_roundup(total_blocks - norm_firstzone + 1, BITS_PER_BLOCK);
496 if (SB_ZMAPS == sb_zmaps) goto got_it;
497 SB_ZMAPS = sb_zmaps;
498 /* new SB_ZMAPS, need to recalc NORM_FIRSTZONE */
499 } while (--i);
500 bb_error_msg_and_die("incompatible size/inode count, try different -i N");
501 got_it:
502
503 SB_FIRSTZONE = norm_firstzone;
504 inode_map = xmalloc(SB_IMAPS * BLOCK_SIZE);
505 zone_map = xmalloc(SB_ZMAPS * BLOCK_SIZE);
506 memset(inode_map, 0xff, SB_IMAPS * BLOCK_SIZE);
507 memset(zone_map, 0xff, SB_ZMAPS * BLOCK_SIZE);
508 for (i = SB_FIRSTZONE; i < SB_ZONES; i++)
509 unmark_zone(i);
510 for (i = MINIX_ROOT_INO; i <= SB_INODES; i++)
511 unmark_inode(i);
512 inode_buffer = xzalloc(INODE_BUFFER_SIZE);
513 printf("%ld inodes\n", (long)SB_INODES);
514 printf("%ld blocks\n", (long)SB_ZONES);
515 printf("Firstdatazone=%ld (%ld)\n", (long)SB_FIRSTZONE, (long)norm_firstzone);
516 printf("Zonesize=%d\n", BLOCK_SIZE << SB_ZONE_SIZE);
517 printf("Maxsize=%ld\n", (long)SB_MAXSIZE);
518}
519
520/* 456/*
521 * Perform a test of a block; return the number of 457 * Perform a test of a block; return the number of
522 * blocks readable. 458 * blocks readable.
@@ -527,11 +463,11 @@ static size_t do_check(char *buffer, size_t try, unsigned current_block)
527 463
528 /* Seek to the correct loc. */ 464 /* Seek to the correct loc. */
529 msg_eol = "seek failed during testing of blocks"; 465 msg_eol = "seek failed during testing of blocks";
530 xlseek(dev_fd, current_block * BLOCK_SIZE, SEEK_SET); 466 xlseek(G.dev_fd, current_block * BLOCK_SIZE, SEEK_SET);
531 msg_eol = "\n"; 467 msg_eol = "\n";
532 468
533 /* Try the read */ 469 /* Try the read */
534 got = read(dev_fd, buffer, try * BLOCK_SIZE); 470 got = read(G.dev_fd, buffer, try * BLOCK_SIZE);
535 if (got < 0) 471 if (got < 0)
536 got = 0; 472 got = 0;
537 try = ((size_t)got) / BLOCK_SIZE; 473 try = ((size_t)got) / BLOCK_SIZE;
@@ -541,17 +477,15 @@ static size_t do_check(char *buffer, size_t try, unsigned current_block)
541 return try; 477 return try;
542} 478}
543 479
544static unsigned currently_testing;
545
546static void alarm_intr(int alnum) 480static void alarm_intr(int alnum)
547{ 481{
548 if (currently_testing >= SB_ZONES) 482 if (G.currently_testing >= SB_ZONES)
549 return; 483 return;
550 signal(SIGALRM, alarm_intr); 484 signal(SIGALRM, alarm_intr);
551 alarm(5); 485 alarm(5);
552 if (!currently_testing) 486 if (!G.currently_testing)
553 return; 487 return;
554 printf("%d ...", currently_testing); 488 printf("%d ...", G.currently_testing);
555 fflush(stdout); 489 fflush(stdout);
556} 490}
557 491
@@ -561,28 +495,29 @@ static void check_blocks(void)
561 /* buffer[] was the biggest static in entire bbox */ 495 /* buffer[] was the biggest static in entire bbox */
562 char *buffer = xmalloc(BLOCK_SIZE * TEST_BUFFER_BLOCKS); 496 char *buffer = xmalloc(BLOCK_SIZE * TEST_BUFFER_BLOCKS);
563 497
564 currently_testing = 0; 498 G.currently_testing = 0;
565 signal(SIGALRM, alarm_intr); 499 signal(SIGALRM, alarm_intr);
566 alarm(5); 500 alarm(5);
567 while (currently_testing < SB_ZONES) { 501 while (G.currently_testing < SB_ZONES) {
568 msg_eol = "seek failed in check_blocks"; 502 msg_eol = "seek failed in check_blocks";
569 xlseek(dev_fd, currently_testing * BLOCK_SIZE, SEEK_SET); 503 xlseek(G.dev_fd, G.currently_testing * BLOCK_SIZE, SEEK_SET);
570 msg_eol = "\n"; 504 msg_eol = "\n";
571 try = TEST_BUFFER_BLOCKS; 505 try = TEST_BUFFER_BLOCKS;
572 if (currently_testing + try > SB_ZONES) 506 if (G.currently_testing + try > SB_ZONES)
573 try = SB_ZONES - currently_testing; 507 try = SB_ZONES - G.currently_testing;
574 got = do_check(buffer, try, currently_testing); 508 got = do_check(buffer, try, G.currently_testing);
575 currently_testing += got; 509 G.currently_testing += got;
576 if (got == try) 510 if (got == try)
577 continue; 511 continue;
578 if (currently_testing < SB_FIRSTZONE) 512 if (G.currently_testing < SB_FIRSTZONE)
579 bb_error_msg_and_die("bad blocks before data-area: cannot make fs"); 513 bb_error_msg_and_die("bad blocks before data-area: cannot make fs");
580 mark_zone(currently_testing); 514 mark_zone(G.currently_testing);
581 badblocks++; 515 G.badblocks++;
582 currently_testing++; 516 G.currently_testing++;
583 } 517 }
518 alarm(0);
584 free(buffer); 519 free(buffer);
585 printf("%d bad block(s)\n", badblocks); 520 printf("%d bad block(s)\n", G.badblocks);
586} 521}
587 522
588static void get_list_blocks(char *filename) 523static void get_list_blocks(char *filename)
@@ -594,9 +529,80 @@ static void get_list_blocks(char *filename)
594 while (!feof(listfile)) { 529 while (!feof(listfile)) {
595 fscanf(listfile, "%ld\n", &blockno); 530 fscanf(listfile, "%ld\n", &blockno);
596 mark_zone(blockno); 531 mark_zone(blockno);
597 badblocks++; 532 G.badblocks++;
598 } 533 }
599 printf("%d bad block(s)\n", badblocks); 534 printf("%d bad block(s)\n", G.badblocks);
535}
536
537static void setup_tables(void)
538{
539 unsigned long inodes;
540 unsigned norm_firstzone;
541 unsigned sb_zmaps;
542 unsigned i;
543
544 /* memset(G.super_block_buffer, 0, BLOCK_SIZE); */
545 /* memset(G.boot_block_buffer, 0, 512); */
546 SB_MAGIC = G.magic;
547 SB_ZONE_SIZE = 0;
548 SB_MAXSIZE = version2 ? 0x7fffffff : (7 + 512 + 512 * 512) * 1024;
549 if (version2)
550 SB.s_zones = G.total_blocks;
551 else
552 SB.s_nzones = G.total_blocks;
553
554 /* some magic nrs: 1 inode / 3 blocks */
555 if (G.req_nr_inodes == 0)
556 inodes = G.total_blocks / 3;
557 else
558 inodes = G.req_nr_inodes;
559 /* Round up inode count to fill block size */
560 if (version2)
561 inodes = (inodes + MINIX2_INODES_PER_BLOCK - 1) &
562 ~(MINIX2_INODES_PER_BLOCK - 1);
563 else
564 inodes = (inodes + MINIX1_INODES_PER_BLOCK - 1) &
565 ~(MINIX1_INODES_PER_BLOCK - 1);
566 if (inodes > 65535)
567 inodes = 65535;
568 SB_INODES = inodes;
569 SB_IMAPS = div_roundup(SB_INODES + 1, BITS_PER_BLOCK);
570
571 /* Real bad hack but overwise mkfs.minix can be thrown
572 * in infinite loop...
573 * try:
574 * dd if=/dev/zero of=test.fs count=10 bs=1024
575 * mkfs.minix -i 200 test.fs
576 */
577 /* This code is not insane: NORM_FIRSTZONE is not a constant,
578 * it is calculated from SB_INODES, SB_IMAPS and SB_ZMAPS */
579 i = 999;
580 SB_ZMAPS = 0;
581 do {
582 norm_firstzone = NORM_FIRSTZONE;
583 sb_zmaps = div_roundup(G.total_blocks - norm_firstzone + 1, BITS_PER_BLOCK);
584 if (SB_ZMAPS == sb_zmaps) goto got_it;
585 SB_ZMAPS = sb_zmaps;
586 /* new SB_ZMAPS, need to recalc NORM_FIRSTZONE */
587 } while (--i);
588 bb_error_msg_and_die("incompatible size/inode count, try different -i N");
589 got_it:
590
591 SB_FIRSTZONE = norm_firstzone;
592 G.inode_map = xmalloc(SB_IMAPS * BLOCK_SIZE);
593 G.zone_map = xmalloc(SB_ZMAPS * BLOCK_SIZE);
594 memset(G.inode_map, 0xff, SB_IMAPS * BLOCK_SIZE);
595 memset(G.zone_map, 0xff, SB_ZMAPS * BLOCK_SIZE);
596 for (i = SB_FIRSTZONE; i < SB_ZONES; i++)
597 unmark_zone(i);
598 for (i = MINIX_ROOT_INO; i <= SB_INODES; i++)
599 unmark_inode(i);
600 G.inode_buffer = xzalloc(INODE_BUFFER_SIZE);
601 printf("%ld inodes\n", (long)SB_INODES);
602 printf("%ld blocks\n", (long)SB_ZONES);
603 printf("Firstdatazone=%ld (%ld)\n", (long)SB_FIRSTZONE, (long)norm_firstzone);
604 printf("Zonesize=%d\n", BLOCK_SIZE << SB_ZONE_SIZE);
605 printf("Maxsize=%ld\n", (long)SB_MAXSIZE);
600} 606}
601 607
602int mkfs_minix_main(int argc, char **argv); 608int mkfs_minix_main(int argc, char **argv);
@@ -609,6 +615,12 @@ int mkfs_minix_main(int argc, char **argv)
609 char *str_i, *str_n; 615 char *str_i, *str_n;
610 char *listfile = NULL; 616 char *listfile = NULL;
611 617
618 PTR_TO_GLOBALS = xzalloc(sizeof(G));
619/* default (changed to 30, per Linus's suggestion, Sun Nov 21 08:05:07 1993) */
620 G.namelen = 30;
621 G.dirsize = 32;
622 G.magic = MINIX1_SUPER_MAGIC2;
623
612 if (INODE_SIZE1 * MINIX1_INODES_PER_BLOCK != BLOCK_SIZE) 624 if (INODE_SIZE1 * MINIX1_INODES_PER_BLOCK != BLOCK_SIZE)
613 bb_error_msg_and_die("bad inode size"); 625 bb_error_msg_and_die("bad inode size");
614#if ENABLE_FEATURE_MINIX2 626#if ENABLE_FEATURE_MINIX2
@@ -619,14 +631,14 @@ int mkfs_minix_main(int argc, char **argv)
619 opt = getopt32(argc, argv, "ci:l:n:v", &str_i, &listfile, &str_n); 631 opt = getopt32(argc, argv, "ci:l:n:v", &str_i, &listfile, &str_n);
620 argv += optind; 632 argv += optind;
621 //if (opt & 1) -c 633 //if (opt & 1) -c
622 if (opt & 2) req_nr_inodes = xatoul(str_i); // -i 634 if (opt & 2) G.req_nr_inodes = xatoul(str_i); // -i
623 //if (opt & 4) -l 635 //if (opt & 4) -l
624 if (opt & 8) { // -n 636 if (opt & 8) { // -n
625 namelen = xatoi_u(str_n); 637 G.namelen = xatoi_u(str_n);
626 if (namelen == 14) magic = MINIX1_SUPER_MAGIC; 638 if (G.namelen == 14) G.magic = MINIX1_SUPER_MAGIC;
627 else if (namelen == 30) magic = MINIX1_SUPER_MAGIC2; 639 else if (G.namelen == 30) G.magic = MINIX1_SUPER_MAGIC2;
628 else bb_show_usage(); 640 else bb_show_usage();
629 dirsize = namelen + 2; 641 G.dirsize = G.namelen + 2;
630 } 642 }
631 if (opt & 0x10) { // -v 643 if (opt & 0x10) { // -v
632#if ENABLE_FEATURE_MINIX2 644#if ENABLE_FEATURE_MINIX2
@@ -636,34 +648,34 @@ int mkfs_minix_main(int argc, char **argv)
636#endif 648#endif
637 } 649 }
638 650
639 device_name = *argv++; 651 G.device_name = *argv++;
640 if (!device_name) 652 if (!G.device_name)
641 bb_show_usage(); 653 bb_show_usage();
642 if (*argv) 654 if (*argv)
643 total_blocks = xatou32(*argv); 655 G.total_blocks = xatou32(*argv);
644 else 656 else
645 total_blocks = get_size(device_name) / 1024; 657 G.total_blocks = get_size(G.device_name) / 1024;
646 658
647 if (total_blocks < 10) 659 if (G.total_blocks < 10)
648 bb_error_msg_and_die("must have at least 10 blocks"); 660 bb_error_msg_and_die("must have at least 10 blocks");
649 661
650 if (version2) { 662 if (version2) {
651 magic = MINIX2_SUPER_MAGIC2; 663 G.magic = MINIX2_SUPER_MAGIC2;
652 if (namelen == 14) 664 if (G.namelen == 14)
653 magic = MINIX2_SUPER_MAGIC; 665 G.magic = MINIX2_SUPER_MAGIC;
654 } else if (total_blocks > 65535) 666 } else if (G.total_blocks > 65535)
655 total_blocks = 65535; 667 G.total_blocks = 65535;
656 668
657 /* Check if it is mounted */ 669 /* Check if it is mounted */
658 mp = find_mount_point(device_name, NULL); 670 mp = find_mount_point(G.device_name, NULL);
659 if (mp && strcmp(device_name, mp->mnt_fsname) == 0) 671 if (mp && strcmp(G.device_name, mp->mnt_fsname) == 0)
660 bb_error_msg_and_die("%s is mounted on %s; " 672 bb_error_msg_and_die("%s is mounted on %s; "
661 "refusing to make a filesystem", 673 "refusing to make a filesystem",
662 device_name, mp->mnt_dir); 674 G.device_name, mp->mnt_dir);
663 675
664 dev_fd = xopen(device_name, O_RDWR); 676 G.dev_fd = xopen(G.device_name, O_RDWR);
665 if (fstat(dev_fd, &statbuf) < 0) 677 if (fstat(G.dev_fd, &statbuf) < 0)
666 bb_error_msg_and_die("cannot stat %s", device_name); 678 bb_error_msg_and_die("cannot stat %s", G.device_name);
667 if (!S_ISBLK(statbuf.st_mode)) 679 if (!S_ISBLK(statbuf.st_mode))
668 opt &= ~1; // clear -c (check) 680 opt &= ~1; // clear -c (check)
669 681
@@ -673,16 +685,16 @@ int mkfs_minix_main(int argc, char **argv)
673 else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340) 685 else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340)
674 /* what is this? */ 686 /* what is this? */
675 bb_error_msg_and_die("will not try " 687 bb_error_msg_and_die("will not try "
676 "to make filesystem on '%s'", device_name); 688 "to make filesystem on '%s'", G.device_name);
677#endif 689#endif
678 690
679 tmp = root_block; 691 tmp = G.root_block;
680 *(short *) tmp = 1; 692 *(short *) tmp = 1;
681 strcpy(tmp + 2, "."); 693 strcpy(tmp + 2, ".");
682 tmp += dirsize; 694 tmp += G.dirsize;
683 *(short *) tmp = 1; 695 *(short *) tmp = 1;
684 strcpy(tmp + 2, ".."); 696 strcpy(tmp + 2, "..");
685 tmp += dirsize; 697 tmp += G.dirsize;
686 *(short *) tmp = 2; 698 *(short *) tmp = 2;
687 strcpy(tmp + 2, ".badblocks"); 699 strcpy(tmp + 2, ".badblocks");
688 700