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