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