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