|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1980, 1989 The Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms are permitted provided ! 6: * that: (1) source distributions retain this entire copyright notice and ! 7: * comment, and (2) distributions including binaries display the following ! 8: * acknowledgement: ``This product includes software developed by the ! 9: * University of California, Berkeley and its contributors'' in the ! 10: * documentation or other materials provided with the distribution and in ! 11: * all advertising materials mentioning features or use of this software. ! 12: * Neither the name of the University nor the names of its contributors may ! 13: * be used to endorse or promote products derived from this software without ! 14: * specific prior written permission. ! 15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED ! 16: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF ! 17: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 18: */ ! 19: ! 20: #ifndef lint ! 21: static char sccsid[] = "@(#)mkfs.c 6.15 (Berkeley) 6/29/90"; ! 22: #endif /* not lint */ ! 23: ! 24: #ifndef STANDALONE ! 25: #include <stdio.h> ! 26: #include <a.out.h> ! 27: #endif ! 28: ! 29: #include <sys/param.h> ! 30: #include <sys/time.h> ! 31: #include <sys/wait.h> ! 32: #include <sys/resource.h> ! 33: #include <ufs/dinode.h> ! 34: #include <ufs/fs.h> ! 35: #include <ufs/dir.h> ! 36: #include <sys/disklabel.h> ! 37: #include <machine/endian.h> ! 38: ! 39: /* ! 40: * make file system for cylinder-group style file systems ! 41: */ ! 42: ! 43: /* ! 44: * The size of a cylinder group is calculated by CGSIZE. The maximum size ! 45: * is limited by the fact that cylinder groups are at most one block. ! 46: * Its size is derived from the size of the maps maintained in the ! 47: * cylinder group and the (struct cg) size. ! 48: */ ! 49: #define CGSIZE(fs) \ ! 50: /* base cg */ (sizeof(struct cg) + \ ! 51: /* blktot size */ (fs)->fs_cpg * sizeof(long) + \ ! 52: /* blks size */ (fs)->fs_cpg * (fs)->fs_nrpos * sizeof(short) + \ ! 53: /* inode map */ howmany((fs)->fs_ipg, NBBY) + \ ! 54: /* block map */ howmany((fs)->fs_cpg * (fs)->fs_spc / NSPF(fs), NBBY)) ! 55: ! 56: /* ! 57: * We limit the size of the inode map to be no more than a ! 58: * third of the cylinder group space, since we must leave at ! 59: * least an equal amount of space for the block map. ! 60: * ! 61: * N.B.: MAXIPG must be a multiple of INOPB(fs). ! 62: */ ! 63: #define MAXIPG(fs) roundup((fs)->fs_bsize * NBBY / 3, INOPB(fs)) ! 64: ! 65: #define UMASK 0755 ! 66: #define MAXINOPB (MAXBSIZE / sizeof(struct dinode)) ! 67: #define POWEROF2(num) (((num) & ((num) - 1)) == 0) ! 68: ! 69: /* ! 70: * variables set up by front end. ! 71: */ ! 72: extern int mfs; /* run as the memory based filesystem */ ! 73: extern int Nflag; /* run mkfs without writing file system */ ! 74: extern int fssize; /* file system size */ ! 75: extern int ntracks; /* # tracks/cylinder */ ! 76: extern int nsectors; /* # sectors/track */ ! 77: extern int nphyssectors; /* # sectors/track including spares */ ! 78: extern int secpercyl; /* sectors per cylinder */ ! 79: extern int sectorsize; /* bytes/sector */ ! 80: extern int rpm; /* revolutions/minute of drive */ ! 81: extern int interleave; /* hardware sector interleave */ ! 82: extern int trackskew; /* sector 0 skew, per track */ ! 83: extern int headswitch; /* head switch time, usec */ ! 84: extern int trackseek; /* track-to-track seek, usec */ ! 85: extern int fsize; /* fragment size */ ! 86: extern int bsize; /* block size */ ! 87: extern int cpg; /* cylinders/cylinder group */ ! 88: extern int cpgflg; /* cylinders/cylinder group flag was given */ ! 89: extern int minfree; /* free space threshold */ ! 90: extern int opt; /* optimization preference (space or time) */ ! 91: extern int density; /* number of bytes per inode */ ! 92: extern int maxcontig; /* max contiguous blocks to allocate */ ! 93: extern int rotdelay; /* rotational delay between blocks */ ! 94: extern int maxbpg; /* maximum blocks per file in a cyl group */ ! 95: extern int nrpos; /* # of distinguished rotational positions */ ! 96: extern int bbsize; /* boot block size */ ! 97: extern int sbsize; /* superblock size */ ! 98: extern u_long memleft; /* virtual memory available */ ! 99: extern caddr_t membase; /* start address of memory based filesystem */ ! 100: extern caddr_t malloc(), calloc(); ! 101: ! 102: union { ! 103: struct fs fs; ! 104: char pad[SBSIZE]; ! 105: } fsun; ! 106: #define sblock fsun.fs ! 107: struct csum *fscs; ! 108: ! 109: union { ! 110: struct cg cg; ! 111: char pad[MAXBSIZE]; ! 112: } cgun; ! 113: #define acg cgun.cg ! 114: ! 115: struct dinode zino[MAXBSIZE / sizeof(struct dinode)]; ! 116: ! 117: int fsi, fso; ! 118: time_t utime; ! 119: daddr_t alloc(); ! 120: ! 121: mkfs(pp, fsys, fi, fo) ! 122: struct partition *pp; ! 123: char *fsys; ! 124: int fi, fo; ! 125: { ! 126: register long i, mincpc, mincpg, inospercg; ! 127: long cylno, rpos, blk, j, warn = 0; ! 128: long used, mincpgcnt, bpcg; ! 129: long mapcramped, inodecramped; ! 130: long postblsize, rotblsize, totalsbsize; ! 131: int ppid, status, started(); ! 132: ! 133: #ifndef STANDALONE ! 134: time(&utime); ! 135: #endif ! 136: if (mfs) { ! 137: ppid = getpid(); ! 138: (void) signal(SIGUSR1, started); ! 139: if (i = fork()) { ! 140: if (i == -1) { ! 141: perror("mfs"); ! 142: exit(10); ! 143: } ! 144: if (waitpid(i, &status, 0) != -1 && WIFEXITED(status)) ! 145: exit(WEXITSTATUS(status)); ! 146: exit(11); ! 147: /* NOTREACHED */ ! 148: } ! 149: (void)malloc(0); ! 150: if (fssize * sectorsize > memleft) ! 151: fssize = (memleft - 16384) / sectorsize; ! 152: if ((membase = malloc(fssize * sectorsize)) == 0) ! 153: exit(12); ! 154: } ! 155: fsi = fi; ! 156: fso = fo; ! 157: /* ! 158: * Validate the given file system size. ! 159: * Verify that its last block can actually be accessed. ! 160: */ ! 161: if (fssize <= 0) ! 162: printf("preposterous size %d\n", fssize), exit(13); ! 163: wtfs(fssize - 1, sectorsize, (char *)&sblock); ! 164: /* ! 165: * collect and verify the sector and track info ! 166: */ ! 167: sblock.fs_nsect = nsectors; ! 168: sblock.fs_ntrak = ntracks; ! 169: if (sblock.fs_ntrak <= 0) ! 170: printf("preposterous ntrak %d\n", sblock.fs_ntrak), exit(14); ! 171: if (sblock.fs_nsect <= 0) ! 172: printf("preposterous nsect %d\n", sblock.fs_nsect), exit(15); ! 173: /* ! 174: * collect and verify the block and fragment sizes ! 175: */ ! 176: sblock.fs_bsize = bsize; ! 177: sblock.fs_fsize = fsize; ! 178: if (!POWEROF2(sblock.fs_bsize)) { ! 179: printf("block size must be a power of 2, not %d\n", ! 180: sblock.fs_bsize); ! 181: exit(16); ! 182: } ! 183: if (!POWEROF2(sblock.fs_fsize)) { ! 184: printf("fragment size must be a power of 2, not %d\n", ! 185: sblock.fs_fsize); ! 186: exit(17); ! 187: } ! 188: if (sblock.fs_fsize < sectorsize) { ! 189: printf("fragment size %d is too small, minimum is %d\n", ! 190: sblock.fs_fsize, sectorsize); ! 191: exit(18); ! 192: } ! 193: if (sblock.fs_bsize < MINBSIZE) { ! 194: printf("block size %d is too small, minimum is %d\n", ! 195: sblock.fs_bsize, MINBSIZE); ! 196: exit(19); ! 197: } ! 198: if (sblock.fs_bsize < sblock.fs_fsize) { ! 199: printf("block size (%d) cannot be smaller than fragment size (%d)\n", ! 200: sblock.fs_bsize, sblock.fs_fsize); ! 201: exit(20); ! 202: } ! 203: sblock.fs_bmask = ~(sblock.fs_bsize - 1); ! 204: sblock.fs_fmask = ~(sblock.fs_fsize - 1); ! 205: /* ! 206: * Planning now for future expansion. ! 207: */ ! 208: # if (BYTE_ORDER == BIG_ENDIAN) ! 209: sblock.fs_qbmask.val[0] = 0; ! 210: sblock.fs_qbmask.val[1] = ~sblock.fs_bmask; ! 211: sblock.fs_qfmask.val[0] = 0; ! 212: sblock.fs_qfmask.val[1] = ~sblock.fs_fmask; ! 213: # endif /* BIG_ENDIAN */ ! 214: # if (BYTE_ORDER == LITTLE_ENDIAN) ! 215: sblock.fs_qbmask.val[0] = ~sblock.fs_bmask; ! 216: sblock.fs_qbmask.val[1] = 0; ! 217: sblock.fs_qfmask.val[0] = ~sblock.fs_fmask; ! 218: sblock.fs_qfmask.val[1] = 0; ! 219: # endif /* LITTLE_ENDIAN */ ! 220: for (sblock.fs_bshift = 0, i = sblock.fs_bsize; i > 1; i >>= 1) ! 221: sblock.fs_bshift++; ! 222: for (sblock.fs_fshift = 0, i = sblock.fs_fsize; i > 1; i >>= 1) ! 223: sblock.fs_fshift++; ! 224: sblock.fs_frag = numfrags(&sblock, sblock.fs_bsize); ! 225: for (sblock.fs_fragshift = 0, i = sblock.fs_frag; i > 1; i >>= 1) ! 226: sblock.fs_fragshift++; ! 227: if (sblock.fs_frag > MAXFRAG) { ! 228: printf("fragment size %d is too small, minimum with block size %d is %d\n", ! 229: sblock.fs_fsize, sblock.fs_bsize, ! 230: sblock.fs_bsize / MAXFRAG); ! 231: exit(21); ! 232: } ! 233: sblock.fs_nrpos = nrpos; ! 234: sblock.fs_nindir = sblock.fs_bsize / sizeof(daddr_t); ! 235: sblock.fs_inopb = sblock.fs_bsize / sizeof(struct dinode); ! 236: sblock.fs_nspf = sblock.fs_fsize / sectorsize; ! 237: for (sblock.fs_fsbtodb = 0, i = NSPF(&sblock); i > 1; i >>= 1) ! 238: sblock.fs_fsbtodb++; ! 239: sblock.fs_sblkno = ! 240: roundup(howmany(bbsize + sbsize, sblock.fs_fsize), sblock.fs_frag); ! 241: sblock.fs_cblkno = (daddr_t)(sblock.fs_sblkno + ! 242: roundup(howmany(sbsize, sblock.fs_fsize), sblock.fs_frag)); ! 243: sblock.fs_iblkno = sblock.fs_cblkno + sblock.fs_frag; ! 244: sblock.fs_cgoffset = roundup( ! 245: howmany(sblock.fs_nsect, NSPF(&sblock)), sblock.fs_frag); ! 246: for (sblock.fs_cgmask = 0xffffffff, i = sblock.fs_ntrak; i > 1; i >>= 1) ! 247: sblock.fs_cgmask <<= 1; ! 248: if (!POWEROF2(sblock.fs_ntrak)) ! 249: sblock.fs_cgmask <<= 1; ! 250: /* ! 251: * Validate specified/determined secpercyl ! 252: * and calculate minimum cylinders per group. ! 253: */ ! 254: sblock.fs_spc = secpercyl; ! 255: for (sblock.fs_cpc = NSPB(&sblock), i = sblock.fs_spc; ! 256: sblock.fs_cpc > 1 && (i & 1) == 0; ! 257: sblock.fs_cpc >>= 1, i >>= 1) ! 258: /* void */; ! 259: mincpc = sblock.fs_cpc; ! 260: bpcg = sblock.fs_spc * sectorsize; ! 261: inospercg = roundup(bpcg / sizeof(struct dinode), INOPB(&sblock)); ! 262: if (inospercg > MAXIPG(&sblock)) ! 263: inospercg = MAXIPG(&sblock); ! 264: used = (sblock.fs_iblkno + inospercg / INOPF(&sblock)) * NSPF(&sblock); ! 265: mincpgcnt = howmany(sblock.fs_cgoffset * (~sblock.fs_cgmask) + used, ! 266: sblock.fs_spc); ! 267: mincpg = roundup(mincpgcnt, mincpc); ! 268: /* ! 269: * Insure that cylinder group with mincpg has enough space ! 270: * for block maps ! 271: */ ! 272: sblock.fs_cpg = mincpg; ! 273: sblock.fs_ipg = inospercg; ! 274: mapcramped = 0; ! 275: while (CGSIZE(&sblock) > sblock.fs_bsize) { ! 276: mapcramped = 1; ! 277: if (sblock.fs_bsize < MAXBSIZE) { ! 278: sblock.fs_bsize <<= 1; ! 279: if ((i & 1) == 0) { ! 280: i >>= 1; ! 281: } else { ! 282: sblock.fs_cpc <<= 1; ! 283: mincpc <<= 1; ! 284: mincpg = roundup(mincpgcnt, mincpc); ! 285: sblock.fs_cpg = mincpg; ! 286: } ! 287: sblock.fs_frag <<= 1; ! 288: sblock.fs_fragshift += 1; ! 289: if (sblock.fs_frag <= MAXFRAG) ! 290: continue; ! 291: } ! 292: if (sblock.fs_fsize == sblock.fs_bsize) { ! 293: printf("There is no block size that"); ! 294: printf(" can support this disk\n"); ! 295: exit(22); ! 296: } ! 297: sblock.fs_frag >>= 1; ! 298: sblock.fs_fragshift -= 1; ! 299: sblock.fs_fsize <<= 1; ! 300: sblock.fs_nspf <<= 1; ! 301: } ! 302: /* ! 303: * Insure that cylinder group with mincpg has enough space for inodes ! 304: */ ! 305: inodecramped = 0; ! 306: used *= sectorsize; ! 307: inospercg = roundup((mincpg * bpcg - used) / density, INOPB(&sblock)); ! 308: sblock.fs_ipg = inospercg; ! 309: while (inospercg > MAXIPG(&sblock)) { ! 310: inodecramped = 1; ! 311: if (mincpc == 1 || sblock.fs_frag == 1 || ! 312: sblock.fs_bsize == MINBSIZE) ! 313: break; ! 314: printf("With a block size of %d %s %d\n", sblock.fs_bsize, ! 315: "minimum bytes per inode is", ! 316: (mincpg * bpcg - used) / MAXIPG(&sblock) + 1); ! 317: sblock.fs_bsize >>= 1; ! 318: sblock.fs_frag >>= 1; ! 319: sblock.fs_fragshift -= 1; ! 320: mincpc >>= 1; ! 321: sblock.fs_cpg = roundup(mincpgcnt, mincpc); ! 322: if (CGSIZE(&sblock) > sblock.fs_bsize) { ! 323: sblock.fs_bsize <<= 1; ! 324: break; ! 325: } ! 326: mincpg = sblock.fs_cpg; ! 327: inospercg = ! 328: roundup((mincpg * bpcg - used) / density, INOPB(&sblock)); ! 329: sblock.fs_ipg = inospercg; ! 330: } ! 331: if (inodecramped) { ! 332: if (inospercg > MAXIPG(&sblock)) { ! 333: printf("Minimum bytes per inode is %d\n", ! 334: (mincpg * bpcg - used) / MAXIPG(&sblock) + 1); ! 335: } else if (!mapcramped) { ! 336: printf("With %d bytes per inode, ", density); ! 337: printf("minimum cylinders per group is %d\n", mincpg); ! 338: } ! 339: } ! 340: if (mapcramped) { ! 341: printf("With %d sectors per cylinder, ", sblock.fs_spc); ! 342: printf("minimum cylinders per group is %d\n", mincpg); ! 343: } ! 344: if (inodecramped || mapcramped) { ! 345: if (sblock.fs_bsize != bsize) ! 346: printf("%s to be changed from %d to %d\n", ! 347: "This requires the block size", ! 348: bsize, sblock.fs_bsize); ! 349: if (sblock.fs_fsize != fsize) ! 350: printf("\t%s to be changed from %d to %d\n", ! 351: "and the fragment size", ! 352: fsize, sblock.fs_fsize); ! 353: exit(23); ! 354: } ! 355: /* ! 356: * Calculate the number of cylinders per group ! 357: */ ! 358: sblock.fs_cpg = cpg; ! 359: if (sblock.fs_cpg % mincpc != 0) { ! 360: printf("%s groups must have a multiple of %d cylinders\n", ! 361: cpgflg ? "Cylinder" : "Warning: cylinder", mincpc); ! 362: sblock.fs_cpg = roundup(sblock.fs_cpg, mincpc); ! 363: if (!cpgflg) ! 364: cpg = sblock.fs_cpg; ! 365: } ! 366: /* ! 367: * Must insure there is enough space for inodes ! 368: */ ! 369: sblock.fs_ipg = roundup((sblock.fs_cpg * bpcg - used) / density, ! 370: INOPB(&sblock)); ! 371: while (sblock.fs_ipg > MAXIPG(&sblock)) { ! 372: inodecramped = 1; ! 373: sblock.fs_cpg -= mincpc; ! 374: sblock.fs_ipg = roundup((sblock.fs_cpg * bpcg - used) / density, ! 375: INOPB(&sblock)); ! 376: } ! 377: /* ! 378: * Must insure there is enough space to hold block map ! 379: */ ! 380: while (CGSIZE(&sblock) > sblock.fs_bsize) { ! 381: mapcramped = 1; ! 382: sblock.fs_cpg -= mincpc; ! 383: sblock.fs_ipg = roundup((sblock.fs_cpg * bpcg - used) / density, ! 384: INOPB(&sblock)); ! 385: } ! 386: sblock.fs_fpg = (sblock.fs_cpg * sblock.fs_spc) / NSPF(&sblock); ! 387: if ((sblock.fs_cpg * sblock.fs_spc) % NSPB(&sblock) != 0) { ! 388: printf("panic (fs_cpg * fs_spc) % NSPF != 0"); ! 389: exit(24); ! 390: } ! 391: if (sblock.fs_cpg < mincpg) { ! 392: printf("cylinder groups must have at least %d cylinders\n", ! 393: mincpg); ! 394: exit(25); ! 395: } else if (sblock.fs_cpg != cpg) { ! 396: if (!cpgflg) ! 397: printf("Warning: "); ! 398: else if (!mapcramped && !inodecramped) ! 399: exit(26); ! 400: if (mapcramped && inodecramped) ! 401: printf("Block size and bytes per inode restrict"); ! 402: else if (mapcramped) ! 403: printf("Block size restricts"); ! 404: else ! 405: printf("Bytes per inode restrict"); ! 406: printf(" cylinders per group to %d.\n", sblock.fs_cpg); ! 407: if (cpgflg) ! 408: exit(27); ! 409: } ! 410: sblock.fs_cgsize = fragroundup(&sblock, CGSIZE(&sblock)); ! 411: /* ! 412: * Now have size for file system and nsect and ntrak. ! 413: * Determine number of cylinders and blocks in the file system. ! 414: */ ! 415: sblock.fs_size = fssize = dbtofsb(&sblock, fssize); ! 416: sblock.fs_ncyl = fssize * NSPF(&sblock) / sblock.fs_spc; ! 417: if (fssize * NSPF(&sblock) > sblock.fs_ncyl * sblock.fs_spc) { ! 418: sblock.fs_ncyl++; ! 419: warn = 1; ! 420: } ! 421: if (sblock.fs_ncyl < 1) { ! 422: printf("file systems must have at least one cylinder\n"); ! 423: exit(28); ! 424: } ! 425: /* ! 426: * Determine feasability/values of rotational layout tables. ! 427: * ! 428: * The size of the rotational layout tables is limited by the ! 429: * size of the superblock, SBSIZE. The amount of space available ! 430: * for tables is calculated as (SBSIZE - sizeof (struct fs)). ! 431: * The size of these tables is inversely proportional to the block ! 432: * size of the file system. The size increases if sectors per track ! 433: * are not powers of two, because more cylinders must be described ! 434: * by the tables before the rotational pattern repeats (fs_cpc). ! 435: */ ! 436: sblock.fs_interleave = interleave; ! 437: sblock.fs_trackskew = trackskew; ! 438: sblock.fs_npsect = nphyssectors; ! 439: sblock.fs_postblformat = FS_DYNAMICPOSTBLFMT; ! 440: sblock.fs_sbsize = fragroundup(&sblock, sizeof(struct fs)); ! 441: if (sblock.fs_ntrak == 1) { ! 442: sblock.fs_cpc = 0; ! 443: goto next; ! 444: } ! 445: postblsize = sblock.fs_nrpos * sblock.fs_cpc * sizeof(short); ! 446: rotblsize = sblock.fs_cpc * sblock.fs_spc / NSPB(&sblock); ! 447: totalsbsize = sizeof(struct fs) + rotblsize; ! 448: if (sblock.fs_nrpos == 8 && sblock.fs_cpc <= 16) { ! 449: /* use old static table space */ ! 450: sblock.fs_postbloff = (char *)(&sblock.fs_opostbl[0][0]) - ! 451: (char *)(&sblock.fs_link); ! 452: sblock.fs_rotbloff = &sblock.fs_space[0] - ! 453: (u_char *)(&sblock.fs_link); ! 454: } else { ! 455: /* use dynamic table space */ ! 456: sblock.fs_postbloff = &sblock.fs_space[0] - ! 457: (u_char *)(&sblock.fs_link); ! 458: sblock.fs_rotbloff = sblock.fs_postbloff + postblsize; ! 459: totalsbsize += postblsize; ! 460: } ! 461: if (totalsbsize > SBSIZE || ! 462: sblock.fs_nsect > (1 << NBBY) * NSPB(&sblock)) { ! 463: printf("%s %s %d %s %d.%s", ! 464: "Warning: insufficient space in super block for\n", ! 465: "rotational layout tables with nsect", sblock.fs_nsect, ! 466: "and ntrak", sblock.fs_ntrak, ! 467: "\nFile system performance may be impaired.\n"); ! 468: sblock.fs_cpc = 0; ! 469: goto next; ! 470: } ! 471: sblock.fs_sbsize = fragroundup(&sblock, totalsbsize); ! 472: /* ! 473: * calculate the available blocks for each rotational position ! 474: */ ! 475: for (cylno = 0; cylno < sblock.fs_cpc; cylno++) ! 476: for (rpos = 0; rpos < sblock.fs_nrpos; rpos++) ! 477: fs_postbl(&sblock, cylno)[rpos] = -1; ! 478: for (i = (rotblsize - 1) * sblock.fs_frag; ! 479: i >= 0; i -= sblock.fs_frag) { ! 480: cylno = cbtocylno(&sblock, i); ! 481: rpos = cbtorpos(&sblock, i); ! 482: blk = fragstoblks(&sblock, i); ! 483: if (fs_postbl(&sblock, cylno)[rpos] == -1) ! 484: fs_rotbl(&sblock)[blk] = 0; ! 485: else ! 486: fs_rotbl(&sblock)[blk] = ! 487: fs_postbl(&sblock, cylno)[rpos] - blk; ! 488: fs_postbl(&sblock, cylno)[rpos] = blk; ! 489: } ! 490: next: ! 491: /* ! 492: * Compute/validate number of cylinder groups. ! 493: */ ! 494: sblock.fs_ncg = sblock.fs_ncyl / sblock.fs_cpg; ! 495: if (sblock.fs_ncyl % sblock.fs_cpg) ! 496: sblock.fs_ncg++; ! 497: sblock.fs_dblkno = sblock.fs_iblkno + sblock.fs_ipg / INOPF(&sblock); ! 498: i = MIN(~sblock.fs_cgmask, sblock.fs_ncg - 1); ! 499: if (cgdmin(&sblock, i) - cgbase(&sblock, i) >= sblock.fs_fpg) { ! 500: printf("inode blocks/cyl group (%d) >= data blocks (%d)\n", ! 501: cgdmin(&sblock, i) - cgbase(&sblock, i) / sblock.fs_frag, ! 502: sblock.fs_fpg / sblock.fs_frag); ! 503: printf("number of cylinders per cylinder group (%d) %s.\n", ! 504: sblock.fs_cpg, "must be increased"); ! 505: exit(29); ! 506: } ! 507: j = sblock.fs_ncg - 1; ! 508: if ((i = fssize - j * sblock.fs_fpg) < sblock.fs_fpg && ! 509: cgdmin(&sblock, j) - cgbase(&sblock, j) > i) { ! 510: if (j == 0) { ! 511: printf("Filesystem must have at least %d sectors\n", ! 512: NSPF(&sblock) * ! 513: (cgdmin(&sblock, 0) + 3 * sblock.fs_frag)); ! 514: exit(30); ! 515: } ! 516: printf("Warning: inode blocks/cyl group (%d) >= data blocks (%d) in last\n", ! 517: (cgdmin(&sblock, j) - cgbase(&sblock, j)) / sblock.fs_frag, ! 518: i / sblock.fs_frag); ! 519: printf(" cylinder group. This implies %d sector(s) cannot be allocated.\n", ! 520: i * NSPF(&sblock)); ! 521: sblock.fs_ncg--; ! 522: sblock.fs_ncyl -= sblock.fs_ncyl % sblock.fs_cpg; ! 523: sblock.fs_size = fssize = sblock.fs_ncyl * sblock.fs_spc / ! 524: NSPF(&sblock); ! 525: warn = 0; ! 526: } ! 527: if (warn && !mfs) { ! 528: printf("Warning: %d sector(s) in last cylinder unallocated\n", ! 529: sblock.fs_spc - ! 530: (fssize * NSPF(&sblock) - (sblock.fs_ncyl - 1) ! 531: * sblock.fs_spc)); ! 532: } ! 533: /* ! 534: * fill in remaining fields of the super block ! 535: */ ! 536: sblock.fs_csaddr = cgdmin(&sblock, 0); ! 537: sblock.fs_cssize = ! 538: fragroundup(&sblock, sblock.fs_ncg * sizeof(struct csum)); ! 539: i = sblock.fs_bsize / sizeof(struct csum); ! 540: sblock.fs_csmask = ~(i - 1); ! 541: for (sblock.fs_csshift = 0; i > 1; i >>= 1) ! 542: sblock.fs_csshift++; ! 543: fscs = (struct csum *)calloc(1, sblock.fs_cssize); ! 544: sblock.fs_magic = FS_MAGIC; ! 545: sblock.fs_rotdelay = rotdelay; ! 546: sblock.fs_minfree = minfree; ! 547: sblock.fs_maxcontig = maxcontig; ! 548: sblock.fs_headswitch = headswitch; ! 549: sblock.fs_trkseek = trackseek; ! 550: sblock.fs_maxbpg = maxbpg; ! 551: sblock.fs_rps = rpm / 60; ! 552: sblock.fs_optim = opt; ! 553: sblock.fs_cgrotor = 0; ! 554: sblock.fs_cstotal.cs_ndir = 0; ! 555: sblock.fs_cstotal.cs_nbfree = 0; ! 556: sblock.fs_cstotal.cs_nifree = 0; ! 557: sblock.fs_cstotal.cs_nffree = 0; ! 558: sblock.fs_fmod = 0; ! 559: sblock.fs_ronly = 0; ! 560: /* ! 561: * Dump out summary information about file system. ! 562: */ ! 563: if (!mfs) { ! 564: printf("%s:\t%d sectors in %d %s of %d tracks, %d sectors\n", ! 565: fsys, sblock.fs_size * NSPF(&sblock), sblock.fs_ncyl, ! 566: "cylinders", sblock.fs_ntrak, sblock.fs_nsect); ! 567: printf("\t%.1fMB in %d cyl groups (%d c/g, %.2fMB/g, %d i/g)\n", ! 568: (float)sblock.fs_size * sblock.fs_fsize * 1e-6, ! 569: sblock.fs_ncg, sblock.fs_cpg, ! 570: (float)sblock.fs_fpg * sblock.fs_fsize * 1e-6, ! 571: sblock.fs_ipg); ! 572: } ! 573: /* ! 574: * Now build the cylinders group blocks and ! 575: * then print out indices of cylinder groups. ! 576: */ ! 577: if (!mfs) ! 578: printf("super-block backups (for fsck -b #) at:"); ! 579: for (cylno = 0; cylno < sblock.fs_ncg; cylno++) { ! 580: initcg(cylno); ! 581: if (mfs) ! 582: continue; ! 583: if (cylno % 9 == 0) ! 584: printf("\n"); ! 585: printf(" %d,", fsbtodb(&sblock, cgsblock(&sblock, cylno))); ! 586: } ! 587: if (!mfs) ! 588: printf("\n"); ! 589: if (Nflag && !mfs) ! 590: exit(0); ! 591: /* ! 592: * Now construct the initial file system, ! 593: * then write out the super-block. ! 594: */ ! 595: fsinit(); ! 596: sblock.fs_time = utime; ! 597: wtfs(SBOFF / sectorsize, sbsize, (char *)&sblock); ! 598: for (i = 0; i < sblock.fs_cssize; i += sblock.fs_bsize) ! 599: wtfs(fsbtodb(&sblock, sblock.fs_csaddr + numfrags(&sblock, i)), ! 600: sblock.fs_cssize - i < sblock.fs_bsize ? ! 601: sblock.fs_cssize - i : sblock.fs_bsize, ! 602: ((char *)fscs) + i); ! 603: /* ! 604: * Write out the duplicate super blocks ! 605: */ ! 606: for (cylno = 0; cylno < sblock.fs_ncg; cylno++) ! 607: wtfs(fsbtodb(&sblock, cgsblock(&sblock, cylno)), ! 608: sbsize, (char *)&sblock); ! 609: /* ! 610: * Update information about this partion in pack ! 611: * label, to that it may be updated on disk. ! 612: */ ! 613: pp->p_fstype = FS_BSDFFS; ! 614: pp->p_fsize = sblock.fs_fsize; ! 615: pp->p_frag = sblock.fs_frag; ! 616: pp->p_cpg = sblock.fs_cpg; ! 617: /* ! 618: * Notify parent process of success. ! 619: * Dissociate from session and tty. ! 620: */ ! 621: if (mfs) { ! 622: kill(ppid, SIGUSR1); ! 623: (void) setsid(); ! 624: (void) close(0); ! 625: (void) close(1); ! 626: (void) close(2); ! 627: (void) chdir("/"); ! 628: } ! 629: } ! 630: ! 631: /* ! 632: * Initialize a cylinder group. ! 633: */ ! 634: initcg(cylno) ! 635: int cylno; ! 636: { ! 637: daddr_t cbase, d, dlower, dupper, dmax; ! 638: long i, j, s; ! 639: register struct csum *cs; ! 640: ! 641: /* ! 642: * Determine block bounds for cylinder group. ! 643: * Allow space for super block summary information in first ! 644: * cylinder group. ! 645: */ ! 646: cbase = cgbase(&sblock, cylno); ! 647: dmax = cbase + sblock.fs_fpg; ! 648: if (dmax > sblock.fs_size) ! 649: dmax = sblock.fs_size; ! 650: dlower = cgsblock(&sblock, cylno) - cbase; ! 651: dupper = cgdmin(&sblock, cylno) - cbase; ! 652: if (cylno == 0) ! 653: dupper += howmany(sblock.fs_cssize, sblock.fs_fsize); ! 654: cs = fscs + cylno; ! 655: acg.cg_time = utime; ! 656: acg.cg_magic = CG_MAGIC; ! 657: acg.cg_cgx = cylno; ! 658: if (cylno == sblock.fs_ncg - 1) ! 659: acg.cg_ncyl = sblock.fs_ncyl % sblock.fs_cpg; ! 660: else ! 661: acg.cg_ncyl = sblock.fs_cpg; ! 662: acg.cg_niblk = sblock.fs_ipg; ! 663: acg.cg_ndblk = dmax - cbase; ! 664: acg.cg_cs.cs_ndir = 0; ! 665: acg.cg_cs.cs_nffree = 0; ! 666: acg.cg_cs.cs_nbfree = 0; ! 667: acg.cg_cs.cs_nifree = 0; ! 668: acg.cg_rotor = 0; ! 669: acg.cg_frotor = 0; ! 670: acg.cg_irotor = 0; ! 671: acg.cg_btotoff = &acg.cg_space[0] - (u_char *)(&acg.cg_link); ! 672: acg.cg_boff = acg.cg_btotoff + sblock.fs_cpg * sizeof(long); ! 673: acg.cg_iusedoff = acg.cg_boff + ! 674: sblock.fs_cpg * sblock.fs_nrpos * sizeof(short); ! 675: acg.cg_freeoff = acg.cg_iusedoff + howmany(sblock.fs_ipg, NBBY); ! 676: acg.cg_nextfreeoff = acg.cg_freeoff + ! 677: howmany(sblock.fs_cpg * sblock.fs_spc / NSPF(&sblock), NBBY); ! 678: for (i = 0; i < sblock.fs_frag; i++) { ! 679: acg.cg_frsum[i] = 0; ! 680: } ! 681: bzero((caddr_t)cg_inosused(&acg), acg.cg_freeoff - acg.cg_iusedoff); ! 682: acg.cg_cs.cs_nifree += sblock.fs_ipg; ! 683: if (cylno == 0) ! 684: for (i = 0; i < ROOTINO; i++) { ! 685: setbit(cg_inosused(&acg), i); ! 686: acg.cg_cs.cs_nifree--; ! 687: } ! 688: for (i = 0; i < sblock.fs_ipg / INOPF(&sblock); i += sblock.fs_frag) ! 689: wtfs(fsbtodb(&sblock, cgimin(&sblock, cylno) + i), ! 690: sblock.fs_bsize, (char *)zino); ! 691: bzero((caddr_t)cg_blktot(&acg), acg.cg_boff - acg.cg_btotoff); ! 692: bzero((caddr_t)cg_blks(&sblock, &acg, 0), ! 693: acg.cg_iusedoff - acg.cg_boff); ! 694: bzero((caddr_t)cg_blksfree(&acg), acg.cg_nextfreeoff - acg.cg_freeoff); ! 695: if (cylno > 0) { ! 696: /* ! 697: * In cylno 0, beginning space is reserved ! 698: * for boot and super blocks. ! 699: */ ! 700: for (d = 0; d < dlower; d += sblock.fs_frag) { ! 701: setblock(&sblock, cg_blksfree(&acg), d/sblock.fs_frag); ! 702: acg.cg_cs.cs_nbfree++; ! 703: cg_blktot(&acg)[cbtocylno(&sblock, d)]++; ! 704: cg_blks(&sblock, &acg, cbtocylno(&sblock, d)) ! 705: [cbtorpos(&sblock, d)]++; ! 706: } ! 707: sblock.fs_dsize += dlower; ! 708: } ! 709: sblock.fs_dsize += acg.cg_ndblk - dupper; ! 710: if (i = dupper % sblock.fs_frag) { ! 711: acg.cg_frsum[sblock.fs_frag - i]++; ! 712: for (d = dupper + sblock.fs_frag - i; dupper < d; dupper++) { ! 713: setbit(cg_blksfree(&acg), dupper); ! 714: acg.cg_cs.cs_nffree++; ! 715: } ! 716: } ! 717: for (d = dupper; d + sblock.fs_frag <= dmax - cbase; ) { ! 718: setblock(&sblock, cg_blksfree(&acg), d / sblock.fs_frag); ! 719: acg.cg_cs.cs_nbfree++; ! 720: cg_blktot(&acg)[cbtocylno(&sblock, d)]++; ! 721: cg_blks(&sblock, &acg, cbtocylno(&sblock, d)) ! 722: [cbtorpos(&sblock, d)]++; ! 723: d += sblock.fs_frag; ! 724: } ! 725: if (d < dmax - cbase) { ! 726: acg.cg_frsum[dmax - cbase - d]++; ! 727: for (; d < dmax - cbase; d++) { ! 728: setbit(cg_blksfree(&acg), d); ! 729: acg.cg_cs.cs_nffree++; ! 730: } ! 731: } ! 732: sblock.fs_cstotal.cs_ndir += acg.cg_cs.cs_ndir; ! 733: sblock.fs_cstotal.cs_nffree += acg.cg_cs.cs_nffree; ! 734: sblock.fs_cstotal.cs_nbfree += acg.cg_cs.cs_nbfree; ! 735: sblock.fs_cstotal.cs_nifree += acg.cg_cs.cs_nifree; ! 736: *cs = acg.cg_cs; ! 737: wtfs(fsbtodb(&sblock, cgtod(&sblock, cylno)), ! 738: sblock.fs_bsize, (char *)&acg); ! 739: } ! 740: ! 741: /* ! 742: * initialize the file system ! 743: */ ! 744: struct dinode node; ! 745: ! 746: #ifdef LOSTDIR ! 747: #define PREDEFDIR 3 ! 748: #else ! 749: #define PREDEFDIR 2 ! 750: #endif ! 751: ! 752: struct direct root_dir[] = { ! 753: { ROOTINO, sizeof(struct direct), 1, "." }, ! 754: { ROOTINO, sizeof(struct direct), 2, ".." }, ! 755: #ifdef LOSTDIR ! 756: { LOSTFOUNDINO, sizeof(struct direct), 10, "lost+found" }, ! 757: #endif ! 758: }; ! 759: #ifdef LOSTDIR ! 760: struct direct lost_found_dir[] = { ! 761: { LOSTFOUNDINO, sizeof(struct direct), 1, "." }, ! 762: { ROOTINO, sizeof(struct direct), 2, ".." }, ! 763: { 0, DIRBLKSIZ, 0, 0 }, ! 764: }; ! 765: #endif ! 766: char buf[MAXBSIZE]; ! 767: ! 768: fsinit() ! 769: { ! 770: int i; ! 771: ! 772: /* ! 773: * initialize the node ! 774: */ ! 775: node.di_atime = utime; ! 776: node.di_mtime = utime; ! 777: node.di_ctime = utime; ! 778: #ifdef LOSTDIR ! 779: /* ! 780: * create the lost+found directory ! 781: */ ! 782: (void)makedir(lost_found_dir, 2); ! 783: for (i = DIRBLKSIZ; i < sblock.fs_bsize; i += DIRBLKSIZ) ! 784: bcopy(&lost_found_dir[2], &buf[i], DIRSIZ(&lost_found_dir[2])); ! 785: node.di_mode = IFDIR | UMASK; ! 786: node.di_nlink = 2; ! 787: node.di_size = sblock.fs_bsize; ! 788: node.di_db[0] = alloc(node.di_size, node.di_mode); ! 789: node.di_blocks = btodb(fragroundup(&sblock, node.di_size)); ! 790: wtfs(fsbtodb(&sblock, node.di_db[0]), node.di_size, buf); ! 791: iput(&node, LOSTFOUNDINO); ! 792: #endif ! 793: /* ! 794: * create the root directory ! 795: */ ! 796: if (mfs) ! 797: node.di_mode = IFDIR | 01777; ! 798: else ! 799: node.di_mode = IFDIR | UMASK; ! 800: node.di_nlink = PREDEFDIR; ! 801: node.di_size = makedir(root_dir, PREDEFDIR); ! 802: node.di_db[0] = alloc(sblock.fs_fsize, node.di_mode); ! 803: node.di_blocks = btodb(fragroundup(&sblock, node.di_size)); ! 804: wtfs(fsbtodb(&sblock, node.di_db[0]), sblock.fs_fsize, buf); ! 805: iput(&node, ROOTINO); ! 806: } ! 807: ! 808: /* ! 809: * construct a set of directory entries in "buf". ! 810: * return size of directory. ! 811: */ ! 812: makedir(protodir, entries) ! 813: register struct direct *protodir; ! 814: int entries; ! 815: { ! 816: char *cp; ! 817: int i, spcleft; ! 818: ! 819: spcleft = DIRBLKSIZ; ! 820: for (cp = buf, i = 0; i < entries - 1; i++) { ! 821: protodir[i].d_reclen = DIRSIZ(&protodir[i]); ! 822: bcopy(&protodir[i], cp, protodir[i].d_reclen); ! 823: cp += protodir[i].d_reclen; ! 824: spcleft -= protodir[i].d_reclen; ! 825: } ! 826: protodir[i].d_reclen = spcleft; ! 827: bcopy(&protodir[i], cp, DIRSIZ(&protodir[i])); ! 828: return (DIRBLKSIZ); ! 829: } ! 830: ! 831: /* ! 832: * allocate a block or frag ! 833: */ ! 834: daddr_t ! 835: alloc(size, mode) ! 836: int size; ! 837: int mode; ! 838: { ! 839: int i, frag; ! 840: daddr_t d; ! 841: ! 842: rdfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, ! 843: (char *)&acg); ! 844: if (acg.cg_magic != CG_MAGIC) { ! 845: printf("cg 0: bad magic number\n"); ! 846: return (0); ! 847: } ! 848: if (acg.cg_cs.cs_nbfree == 0) { ! 849: printf("first cylinder group ran out of space\n"); ! 850: return (0); ! 851: } ! 852: for (d = 0; d < acg.cg_ndblk; d += sblock.fs_frag) ! 853: if (isblock(&sblock, cg_blksfree(&acg), d / sblock.fs_frag)) ! 854: goto goth; ! 855: printf("internal error: can't find block in cyl 0\n"); ! 856: return (0); ! 857: goth: ! 858: clrblock(&sblock, cg_blksfree(&acg), d / sblock.fs_frag); ! 859: acg.cg_cs.cs_nbfree--; ! 860: sblock.fs_cstotal.cs_nbfree--; ! 861: fscs[0].cs_nbfree--; ! 862: if (mode & IFDIR) { ! 863: acg.cg_cs.cs_ndir++; ! 864: sblock.fs_cstotal.cs_ndir++; ! 865: fscs[0].cs_ndir++; ! 866: } ! 867: cg_blktot(&acg)[cbtocylno(&sblock, d)]--; ! 868: cg_blks(&sblock, &acg, cbtocylno(&sblock, d))[cbtorpos(&sblock, d)]--; ! 869: if (size != sblock.fs_bsize) { ! 870: frag = howmany(size, sblock.fs_fsize); ! 871: fscs[0].cs_nffree += sblock.fs_frag - frag; ! 872: sblock.fs_cstotal.cs_nffree += sblock.fs_frag - frag; ! 873: acg.cg_cs.cs_nffree += sblock.fs_frag - frag; ! 874: acg.cg_frsum[sblock.fs_frag - frag]++; ! 875: for (i = frag; i < sblock.fs_frag; i++) ! 876: setbit(cg_blksfree(&acg), d + i); ! 877: } ! 878: wtfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, ! 879: (char *)&acg); ! 880: return (d); ! 881: } ! 882: ! 883: /* ! 884: * Allocate an inode on the disk ! 885: */ ! 886: iput(ip, ino) ! 887: register struct dinode *ip; ! 888: register ino_t ino; ! 889: { ! 890: struct dinode buf[MAXINOPB]; ! 891: daddr_t d; ! 892: int c; ! 893: ! 894: c = itog(&sblock, ino); ! 895: rdfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, ! 896: (char *)&acg); ! 897: if (acg.cg_magic != CG_MAGIC) { ! 898: printf("cg 0: bad magic number\n"); ! 899: exit(31); ! 900: } ! 901: acg.cg_cs.cs_nifree--; ! 902: setbit(cg_inosused(&acg), ino); ! 903: wtfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, ! 904: (char *)&acg); ! 905: sblock.fs_cstotal.cs_nifree--; ! 906: fscs[0].cs_nifree--; ! 907: if (ino >= sblock.fs_ipg * sblock.fs_ncg) { ! 908: printf("fsinit: inode value out of range (%d).\n", ino); ! 909: exit(32); ! 910: } ! 911: d = fsbtodb(&sblock, itod(&sblock, ino)); ! 912: rdfs(d, sblock.fs_bsize, buf); ! 913: buf[itoo(&sblock, ino)] = *ip; ! 914: wtfs(d, sblock.fs_bsize, buf); ! 915: } ! 916: ! 917: /* ! 918: * Notify parent process that the filesystem has created itself successfully. ! 919: */ ! 920: started() ! 921: { ! 922: ! 923: exit(0); ! 924: } ! 925: ! 926: /* ! 927: * Replace libc function with one suited to our needs. ! 928: */ ! 929: caddr_t ! 930: malloc(size) ! 931: register u_long size; ! 932: { ! 933: u_long base, i; ! 934: static u_long pgsz; ! 935: struct rlimit rlp; ! 936: ! 937: if (pgsz == 0) { ! 938: base = sbrk(0); ! 939: pgsz = getpagesize() - 1; ! 940: i = (base + pgsz) &~ pgsz; ! 941: base = sbrk(i - base); ! 942: if (getrlimit(RLIMIT_DATA, &rlp) < 0) ! 943: perror("getrlimit"); ! 944: rlp.rlim_cur = rlp.rlim_max; ! 945: if (setrlimit(RLIMIT_DATA, &rlp) < 0) ! 946: perror("setrlimit"); ! 947: memleft = rlp.rlim_max - base; ! 948: } ! 949: size = (size + pgsz) &~ pgsz; ! 950: if (size > memleft) ! 951: size = memleft; ! 952: memleft -= size; ! 953: if (size == 0) ! 954: return (0); ! 955: return ((caddr_t)sbrk(size)); ! 956: } ! 957: ! 958: /* ! 959: * Replace libc function with one suited to our needs. ! 960: */ ! 961: caddr_t ! 962: realloc(ptr, size) ! 963: char *ptr; ! 964: u_long size; ! 965: { ! 966: ! 967: /* always fail for now */ ! 968: return ((caddr_t)0); ! 969: } ! 970: ! 971: /* ! 972: * Replace libc function with one suited to our needs. ! 973: */ ! 974: char * ! 975: calloc(size, numelm) ! 976: u_long size, numelm; ! 977: { ! 978: caddr_t base; ! 979: ! 980: size *= numelm; ! 981: base = malloc(size); ! 982: bzero(base, size); ! 983: return (base); ! 984: } ! 985: ! 986: /* ! 987: * Replace libc function with one suited to our needs. ! 988: */ ! 989: free(ptr) ! 990: char *ptr; ! 991: { ! 992: ! 993: /* do not worry about it for now */ ! 994: } ! 995: ! 996: /* ! 997: * read a block from the file system ! 998: */ ! 999: rdfs(bno, size, bf) ! 1000: daddr_t bno; ! 1001: int size; ! 1002: char *bf; ! 1003: { ! 1004: int n; ! 1005: ! 1006: if (mfs) { ! 1007: bcopy(membase + bno * sectorsize, bf, size); ! 1008: return; ! 1009: } ! 1010: if (lseek(fsi, bno * sectorsize, 0) < 0) { ! 1011: printf("seek error: %ld\n", bno); ! 1012: perror("rdfs"); ! 1013: exit(33); ! 1014: } ! 1015: n = read(fsi, bf, size); ! 1016: if(n != size) { ! 1017: printf("read error: %ld\n", bno); ! 1018: perror("rdfs"); ! 1019: exit(34); ! 1020: } ! 1021: } ! 1022: ! 1023: /* ! 1024: * write a block to the file system ! 1025: */ ! 1026: wtfs(bno, size, bf) ! 1027: daddr_t bno; ! 1028: int size; ! 1029: char *bf; ! 1030: { ! 1031: int n; ! 1032: ! 1033: if (mfs) { ! 1034: bcopy(bf, membase + bno * sectorsize, size); ! 1035: return; ! 1036: } ! 1037: if (Nflag) ! 1038: return; ! 1039: if (lseek(fso, bno * sectorsize, 0) < 0) { ! 1040: printf("seek error: %ld\n", bno); ! 1041: perror("wtfs"); ! 1042: exit(35); ! 1043: } ! 1044: n = write(fso, bf, size); ! 1045: if(n != size) { ! 1046: printf("write error: %ld\n", bno); ! 1047: perror("wtfs"); ! 1048: exit(36); ! 1049: } ! 1050: } ! 1051: ! 1052: /* ! 1053: * check if a block is available ! 1054: */ ! 1055: isblock(fs, cp, h) ! 1056: struct fs *fs; ! 1057: unsigned char *cp; ! 1058: int h; ! 1059: { ! 1060: unsigned char mask; ! 1061: ! 1062: switch (fs->fs_frag) { ! 1063: case 8: ! 1064: return (cp[h] == 0xff); ! 1065: case 4: ! 1066: mask = 0x0f << ((h & 0x1) << 2); ! 1067: return ((cp[h >> 1] & mask) == mask); ! 1068: case 2: ! 1069: mask = 0x03 << ((h & 0x3) << 1); ! 1070: return ((cp[h >> 2] & mask) == mask); ! 1071: case 1: ! 1072: mask = 0x01 << (h & 0x7); ! 1073: return ((cp[h >> 3] & mask) == mask); ! 1074: default: ! 1075: #ifdef STANDALONE ! 1076: printf("isblock bad fs_frag %d\n", fs->fs_frag); ! 1077: #else ! 1078: fprintf(stderr, "isblock bad fs_frag %d\n", fs->fs_frag); ! 1079: #endif ! 1080: return (0); ! 1081: } ! 1082: } ! 1083: ! 1084: /* ! 1085: * take a block out of the map ! 1086: */ ! 1087: clrblock(fs, cp, h) ! 1088: struct fs *fs; ! 1089: unsigned char *cp; ! 1090: int h; ! 1091: { ! 1092: switch ((fs)->fs_frag) { ! 1093: case 8: ! 1094: cp[h] = 0; ! 1095: return; ! 1096: case 4: ! 1097: cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); ! 1098: return; ! 1099: case 2: ! 1100: cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); ! 1101: return; ! 1102: case 1: ! 1103: cp[h >> 3] &= ~(0x01 << (h & 0x7)); ! 1104: return; ! 1105: default: ! 1106: #ifdef STANDALONE ! 1107: printf("clrblock bad fs_frag %d\n", fs->fs_frag); ! 1108: #else ! 1109: fprintf(stderr, "clrblock bad fs_frag %d\n", fs->fs_frag); ! 1110: #endif ! 1111: return; ! 1112: } ! 1113: } ! 1114: ! 1115: /* ! 1116: * put a block into the map ! 1117: */ ! 1118: setblock(fs, cp, h) ! 1119: struct fs *fs; ! 1120: unsigned char *cp; ! 1121: int h; ! 1122: { ! 1123: switch (fs->fs_frag) { ! 1124: case 8: ! 1125: cp[h] = 0xff; ! 1126: return; ! 1127: case 4: ! 1128: cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); ! 1129: return; ! 1130: case 2: ! 1131: cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); ! 1132: return; ! 1133: case 1: ! 1134: cp[h >> 3] |= (0x01 << (h & 0x7)); ! 1135: return; ! 1136: default: ! 1137: #ifdef STANDALONE ! 1138: printf("setblock bad fs_frag %d\n", fs->fs_frag); ! 1139: #else ! 1140: fprintf(stderr, "setblock bad fs_frag %d\n", fs->fs_frag); ! 1141: #endif ! 1142: return; ! 1143: } ! 1144: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.