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: }

Defined functions

alloc defined in line 755; used 3 times
clrblock defined in line 921; used 4 times
fsinit defined in line 692; used 1 times
initcg defined in line 561; used 1 times
iput defined in line 807; used 2 times
isblock defined in line 889; used 1 times
main defined in line 133; never used
makedir defined in line 733; used 2 times
rdfs defined in line 841; used 3 times
setblock defined in line 952; used 2 times
wtfs defined in line 864; used 11 times

Defined variables

Nflag defined in line 130; used 4 times
buf defined in line 690; used 8 times
copyright defined in line 8; never used
fscs defined in line 116; used 7 times
fsi defined in line 128; used 6 times
fso defined in line 129; used 6 times
fsys defined in line 126; used 6 times
lost_found_dir defined in line 685; used 3 times
node defined in line 678; used 25 times
root_dir defined in line 680; used 1 times
sccsid defined in line 14; never used
zino defined in line 124; used 1 times

Defined macros

DEFAULTOPT defined in line 60; used 1 times
DEFHZ defined in line 95; used 1 times
DESBLKSIZE defined in line 38; used 1 times
DESCPG defined in line 47; used 1 times
DESFRAGSIZE defined in line 39; used 1 times
DFLNSECT defined in line 28; used 1 times
DFLNTRAK defined in line 29; used 1 times
MAXBLKPG defined in line 83; used 1 times
MAXCONTIG defined in line 76; used 1 times
MAXINOPB defined in line 108; used 1 times
MINFREE defined in line 59; used 3 times
NBPI defined in line 90; used 1 times
POWEROF2 defined in line 109; used 3 times
PREDEFDIR defined in line 679; used 2 times
ROTDELAY defined in line 68; used 1 times
UMASK defined in line 107; used 2 times
acg defined in line 122; used 66 times
sblock defined in line 115; used 401 times
Last modified: 1985-09-12
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2965
Valid CSS Valid XHTML 1.0 Strict