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