1 static char *sccsid = "@(#)mkfs.c 2.12 (Berkeley) 05/25/83"; 2 3 /* 4 * make file system for cylinder-group style file systems 5 * 6 * usage: mkfs special size [ nsect ntrak bsize fsize cpg minfree rps nbpi ] 7 */ 8 9 /* 10 * The following constants set the defaults used for the number 11 * of sectors (fs_nsect), and number of tracks (fs_ntrak). 12 */ 13 #define DFLNSECT 32 14 #define DFLNTRAK 16 15 16 /* 17 * The following two constants set the default block and fragment sizes. 18 * Both constants must be a power of 2 and meet the following constraints: 19 * MINBSIZE <= DESBLKSIZE <= MAXBSIZE 20 * DEV_BSIZE <= DESFRAGSIZE <= DESBLKSIZE 21 * DESBLKSIZE / DESFRAGSIZE <= 8 22 */ 23 #define DESBLKSIZE 8192 24 #define DESFRAGSIZE 1024 25 26 /* 27 * Cylinder groups may have up to MAXCPG cylinders. The actual 28 * number used depends upon how much information can be stored 29 * on a single cylinder. The default is to used 16 cylinders 30 * per group. 31 */ 32 #define DESCPG 16 /* desired fs_cpg */ 33 34 /* 35 * MINFREE gives the minimum acceptable percentage of file system 36 * blocks which may be free. If the freelist drops below this level 37 * only the superuser may continue to allocate blocks. This may 38 * be set to 0 if no reserve of free blocks is deemed necessary, 39 * however throughput drops by fifty percent if the file system 40 * is run at between 90% and 100% full; thus the default value of 41 * fs_minfree is 10%. 42 */ 43 #define MINFREE 10 44 45 /* 46 * ROTDELAY gives the minimum number of milliseconds to initiate 47 * another disk transfer on the same cylinder. It is used in 48 * determining the rotationally optimal layout for disk blocks 49 * within a file; the default of fs_rotdelay is 2ms. 50 */ 51 #define ROTDELAY 2 52 53 /* 54 * MAXCONTIG sets the default for the maximum number of blocks 55 * that may be allocated sequentially. Since UNIX drivers are 56 * not capable of scheduling multi-block transfers, this defaults 57 * to 1 (ie no contiguous blocks are allocated). 58 */ 59 #define MAXCONTIG 1 60 61 /* 62 * MAXBLKPG determines the maximum number of data blocks which are 63 * placed in a single cylinder group. This is currently a function 64 * of the block and fragment size of the file system. 65 */ 66 #define MAXBLKPG(fs) ((fs)->fs_fsize / sizeof(daddr_t)) 67 68 /* 69 * Each file system has a number of inodes statically allocated. 70 * We allocate one inode slot per NBPI bytes, expecting this 71 * to be far more than we will ever need. 72 */ 73 #define NBPI 2048 74 75 /* 76 * Disks are assumed to rotate at 60HZ, unless otherwise specified. 77 */ 78 #define DEFHZ 60 79 80 #ifndef STANDALONE 81 #include <stdio.h> 82 #include <a.out.h> 83 #endif 84 85 #ifndef SIMFS 86 #include <sys/param.h> 87 #include <sys/inode.h> 88 #include <sys/fs.h> 89 #else 90 #include "../h/param.h" 91 #include "../h/inode.h" 92 #include "../h/fs.h" 93 #endif 94 #include <dir.h> 95 96 #define UMASK 0755 97 #define MAXINOPB (MAXBSIZE / sizeof(struct dinode)) 98 #define POWEROF2(num) (((num) & ((num) - 1)) == 0) 99 100 union { 101 struct fs fs; 102 char pad[MAXBSIZE]; 103 } fsun; 104 #define sblock fsun.fs 105 struct csum *fscs; 106 107 union { 108 struct cg cg; 109 char pad[MAXBSIZE]; 110 } cgun; 111 #define acg cgun.cg 112 113 struct dinode zino[MAXIPG]; 114 115 char *fsys; 116 time_t utime; 117 int fsi; 118 int fso; 119 daddr_t alloc(); 120 121 main(argc, argv) 122 int argc; 123 char *argv[]; 124 { 125 long cylno, rpos, blk, i, j, inos, fssize, warn = 0; 126 127 #ifndef STANDALONE 128 argc--, argv++; 129 time(&utime); 130 if (argc < 2) { 131 printf("usage: mkfs special size [ nsect ntrak bsize fsize cpg minfree rps nbpi ]\n"); 132 exit(1); 133 } 134 fsys = argv[0]; 135 fssize = atoi(argv[1]); 136 fso = creat(fsys, 0666); 137 if(fso < 0) { 138 printf("%s: cannot create\n", fsys); 139 exit(1); 140 } 141 fsi = open(fsys, 0); 142 if(fsi < 0) { 143 printf("%s: cannot open\n", fsys); 144 exit(1); 145 } 146 #else 147 { 148 static char protos[60]; 149 char fsbuf[100]; 150 151 printf("file sys size: "); 152 gets(protos); 153 fssize = atoi(protos); 154 do { 155 printf("file system: "); 156 gets(fsbuf); 157 fso = open(fsbuf, 1); 158 fsi = open(fsbuf, 0); 159 } while (fso < 0 || fsi < 0); 160 } 161 argc = 0; 162 #endif 163 /* 164 * Validate the given file system size. 165 * Verify that its last block can actually be accessed. 166 */ 167 if (fssize <= 0) 168 printf("preposterous size %d\n", fssize), exit(1); 169 wtfs(fssize - 1, DEV_BSIZE, (char *)&sblock); 170 /* 171 * collect and verify the sector and track info 172 */ 173 if (argc > 2) 174 sblock.fs_nsect = atoi(argv[2]); 175 else 176 sblock.fs_nsect = DFLNSECT; 177 if (argc > 3) 178 sblock.fs_ntrak = atoi(argv[3]); 179 else 180 sblock.fs_ntrak = DFLNTRAK; 181 if (sblock.fs_ntrak <= 0) 182 printf("preposterous ntrak %d\n", sblock.fs_ntrak), exit(1); 183 if (sblock.fs_nsect <= 0) 184 printf("preposterous nsect %d\n", sblock.fs_nsect), exit(1); 185 sblock.fs_spc = sblock.fs_ntrak * sblock.fs_nsect; 186 /* 187 * collect and verify the block and fragment sizes 188 */ 189 if (argc > 4) 190 sblock.fs_bsize = atoi(argv[4]); 191 else 192 sblock.fs_bsize = DESBLKSIZE; 193 if (argc > 5) 194 sblock.fs_fsize = atoi(argv[5]); 195 else 196 sblock.fs_fsize = DESFRAGSIZE; 197 if (!POWEROF2(sblock.fs_bsize)) { 198 printf("block size must be a power of 2, not %d\n", 199 sblock.fs_bsize); 200 exit(1); 201 } 202 if (!POWEROF2(sblock.fs_fsize)) { 203 printf("fragment size must be a power of 2, not %d\n", 204 sblock.fs_fsize); 205 exit(1); 206 } 207 if (sblock.fs_fsize < DEV_BSIZE) { 208 printf("fragment size %d is too small, minimum is %d\n", 209 sblock.fs_fsize, DEV_BSIZE); 210 exit(1); 211 } 212 if (sblock.fs_bsize < MINBSIZE) { 213 printf("block size %d is too small, minimum is %d\n", 214 sblock.fs_bsize, MINBSIZE); 215 exit(1); 216 } 217 if (sblock.fs_bsize < sblock.fs_fsize) { 218 printf("block size (%d) cannot be smaller than fragment size (%d)\n", 219 sblock.fs_bsize, sblock.fs_fsize); 220 exit(1); 221 } 222 sblock.fs_bmask = ~(sblock.fs_bsize - 1); 223 sblock.fs_fmask = ~(sblock.fs_fsize - 1); 224 for (sblock.fs_bshift = 0, i = sblock.fs_bsize; i > 1; i >>= 1) 225 sblock.fs_bshift++; 226 for (sblock.fs_fshift = 0, i = sblock.fs_fsize; i > 1; i >>= 1) 227 sblock.fs_fshift++; 228 sblock.fs_frag = numfrags(&sblock, sblock.fs_bsize); 229 for (sblock.fs_fragshift = 0, i = sblock.fs_frag; i > 1; i >>= 1) 230 sblock.fs_fragshift++; 231 if (sblock.fs_frag > MAXFRAG) { 232 printf("fragment size %d is too small, minimum with block size %d is %d\n", 233 sblock.fs_fsize, sblock.fs_bsize, 234 sblock.fs_bsize / MAXFRAG); 235 exit(1); 236 } 237 sblock.fs_nindir = sblock.fs_bsize / sizeof(daddr_t); 238 sblock.fs_inopb = sblock.fs_bsize / sizeof(struct dinode); 239 sblock.fs_nspf = sblock.fs_fsize / DEV_BSIZE; 240 for (sblock.fs_fsbtodb = 0, i = sblock.fs_nspf; i > 1; i >>= 1) 241 sblock.fs_fsbtodb++; 242 sblock.fs_sblkno = 243 roundup(howmany(BBSIZE + SBSIZE, sblock.fs_fsize), sblock.fs_frag); 244 sblock.fs_cblkno = (daddr_t)(sblock.fs_sblkno + 245 roundup(howmany(SBSIZE, sblock.fs_fsize), sblock.fs_frag)); 246 sblock.fs_iblkno = sblock.fs_cblkno + sblock.fs_frag; 247 sblock.fs_cgoffset = roundup( 248 howmany(sblock.fs_nsect, sblock.fs_fsize / DEV_BSIZE), 249 sblock.fs_frag); 250 for (sblock.fs_cgmask = 0xffffffff, i = sblock.fs_ntrak; i > 1; i >>= 1) 251 sblock.fs_cgmask <<= 1; 252 if (!POWEROF2(sblock.fs_ntrak)) 253 sblock.fs_cgmask <<= 1; 254 for (sblock.fs_cpc = NSPB(&sblock), i = sblock.fs_spc; 255 sblock.fs_cpc > 1 && (i & 1) == 0; 256 sblock.fs_cpc >>= 1, i >>= 1) 257 /* void */; 258 if (sblock.fs_cpc > MAXCPG) { 259 printf("maximum block size with nsect %d and ntrak %d is %d\n", 260 sblock.fs_nsect, sblock.fs_ntrak, 261 sblock.fs_bsize / (sblock.fs_cpc / MAXCPG)); 262 exit(1); 263 } 264 /* 265 * collect and verify the number of cylinders per group 266 */ 267 if (argc > 6) { 268 sblock.fs_cpg = atoi(argv[6]); 269 sblock.fs_fpg = (sblock.fs_cpg * sblock.fs_spc) / NSPF(&sblock); 270 } else { 271 sblock.fs_cpg = MAX(sblock.fs_cpc, DESCPG); 272 sblock.fs_fpg = (sblock.fs_cpg * sblock.fs_spc) / NSPF(&sblock); 273 while (sblock.fs_fpg / sblock.fs_frag > MAXBPG(&sblock) && 274 sblock.fs_cpg > sblock.fs_cpc) { 275 sblock.fs_cpg -= sblock.fs_cpc; 276 sblock.fs_fpg = 277 (sblock.fs_cpg * sblock.fs_spc) / NSPF(&sblock); 278 } 279 } 280 if (sblock.fs_cpg < 1) { 281 printf("cylinder groups must have at least 1 cylinder\n"); 282 exit(1); 283 } 284 if (sblock.fs_cpg > MAXCPG) { 285 printf("cylinder groups are limited to %d cylinders\n", MAXCPG); 286 exit(1); 287 } 288 if (sblock.fs_cpg % sblock.fs_cpc != 0) { 289 printf("cylinder groups must have a multiple of %d cylinders\n", 290 sblock.fs_cpc); 291 exit(1); 292 } 293 /* 294 * Now have size for file system and nsect and ntrak. 295 * Determine number of cylinders and blocks in the file system. 296 */ 297 sblock.fs_size = fssize = dbtofsb(&sblock, fssize); 298 sblock.fs_ncyl = fssize * NSPF(&sblock) / sblock.fs_spc; 299 if (fssize * NSPF(&sblock) > sblock.fs_ncyl * sblock.fs_spc) { 300 sblock.fs_ncyl++; 301 warn = 1; 302 } 303 if (sblock.fs_ncyl < 1) { 304 printf("file systems must have at least one cylinder\n"); 305 exit(1); 306 } 307 /* 308 * determine feasability/values of rotational layout tables 309 */ 310 if (sblock.fs_ntrak == 1) { 311 sblock.fs_cpc = 0; 312 goto next; 313 } 314 if (sblock.fs_spc * sblock.fs_cpc > MAXBPC * NSPB(&sblock) || 315 sblock.fs_nsect > (1 << NBBY) * NSPB(&sblock)) { 316 printf("%s %s %d %s %d.%s", 317 "Warning: insufficient space in super block for\n", 318 "rotational layout tables with nsect", sblock.fs_nsect, 319 "and ntrak", sblock.fs_ntrak, 320 "\nFile system performance may be impared.\n"); 321 sblock.fs_cpc = 0; 322 goto next; 323 } 324 /* 325 * calculate the available blocks for each rotational position 326 */ 327 for (cylno = 0; cylno < MAXCPG; cylno++) 328 for (rpos = 0; rpos < NRPOS; rpos++) 329 sblock.fs_postbl[cylno][rpos] = -1; 330 blk = sblock.fs_spc * sblock.fs_cpc / NSPF(&sblock); 331 for (i = 0; i < blk; i += sblock.fs_frag) 332 /* void */; 333 for (i -= sblock.fs_frag; i >= 0; i -= sblock.fs_frag) { 334 cylno = cbtocylno(&sblock, i); 335 rpos = cbtorpos(&sblock, i); 336 blk = i / sblock.fs_frag; 337 if (sblock.fs_postbl[cylno][rpos] == -1) 338 sblock.fs_rotbl[blk] = 0; 339 else 340 sblock.fs_rotbl[blk] = 341 sblock.fs_postbl[cylno][rpos] - blk; 342 sblock.fs_postbl[cylno][rpos] = blk; 343 } 344 next: 345 /* 346 * Validate specified/determined cpg. 347 */ 348 if (sblock.fs_spc > MAXBPG(&sblock) * NSPB(&sblock)) { 349 printf("too many sectors per cylinder (%d sectors)\n", 350 sblock.fs_spc); 351 while(sblock.fs_spc > MAXBPG(&sblock) * NSPB(&sblock)) { 352 sblock.fs_bsize <<= 1; 353 if (sblock.fs_frag < MAXFRAG) 354 sblock.fs_frag <<= 1; 355 else 356 sblock.fs_fsize <<= 1; 357 } 358 printf("nsect %d, and ntrak %d, requires block size of %d,\n", 359 sblock.fs_nsect, sblock.fs_ntrak, sblock.fs_bsize); 360 printf("\tand fragment size of %d\n", sblock.fs_fsize); 361 exit(1); 362 } 363 if (sblock.fs_fpg > MAXBPG(&sblock) * sblock.fs_frag) { 364 printf("cylinder group too large (%d cylinders); ", 365 sblock.fs_cpg); 366 printf("max: %d cylinders per group\n", 367 MAXBPG(&sblock) * sblock.fs_frag / 368 (sblock.fs_fpg / sblock.fs_cpg)); 369 exit(1); 370 } 371 sblock.fs_cgsize = fragroundup(&sblock, 372 sizeof(struct cg) + howmany(sblock.fs_fpg, NBBY)); 373 /* 374 * Compute/validate number of cylinder groups. 375 */ 376 sblock.fs_ncg = sblock.fs_ncyl / sblock.fs_cpg; 377 if (sblock.fs_ncyl % sblock.fs_cpg) 378 sblock.fs_ncg++; 379 if ((sblock.fs_spc * sblock.fs_cpg) % NSPF(&sblock)) { 380 printf("mkfs: nsect %d, ntrak %d, cpg %d is not tolerable\n", 381 sblock.fs_nsect, sblock.fs_ntrak, sblock.fs_cpg); 382 printf("as this would would have cyl groups whose size\n"); 383 printf("is not a multiple of %d; choke!\n", sblock.fs_fsize); 384 exit(1); 385 } 386 /* 387 * Compute number of inode blocks per cylinder group. 388 * Start with one inode per NBPI bytes; adjust as necessary. 389 */ 390 inos = MAX(NBPI, sblock.fs_fsize); 391 if (argc > 9) { 392 i = atoi(argv[9]); 393 if (i <= 0) 394 printf("%s: bogus nbpi reset to %d\n", argv[9], inos); 395 else 396 inos = i; 397 } 398 i = sblock.fs_iblkno + MAXIPG / INOPF(&sblock); 399 inos = (fssize - sblock.fs_ncg * i) * sblock.fs_fsize / inos / 400 INOPB(&sblock); 401 if (inos <= 0) 402 inos = 1; 403 sblock.fs_ipg = ((inos / sblock.fs_ncg) + 1) * INOPB(&sblock); 404 if (sblock.fs_ipg > MAXIPG) 405 sblock.fs_ipg = MAXIPG; 406 sblock.fs_dblkno = sblock.fs_iblkno + sblock.fs_ipg / INOPF(&sblock); 407 i = MIN(~sblock.fs_cgmask, sblock.fs_ncg - 1); 408 if (cgdmin(&sblock, i) - cgbase(&sblock, i) >= sblock.fs_fpg) { 409 printf("inode blocks/cyl group (%d) >= data blocks (%d)\n", 410 cgdmin(&sblock, i) - cgbase(&sblock, i) / sblock.fs_frag, 411 sblock.fs_fpg / sblock.fs_frag); 412 printf("number of cylinders per cylinder group must be increased\n"); 413 exit(1); 414 } 415 j = sblock.fs_ncg - 1; 416 if ((i = fssize - j * sblock.fs_fpg) < sblock.fs_fpg && 417 cgdmin(&sblock, j) - cgbase(&sblock, j) > i) { 418 printf("Warning: inode blocks/cyl group (%d) >= data blocks (%d) in last\n", 419 (cgdmin(&sblock, j) - cgbase(&sblock, j)) / sblock.fs_frag, 420 i / sblock.fs_frag); 421 printf(" cylinder group. This implies %d sector(s) cannot be allocated.\n", 422 i * NSPF(&sblock)); 423 sblock.fs_ncg--; 424 sblock.fs_ncyl -= sblock.fs_ncyl % sblock.fs_cpg; 425 sblock.fs_size = fssize = sblock.fs_ncyl * sblock.fs_spc / 426 NSPF(&sblock); 427 warn = 0; 428 } 429 if (warn) { 430 printf("Warning: %d sector(s) in last cylinder unallocated\n", 431 sblock.fs_spc - 432 (fssize * NSPF(&sblock) - (sblock.fs_ncyl - 1) 433 * sblock.fs_spc)); 434 } 435 /* 436 * fill in remaining fields of the super block 437 */ 438 sblock.fs_csaddr = cgdmin(&sblock, 0); 439 sblock.fs_cssize = 440 fragroundup(&sblock, sblock.fs_ncg * sizeof(struct csum)); 441 i = sblock.fs_bsize / sizeof(struct csum); 442 sblock.fs_csmask = ~(i - 1); 443 for (sblock.fs_csshift = 0; i > 1; i >>= 1) 444 sblock.fs_csshift++; 445 i = sizeof(struct fs) + 446 howmany(sblock.fs_spc * sblock.fs_cpc, NSPB(&sblock)); 447 sblock.fs_sbsize = fragroundup(&sblock, i); 448 fscs = (struct csum *)calloc(1, sblock.fs_cssize); 449 sblock.fs_magic = FS_MAGIC; 450 sblock.fs_rotdelay = ROTDELAY; 451 if (argc > 7) { 452 sblock.fs_minfree = atoi(argv[7]); 453 if (sblock.fs_minfree < 0 || sblock.fs_minfree > 99) { 454 printf("%s: bogus minfree reset to %d%%\n", argv[7], 455 MINFREE); 456 sblock.fs_minfree = MINFREE; 457 } 458 } else 459 sblock.fs_minfree = MINFREE; 460 sblock.fs_maxcontig = MAXCONTIG; 461 sblock.fs_maxbpg = MAXBLKPG(&sblock); 462 if (argc > 8) 463 sblock.fs_rps = atoi(argv[8]); 464 else 465 sblock.fs_rps = DEFHZ; 466 sblock.fs_cgrotor = 0; 467 sblock.fs_cstotal.cs_ndir = 0; 468 sblock.fs_cstotal.cs_nbfree = 0; 469 sblock.fs_cstotal.cs_nifree = 0; 470 sblock.fs_cstotal.cs_nffree = 0; 471 sblock.fs_fmod = 0; 472 sblock.fs_ronly = 0; 473 /* 474 * Dump out summary information about file system. 475 */ 476 printf("%s:\t%d sectors in %d cylinders of %d tracks, %d sectors\n", 477 fsys, sblock.fs_size * NSPF(&sblock), sblock.fs_ncyl, 478 sblock.fs_ntrak, sblock.fs_nsect); 479 printf("\t%.1fMb in %d cyl groups (%d c/g, %.2fMb/g, %d i/g)\n", 480 (float)sblock.fs_size * sblock.fs_fsize * 1e-6, sblock.fs_ncg, 481 sblock.fs_cpg, (float)sblock.fs_fpg * sblock.fs_fsize * 1e-6, 482 sblock.fs_ipg); 483 /* 484 * Now build the cylinders group blocks and 485 * then print out indices of cylinder groups. 486 */ 487 printf("super-block backups (for fsck -b#) at:"); 488 for (cylno = 0; cylno < sblock.fs_ncg; cylno++) { 489 initcg(cylno); 490 if (cylno % 10 == 0) 491 printf("\n"); 492 printf(" %d,", fsbtodb(&sblock, cgsblock(&sblock, cylno))); 493 } 494 printf("\n"); 495 /* 496 * Now construct the initial file system, 497 * then write out the super-block. 498 */ 499 fsinit(); 500 sblock.fs_time = utime; 501 wtfs(SBLOCK, SBSIZE, (char *)&sblock); 502 for (i = 0; i < sblock.fs_cssize; i += sblock.fs_bsize) 503 wtfs(fsbtodb(&sblock, sblock.fs_csaddr + numfrags(&sblock, i)), 504 sblock.fs_cssize - i < sblock.fs_bsize ? 505 sblock.fs_cssize - i : sblock.fs_bsize, 506 ((char *)fscs) + i); 507 /* 508 * Write out the duplicate super blocks 509 */ 510 for (cylno = 0; cylno < sblock.fs_ncg; cylno++) 511 wtfs(fsbtodb(&sblock, cgsblock(&sblock, cylno)), 512 SBSIZE, (char *)&sblock); 513 #ifndef STANDALONE 514 exit(0); 515 #endif 516 } 517 518 /* 519 * Initialize a cylinder group. 520 */ 521 initcg(cylno) 522 int cylno; 523 { 524 daddr_t cbase, d, dlower, dupper, dmax; 525 long i, j, s; 526 register struct csum *cs; 527 528 /* 529 * Determine block bounds for cylinder group. 530 * Allow space for super block summary information in first 531 * cylinder group. 532 */ 533 cbase = cgbase(&sblock, cylno); 534 dmax = cbase + sblock.fs_fpg; 535 if (dmax > sblock.fs_size) 536 dmax = sblock.fs_size; 537 dlower = cgsblock(&sblock, cylno) - cbase; 538 dupper = cgdmin(&sblock, cylno) - cbase; 539 cs = fscs + cylno; 540 acg.cg_time = utime; 541 acg.cg_magic = CG_MAGIC; 542 acg.cg_cgx = cylno; 543 if (cylno == sblock.fs_ncg - 1) 544 acg.cg_ncyl = sblock.fs_ncyl % sblock.fs_cpg; 545 else 546 acg.cg_ncyl = sblock.fs_cpg; 547 acg.cg_niblk = sblock.fs_ipg; 548 acg.cg_ndblk = dmax - cbase; 549 acg.cg_cs.cs_ndir = 0; 550 acg.cg_cs.cs_nffree = 0; 551 acg.cg_cs.cs_nbfree = 0; 552 acg.cg_cs.cs_nifree = 0; 553 acg.cg_rotor = 0; 554 acg.cg_frotor = 0; 555 acg.cg_irotor = 0; 556 for (i = 0; i < sblock.fs_frag; i++) { 557 acg.cg_frsum[i] = 0; 558 } 559 for (i = 0; i < sblock.fs_ipg; ) { 560 for (j = INOPB(&sblock); j > 0; j--) { 561 clrbit(acg.cg_iused, i); 562 i++; 563 } 564 acg.cg_cs.cs_nifree += INOPB(&sblock); 565 } 566 if (cylno == 0) 567 for (i = 0; i < ROOTINO; i++) { 568 setbit(acg.cg_iused, i); 569 acg.cg_cs.cs_nifree--; 570 } 571 while (i < MAXIPG) { 572 clrbit(acg.cg_iused, i); 573 i++; 574 } 575 lseek(fso, fsbtodb(&sblock, cgimin(&sblock, cylno)) * DEV_BSIZE, 0); 576 if (write(fso, (char *)zino, sblock.fs_ipg * sizeof (struct dinode)) != 577 sblock.fs_ipg * sizeof (struct dinode)) 578 printf("write error %D\n", numfrags(&sblock, tell(fso))); 579 for (i = 0; i < MAXCPG; i++) { 580 acg.cg_btot[i] = 0; 581 for (j = 0; j < NRPOS; j++) 582 acg.cg_b[i][j] = 0; 583 } 584 if (cylno == 0) { 585 /* 586 * reserve space for summary info and Boot block 587 */ 588 dupper += howmany(sblock.fs_cssize, sblock.fs_fsize); 589 for (d = 0; d < dlower; d += sblock.fs_frag) 590 clrblock(&sblock, acg.cg_free, d/sblock.fs_frag); 591 } else { 592 for (d = 0; d < dlower; d += sblock.fs_frag) { 593 setblock(&sblock, acg.cg_free, d/sblock.fs_frag); 594 acg.cg_cs.cs_nbfree++; 595 acg.cg_btot[cbtocylno(&sblock, d)]++; 596 acg.cg_b[cbtocylno(&sblock, d)][cbtorpos(&sblock, d)]++; 597 } 598 sblock.fs_dsize += dlower; 599 } 600 sblock.fs_dsize += acg.cg_ndblk - dupper; 601 for (; d < dupper; d += sblock.fs_frag) 602 clrblock(&sblock, acg.cg_free, d/sblock.fs_frag); 603 if (d > dupper) { 604 acg.cg_frsum[d - dupper]++; 605 for (i = d - 1; i >= dupper; i--) { 606 setbit(acg.cg_free, i); 607 acg.cg_cs.cs_nffree++; 608 } 609 } 610 while ((d + sblock.fs_frag) <= dmax - cbase) { 611 setblock(&sblock, acg.cg_free, d/sblock.fs_frag); 612 acg.cg_cs.cs_nbfree++; 613 acg.cg_btot[cbtocylno(&sblock, d)]++; 614 acg.cg_b[cbtocylno(&sblock, d)][cbtorpos(&sblock, d)]++; 615 d += sblock.fs_frag; 616 } 617 if (d < dmax - cbase) { 618 acg.cg_frsum[dmax - cbase - d]++; 619 for (; d < dmax - cbase; d++) { 620 setbit(acg.cg_free, d); 621 acg.cg_cs.cs_nffree++; 622 } 623 for (; d % sblock.fs_frag != 0; d++) 624 clrbit(acg.cg_free, d); 625 } 626 for (d /= sblock.fs_frag; d < MAXBPG(&sblock); d ++) 627 clrblock(&sblock, acg.cg_free, d); 628 sblock.fs_cstotal.cs_ndir += acg.cg_cs.cs_ndir; 629 sblock.fs_cstotal.cs_nffree += acg.cg_cs.cs_nffree; 630 sblock.fs_cstotal.cs_nbfree += acg.cg_cs.cs_nbfree; 631 sblock.fs_cstotal.cs_nifree += acg.cg_cs.cs_nifree; 632 *cs = acg.cg_cs; 633 wtfs(fsbtodb(&sblock, cgtod(&sblock, cylno)), 634 sblock.fs_bsize, (char *)&acg); 635 } 636 637 /* 638 * initialize the file system 639 */ 640 struct inode node; 641 #define PREDEFDIR 3 642 struct direct root_dir[] = { 643 { ROOTINO, sizeof(struct direct), 1, "." }, 644 { ROOTINO, sizeof(struct direct), 2, ".." }, 645 { LOSTFOUNDINO, sizeof(struct direct), 10, "lost+found" }, 646 }; 647 struct direct lost_found_dir[] = { 648 { LOSTFOUNDINO, sizeof(struct direct), 1, "." }, 649 { ROOTINO, sizeof(struct direct), 2, ".." }, 650 { 0, DIRBLKSIZ, 0, 0 }, 651 }; 652 char buf[MAXBSIZE]; 653 654 fsinit() 655 { 656 int i; 657 658 /* 659 * initialize the node 660 */ 661 node.i_atime = utime; 662 node.i_mtime = utime; 663 node.i_ctime = utime; 664 /* 665 * create the lost+found directory 666 */ 667 (void)makedir(lost_found_dir, 2); 668 for (i = DIRBLKSIZ; i < sblock.fs_bsize; i += DIRBLKSIZ) 669 bcopy(&lost_found_dir[2], &buf[i], DIRSIZ(&lost_found_dir[2])); 670 node.i_number = LOSTFOUNDINO; 671 node.i_mode = IFDIR | UMASK; 672 node.i_nlink = 2; 673 node.i_size = sblock.fs_bsize; 674 node.i_db[0] = alloc(node.i_size, node.i_mode); 675 node.i_blocks = howmany(node.i_size, DEV_BSIZE); 676 wtfs(fsbtodb(&sblock, node.i_db[0]), node.i_size, buf); 677 iput(&node); 678 /* 679 * create the root directory 680 */ 681 node.i_number = ROOTINO; 682 node.i_mode = IFDIR | UMASK; 683 node.i_nlink = PREDEFDIR; 684 node.i_size = makedir(root_dir, PREDEFDIR); 685 node.i_db[0] = alloc(sblock.fs_fsize, node.i_mode); 686 node.i_blocks = howmany(node.i_size, DEV_BSIZE); 687 wtfs(fsbtodb(&sblock, node.i_db[0]), sblock.fs_fsize, buf); 688 iput(&node); 689 } 690 691 /* 692 * construct a set of directory entries in "buf". 693 * return size of directory. 694 */ 695 makedir(protodir, entries) 696 register struct direct *protodir; 697 int entries; 698 { 699 char *cp; 700 int i, spcleft; 701 702 spcleft = DIRBLKSIZ; 703 for (cp = buf, i = 0; i < entries - 1; i++) { 704 protodir[i].d_reclen = DIRSIZ(&protodir[i]); 705 bcopy(&protodir[i], cp, protodir[i].d_reclen); 706 cp += protodir[i].d_reclen; 707 spcleft -= protodir[i].d_reclen; 708 } 709 protodir[i].d_reclen = spcleft; 710 bcopy(&protodir[i], cp, DIRSIZ(&protodir[i])); 711 cp += DIRSIZ(&protodir[i]); 712 return (cp - buf); 713 } 714 715 /* 716 * allocate a block or frag 717 */ 718 daddr_t 719 alloc(size, mode) 720 int size; 721 int mode; 722 { 723 int i, frag; 724 daddr_t d; 725 726 rdfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, 727 (char *)&acg); 728 if (acg.cg_magic != CG_MAGIC) { 729 printf("cg 0: bad magic number\n"); 730 return (0); 731 } 732 if (acg.cg_cs.cs_nbfree == 0) { 733 printf("first cylinder group ran out of space\n"); 734 return (0); 735 } 736 for (d = 0; d < acg.cg_ndblk; d += sblock.fs_frag) 737 if (isblock(&sblock, acg.cg_free, d / sblock.fs_frag)) 738 goto goth; 739 printf("internal error: can't find block in cyl 0\n"); 740 return (0); 741 goth: 742 clrblock(&sblock, acg.cg_free, d / sblock.fs_frag); 743 acg.cg_cs.cs_nbfree--; 744 sblock.fs_cstotal.cs_nbfree--; 745 fscs[0].cs_nbfree--; 746 if (mode & IFDIR) { 747 acg.cg_cs.cs_ndir++; 748 sblock.fs_cstotal.cs_ndir++; 749 fscs[0].cs_ndir++; 750 } 751 acg.cg_btot[cbtocylno(&sblock, d)]--; 752 acg.cg_b[cbtocylno(&sblock, d)][cbtorpos(&sblock, d)]--; 753 if (size != sblock.fs_bsize) { 754 frag = howmany(size, sblock.fs_fsize); 755 fscs[0].cs_nffree += sblock.fs_frag - frag; 756 sblock.fs_cstotal.cs_nffree += sblock.fs_frag - frag; 757 acg.cg_cs.cs_nffree += sblock.fs_frag - frag; 758 acg.cg_frsum[sblock.fs_frag - frag]++; 759 for (i = frag; i < sblock.fs_frag; i++) 760 setbit(acg.cg_free, d + i); 761 } 762 wtfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, 763 (char *)&acg); 764 return (d); 765 } 766 767 /* 768 * Allocate an inode on the disk 769 */ 770 iput(ip) 771 register struct inode *ip; 772 { 773 struct dinode buf[MAXINOPB]; 774 daddr_t d; 775 int c; 776 777 c = itog(&sblock, ip->i_number); 778 rdfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, 779 (char *)&acg); 780 if (acg.cg_magic != CG_MAGIC) { 781 printf("cg 0: bad magic number\n"); 782 exit(1); 783 } 784 acg.cg_cs.cs_nifree--; 785 setbit(acg.cg_iused, ip->i_number); 786 wtfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, 787 (char *)&acg); 788 sblock.fs_cstotal.cs_nifree--; 789 fscs[0].cs_nifree--; 790 if(ip->i_number >= sblock.fs_ipg * sblock.fs_ncg) { 791 printf("fsinit: inode value out of range (%d).\n", 792 ip->i_number); 793 exit(1); 794 } 795 d = fsbtodb(&sblock, itod(&sblock, ip->i_number)); 796 rdfs(d, sblock.fs_bsize, buf); 797 buf[itoo(&sblock, ip->i_number)].di_ic = ip->i_ic; 798 wtfs(d, sblock.fs_bsize, buf); 799 } 800 801 /* 802 * read a block from the file system 803 */ 804 rdfs(bno, size, bf) 805 daddr_t bno; 806 int size; 807 char *bf; 808 { 809 int n; 810 811 if (lseek(fsi, bno * DEV_BSIZE, 0) < 0) { 812 printf("seek error: %ld\n", bno); 813 perror("rdfs"); 814 exit(1); 815 } 816 n = read(fsi, bf, size); 817 if(n != size) { 818 printf("read error: %ld\n", bno); 819 perror("rdfs"); 820 exit(1); 821 } 822 } 823 824 /* 825 * write a block to the file system 826 */ 827 wtfs(bno, size, bf) 828 daddr_t bno; 829 int size; 830 char *bf; 831 { 832 int n; 833 834 if (lseek(fso, bno * DEV_BSIZE, 0) < 0) { 835 printf("seek error: %ld\n", bno); 836 perror("wtfs"); 837 exit(1); 838 } 839 n = write(fso, bf, size); 840 if(n != size) { 841 printf("write error: %D\n", bno); 842 perror("wtfs"); 843 exit(1); 844 } 845 } 846 847 /* 848 * check if a block is available 849 */ 850 isblock(fs, cp, h) 851 struct fs *fs; 852 unsigned char *cp; 853 int h; 854 { 855 unsigned char mask; 856 857 switch (fs->fs_frag) { 858 case 8: 859 return (cp[h] == 0xff); 860 case 4: 861 mask = 0x0f << ((h & 0x1) << 2); 862 return ((cp[h >> 1] & mask) == mask); 863 case 2: 864 mask = 0x03 << ((h & 0x3) << 1); 865 return ((cp[h >> 2] & mask) == mask); 866 case 1: 867 mask = 0x01 << (h & 0x7); 868 return ((cp[h >> 3] & mask) == mask); 869 default: 870 #ifdef STANDALONE 871 printf("isblock bad fs_frag %d\n", fs->fs_frag); 872 #else 873 fprintf(stderr, "isblock bad fs_frag %d\n", fs->fs_frag); 874 #endif 875 return; 876 } 877 } 878 879 /* 880 * take a block out of the map 881 */ 882 clrblock(fs, cp, h) 883 struct fs *fs; 884 unsigned char *cp; 885 int h; 886 { 887 switch ((fs)->fs_frag) { 888 case 8: 889 cp[h] = 0; 890 return; 891 case 4: 892 cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); 893 return; 894 case 2: 895 cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); 896 return; 897 case 1: 898 cp[h >> 3] &= ~(0x01 << (h & 0x7)); 899 return; 900 default: 901 #ifdef STANDALONE 902 printf("clrblock bad fs_frag %d\n", fs->fs_frag); 903 #else 904 fprintf(stderr, "clrblock bad fs_frag %d\n", fs->fs_frag); 905 #endif 906 return; 907 } 908 } 909 910 /* 911 * put a block into the map 912 */ 913 setblock(fs, cp, h) 914 struct fs *fs; 915 unsigned char *cp; 916 int h; 917 { 918 switch (fs->fs_frag) { 919 case 8: 920 cp[h] = 0xff; 921 return; 922 case 4: 923 cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); 924 return; 925 case 2: 926 cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); 927 return; 928 case 1: 929 cp[h >> 3] |= (0x01 << (h & 0x7)); 930 return; 931 default: 932 #ifdef STANDALONE 933 printf("setblock bad fs_frag %d\n", fs->fs_frag); 934 #else 935 fprintf(stderr, "setblock bad fs_frag %d\n", fs->fs_frag); 936 #endif 937 return; 938 } 939 } 940