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