|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1983 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) 1983 Regents of the University of California.\n\ ! 10: All rights reserved.\n"; ! 11: #endif not lint ! 12: ! 13: #ifndef lint ! 14: static char sccsid[] = "@(#)newfs.c 6.15 (Berkeley) 12/7/87"; ! 15: #endif not lint ! 16: ! 17: /* ! 18: * newfs: friendly front end to mkfs ! 19: */ ! 20: #include <sys/param.h> ! 21: #include <sys/stat.h> ! 22: #include <sys/fs.h> ! 23: #include <sys/dir.h> ! 24: #include <sys/ioctl.h> ! 25: #include <sys/disklabel.h> ! 26: #include <sys/file.h> ! 27: ! 28: #include <stdio.h> ! 29: #include <ctype.h> ! 30: ! 31: #define COMPAT /* allow non-labeled disks */ ! 32: ! 33: /* ! 34: * The following two constants set the default block and fragment sizes. ! 35: * Both constants must be a power of 2 and meet the following constraints: ! 36: * MINBSIZE <= DESBLKSIZE <= MAXBSIZE ! 37: * sectorsize <= DESFRAGSIZE <= DESBLKSIZE ! 38: * DESBLKSIZE / DESFRAGSIZE <= 8 ! 39: */ ! 40: #define DFL_FRAGSIZE 1024 ! 41: #define DFL_BLKSIZE 8192 ! 42: ! 43: /* ! 44: * Cylinder groups may have up to MAXCPG cylinders. The actual ! 45: * number used depends upon how much information can be stored ! 46: * on a single cylinder. The default is to used 16 cylinders ! 47: * per group. ! 48: */ ! 49: #define DESCPG 16 /* desired fs_cpg */ ! 50: ! 51: /* ! 52: * MINFREE gives the minimum acceptable percentage of file system ! 53: * blocks which may be free. If the freelist drops below this level ! 54: * only the superuser may continue to allocate blocks. This may ! 55: * be set to 0 if no reserve of free blocks is deemed necessary, ! 56: * however throughput drops by fifty percent if the file system ! 57: * is run at between 90% and 100% full; thus the default value of ! 58: * fs_minfree is 10%. With 10% free space, fragmentation is not a ! 59: * problem, so we choose to optimize for time. ! 60: */ ! 61: #define MINFREE 10 ! 62: #define DEFAULTOPT FS_OPTTIME ! 63: ! 64: /* ! 65: * ROTDELAY gives the minimum number of milliseconds to initiate ! 66: * another disk transfer on the same cylinder. It is used in ! 67: * determining the rotationally optimal layout for disk blocks ! 68: * within a file; the default of fs_rotdelay is 4ms. ! 69: */ ! 70: #define ROTDELAY 4 ! 71: ! 72: /* ! 73: * MAXCONTIG sets the default for the maximum number of blocks ! 74: * that may be allocated sequentially. Since UNIX drivers are ! 75: * not capable of scheduling multi-block transfers, this defaults ! 76: * to 1 (ie no contiguous blocks are allocated). ! 77: */ ! 78: #define MAXCONTIG 1 ! 79: ! 80: /* ! 81: * MAXBLKPG determines the maximum number of data blocks which are ! 82: * placed in a single cylinder group. The default is one indirect ! 83: * block worth of data blocks. ! 84: */ ! 85: #define MAXBLKPG(bsize) ((bsize) / sizeof(daddr_t)) ! 86: ! 87: /* ! 88: * Each file system has a number of inodes statically allocated. ! 89: * We allocate one inode slot per NBPI bytes, expecting this ! 90: * to be far more than we will ever need. ! 91: */ ! 92: #define NBPI 2048 ! 93: ! 94: int Nflag; /* run without writing file system */ ! 95: int fssize; /* file system size */ ! 96: int ntracks; /* # tracks/cylinder */ ! 97: int nsectors; /* # sectors/track */ ! 98: int nphyssectors; /* # sectors/track including spares */ ! 99: int secpercyl; /* sectors per cylinder */ ! 100: int trackspares = -1; /* spare sectors per track */ ! 101: int cylspares = -1; /* spare sectors per cylinder */ ! 102: int sectorsize; /* bytes/sector */ ! 103: #ifdef tahoe ! 104: int realsectorsize; /* bytes/sector in hardware */ ! 105: #endif ! 106: int rpm; /* revolutions/minute of drive */ ! 107: int interleave; /* hardware sector interleave */ ! 108: int trackskew = -1; /* sector 0 skew, per track */ ! 109: int headswitch; /* head switch time, usec */ ! 110: int trackseek; /* track-to-track seek, usec */ ! 111: int fsize = 0; /* fragment size */ ! 112: int bsize = 0; /* block size */ ! 113: int cpg = DESCPG; /* cylinders/cylinder group */ ! 114: int cpgflg; /* cylinders/cylinder group flag was given */ ! 115: int minfree = MINFREE; /* free space threshold */ ! 116: int opt = DEFAULTOPT; /* optimization preference (space or time) */ ! 117: int density = NBPI; /* number of bytes per inode */ ! 118: int maxcontig = MAXCONTIG; /* max contiguous blocks to allocate */ ! 119: int rotdelay = ROTDELAY; /* rotational delay between blocks */ ! 120: int maxbpg; /* maximum blocks per file in a cyl group */ ! 121: int bbsize = BBSIZE; /* boot block size */ ! 122: int sbsize = SBSIZE; /* superblock size */ ! 123: #ifdef COMPAT ! 124: int unlabelled; ! 125: #endif ! 126: ! 127: char device[MAXPATHLEN]; ! 128: ! 129: extern int errno; ! 130: char *index(); ! 131: char *rindex(); ! 132: ! 133: main(argc, argv) ! 134: int argc; ! 135: char *argv[]; ! 136: { ! 137: char *cp, *special; ! 138: register struct partition *pp; ! 139: register struct disklabel *lp; ! 140: struct disklabel *getdisklabel(); ! 141: struct partition oldpartition; ! 142: struct stat st; ! 143: int fsi, fso; ! 144: register int i; ! 145: int status; ! 146: ! 147: argc--, argv++; ! 148: while (argc > 0 && argv[0][0] == '-') { ! 149: for (cp = &argv[0][1]; *cp; cp++) ! 150: switch (*cp) { ! 151: ! 152: case 'N': ! 153: Nflag++; ! 154: break; ! 155: ! 156: case 'S': ! 157: if (argc < 1) ! 158: fatal("-S: missing sector size"); ! 159: argc--, argv++; ! 160: sectorsize = atoi(*argv); ! 161: if (sectorsize <= 0) ! 162: fatal("%s: bad sector size", *argv); ! 163: goto next; ! 164: ! 165: case 'a': ! 166: if (argc < 1) ! 167: fatal("-a: missing max contiguous blocks\n"); ! 168: argc--, argv++; ! 169: maxcontig = atoi(*argv); ! 170: if (maxcontig <= 0) ! 171: fatal("%s: bad max contiguous blocks\n", ! 172: *argv); ! 173: goto next; ! 174: ! 175: case 'b': ! 176: if (argc < 1) ! 177: fatal("-b: missing block size"); ! 178: argc--, argv++; ! 179: bsize = atoi(*argv); ! 180: if (bsize < MINBSIZE) ! 181: fatal("%s: bad block size", *argv); ! 182: goto next; ! 183: ! 184: case 'c': ! 185: if (argc < 1) ! 186: fatal("-c: missing cylinders/group"); ! 187: argc--, argv++; ! 188: cpg = atoi(*argv); ! 189: if (cpg <= 0) ! 190: fatal("%s: bad cylinders/group", *argv); ! 191: cpgflg++; ! 192: goto next; ! 193: ! 194: case 'd': ! 195: if (argc < 1) ! 196: fatal("-d: missing rotational delay\n"); ! 197: argc--, argv++; ! 198: rotdelay = atoi(*argv); ! 199: if (rotdelay < 0) ! 200: fatal("%s: bad rotational delay\n", ! 201: *argv); ! 202: goto next; ! 203: ! 204: case 'e': ! 205: if (argc < 1) ! 206: fatal("-e: missing blocks pre file in a cyl group\n"); ! 207: argc--, argv++; ! 208: maxbpg = atoi(*argv); ! 209: if (maxbpg <= 0) ! 210: fatal("%s: bad blocks per file in a cyl group\n", ! 211: *argv); ! 212: goto next; ! 213: ! 214: case 'f': ! 215: if (argc < 1) ! 216: fatal("-f: missing frag size"); ! 217: argc--, argv++; ! 218: fsize = atoi(*argv); ! 219: if (fsize <= 0) ! 220: fatal("%s: bad frag size", *argv); ! 221: goto next; ! 222: ! 223: case 'i': ! 224: if (argc < 1) ! 225: fatal("-i: missing bytes per inode\n"); ! 226: argc--, argv++; ! 227: density = atoi(*argv); ! 228: if (density <= 0) ! 229: fatal("%s: bad bytes per inode\n", ! 230: *argv); ! 231: goto next; ! 232: ! 233: case 'k': ! 234: if (argc < 1) ! 235: fatal("-k: track skew"); ! 236: argc--, argv++; ! 237: trackskew = atoi(*argv); ! 238: if (trackskew < 0) ! 239: fatal("%s: bad track skew", *argv); ! 240: goto next; ! 241: ! 242: case 'l': ! 243: if (argc < 1) ! 244: fatal("-l: interleave"); ! 245: argc--, argv++; ! 246: interleave = atoi(*argv); ! 247: if (interleave <= 0) ! 248: fatal("%s: bad interleave", *argv); ! 249: goto next; ! 250: ! 251: case 'm': ! 252: if (argc < 1) ! 253: fatal("-m: missing free space %%\n"); ! 254: argc--, argv++; ! 255: minfree = atoi(*argv); ! 256: if (minfree < 0 || minfree > 99) ! 257: fatal("%s: bad free space %%\n", ! 258: *argv); ! 259: goto next; ! 260: ! 261: case 'o': ! 262: if (argc < 1) ! 263: fatal("-o: missing optimization preference"); ! 264: argc--, argv++; ! 265: if (strcmp(*argv, "space") == 0) ! 266: opt = FS_OPTSPACE; ! 267: else if (strcmp(*argv, "time") == 0) ! 268: opt = FS_OPTTIME; ! 269: else ! 270: fatal("%s: bad optimization preference %s", ! 271: *argv, ! 272: "(options are `space' or `time')"); ! 273: goto next; ! 274: ! 275: case 'p': ! 276: if (argc < 1) ! 277: fatal("-p: spare sectors per track"); ! 278: argc--, argv++; ! 279: trackspares = atoi(*argv); ! 280: if (trackspares < 0) ! 281: fatal("%s: bad spare sectors per track", *argv); ! 282: goto next; ! 283: ! 284: case 'r': ! 285: if (argc < 1) ! 286: fatal("-r: missing revs/minute\n"); ! 287: argc--, argv++; ! 288: rpm = atoi(*argv); ! 289: if (rpm <= 0) ! 290: fatal("%s: bad revs/minute\n", *argv); ! 291: goto next; ! 292: ! 293: case 's': ! 294: if (argc < 1) ! 295: fatal("-s: missing file system size"); ! 296: argc--, argv++; ! 297: fssize = atoi(*argv); ! 298: if (fssize <= 0) ! 299: fatal("%s: bad file system size", ! 300: *argv); ! 301: goto next; ! 302: ! 303: case 't': ! 304: if (argc < 1) ! 305: fatal("-t: missing track total"); ! 306: argc--, argv++; ! 307: ntracks = atoi(*argv); ! 308: if (ntracks <= 0) ! 309: fatal("%s: bad total tracks", *argv); ! 310: goto next; ! 311: ! 312: case 'u': ! 313: if (argc < 1) ! 314: fatal("-u: missing sectors/track"); ! 315: argc--, argv++; ! 316: nsectors = atoi(*argv); ! 317: if (nsectors <= 0) ! 318: fatal("%s: bad sectors/track", *argv); ! 319: goto next; ! 320: ! 321: case 'x': ! 322: if (argc < 1) ! 323: fatal("-x: spare sectors per cylinder"); ! 324: argc--, argv++; ! 325: cylspares = atoi(*argv); ! 326: if (cylspares < 0) ! 327: fatal("%s: bad spare sectors per cylinder", *argv); ! 328: goto next; ! 329: ! 330: default: ! 331: fatal("-%c: unknown flag", *cp); ! 332: } ! 333: next: ! 334: argc--, argv++; ! 335: } ! 336: if (argc < 1) { ! 337: #ifdef COMPAT ! 338: fprintf(stderr, ! 339: "usage: newfs [ fsoptions ] special-device [device-type]\n"); ! 340: #else ! 341: fprintf(stderr, "usage: newfs [ fsoptions ] special-device\n"); ! 342: #endif ! 343: fprintf(stderr, "where fsoptions are:\n"); ! 344: fprintf(stderr, "\t-N do not create file system, %s\n", ! 345: "just print out parameters"); ! 346: fprintf(stderr, "\t-b block size\n"); ! 347: fprintf(stderr, "\t-f frag size\n"); ! 348: fprintf(stderr, "\t-m minimum free space %%\n"); ! 349: fprintf(stderr, "\t-o optimization preference %s\n", ! 350: "(`space' or `time')"); ! 351: fprintf(stderr, "\t-a maximum contiguous blocks\n"); ! 352: fprintf(stderr, "\t-d rotational delay between %s\n", ! 353: "contiguous blocks"); ! 354: fprintf(stderr, "\t-e maximum blocks per file in a %s\n", ! 355: "cylinder group"); ! 356: fprintf(stderr, "\t-i number of bytes per inode\n"); ! 357: fprintf(stderr, "\t-c cylinders/group\n"); ! 358: fprintf(stderr, "\t-s file system size (sectors)\n"); ! 359: fprintf(stderr, "\t-r revolutions/minute\n"); ! 360: fprintf(stderr, "\t-S sector size\n"); ! 361: fprintf(stderr, "\t-u sectors/track\n"); ! 362: fprintf(stderr, "\t-t tracks/cylinder\n"); ! 363: fprintf(stderr, "\t-p spare sectors per track\n"); ! 364: fprintf(stderr, "\t-x spare sectors per cylinder\n"); ! 365: fprintf(stderr, "\t-l hardware sector interleave\n"); ! 366: fprintf(stderr, "\t-k sector 0 skew, per track\n"); ! 367: exit(1); ! 368: } ! 369: special = argv[0]; ! 370: cp = rindex(special, '/'); ! 371: if (cp != 0) ! 372: special = cp + 1; ! 373: if (*special == 'r' && special[1] != 'a' && special[1] != 'b') ! 374: special++; ! 375: (void)sprintf(device, "/dev/r%s", special); ! 376: special = device; ! 377: if (!Nflag) { ! 378: fso = open(special, O_WRONLY); ! 379: if (fso < 0) { ! 380: perror(special); ! 381: exit(1); ! 382: } ! 383: } else ! 384: fso = -1; ! 385: fsi = open(special, O_RDONLY); ! 386: if (fsi < 0) { ! 387: perror(special); ! 388: exit(1); ! 389: } ! 390: if (fstat(fsi, &st) < 0) { ! 391: fprintf(stderr, "newfs: "); perror(special); ! 392: exit(2); ! 393: } ! 394: if ((st.st_mode & S_IFMT) != S_IFCHR) ! 395: fatal("%s: not a character device", special); ! 396: cp = index(argv[0], '\0') - 1; ! 397: if (cp == 0 || (*cp < 'a' || *cp > 'h') && !isdigit(*cp)) ! 398: fatal("%s: can't figure out file system partition", argv[0]); ! 399: #ifdef COMPAT ! 400: lp = getdisklabel(special, fsi, argv[1]); ! 401: #else ! 402: lp = getdisklabel(special, fsi); ! 403: #endif ! 404: if (isdigit(*cp)) ! 405: pp = &lp->d_partitions[0]; ! 406: else ! 407: pp = &lp->d_partitions[*cp - 'a']; ! 408: if (pp->p_size == 0) ! 409: fatal("%s: `%c' partition is unavailable", argv[0], *cp); ! 410: if (fssize == 0) ! 411: fssize = pp->p_size; ! 412: if (fssize > pp->p_size) ! 413: fatal("%s: maximum file system size on the `%c' partition is %d", ! 414: argv[0], *cp, pp->p_size); ! 415: if (rpm == 0) { ! 416: rpm = lp->d_rpm; ! 417: if (rpm <= 0) ! 418: rpm = 3600; ! 419: } ! 420: if (ntracks == 0) { ! 421: ntracks = lp->d_ntracks; ! 422: if (ntracks <= 0) ! 423: fatal("%s: no default #tracks", argv[0]); ! 424: } ! 425: if (nsectors == 0) { ! 426: nsectors = lp->d_nsectors; ! 427: if (nsectors <= 0) ! 428: fatal("%s: no default #sectors/track", argv[0]); ! 429: } ! 430: if (sectorsize == 0) { ! 431: sectorsize = lp->d_secsize; ! 432: if (sectorsize <= 0) ! 433: fatal("%s: no default sector size", argv[0]); ! 434: } ! 435: if (trackskew == -1) { ! 436: trackskew = lp->d_trackskew; ! 437: if (trackskew < 0) ! 438: trackskew = 0; ! 439: } ! 440: if (interleave == 0) { ! 441: interleave = lp->d_interleave; ! 442: if (interleave <= 0) ! 443: interleave = 1; ! 444: } ! 445: if (fsize == 0) { ! 446: fsize = pp->p_fsize; ! 447: if (fsize <= 0) ! 448: fsize = MAX(DFL_FRAGSIZE, lp->d_secsize); ! 449: } ! 450: if (bsize == 0) { ! 451: bsize = pp->p_frag * pp->p_fsize; ! 452: if (bsize <= 0) ! 453: bsize = MIN(DFL_BLKSIZE, 8 * fsize); ! 454: } ! 455: if (minfree < 10 && opt != FS_OPTSPACE) { ! 456: fprintf(stderr, "Warning: changing optimization to space "); ! 457: fprintf(stderr, "because minfree is less than 10%%\n"); ! 458: opt = FS_OPTSPACE; ! 459: } ! 460: if (trackspares == -1) { ! 461: trackspares = lp->d_sparespertrack; ! 462: if (trackspares < 0) ! 463: trackspares = 0; ! 464: } ! 465: nphyssectors = nsectors + trackspares; ! 466: if (cylspares == -1) { ! 467: cylspares = lp->d_sparespercyl; ! 468: if (cylspares < 0) ! 469: cylspares = 0; ! 470: } ! 471: secpercyl = nsectors * ntracks - cylspares; ! 472: if (secpercyl != lp->d_secpercyl) ! 473: fprintf(stderr, "%s (%d) %s (%d)\n", ! 474: "Warning: calculated sectors per cylinder", secpercyl, ! 475: "disagrees with disk label", lp->d_secpercyl); ! 476: if (maxbpg == 0) ! 477: maxbpg = MAXBLKPG(bsize); ! 478: headswitch = lp->d_headswitch; ! 479: trackseek = lp->d_trkseek; ! 480: bbsize = lp->d_bbsize; ! 481: sbsize = lp->d_sbsize; ! 482: oldpartition = *pp; ! 483: #ifdef tahoe ! 484: realsectorsize = sectorsize; ! 485: if (sectorsize != DEV_BSIZE) { /* XXX */ ! 486: int secperblk = DEV_BSIZE / sectorsize; ! 487: ! 488: sectorsize = DEV_BSIZE; ! 489: nsectors /= secperblk; ! 490: nphyssectors /= secperblk; ! 491: secpercyl /= secperblk; ! 492: fssize /= secperblk; ! 493: pp->p_size /= secperblk; ! 494: } ! 495: #endif ! 496: mkfs(pp, special, fsi, fso); ! 497: #ifdef tahoe ! 498: if (realsectorsize != DEV_BSIZE) ! 499: pp->p_size *= DEV_BSIZE / realsectorsize; ! 500: #endif ! 501: if (!Nflag && bcmp(pp, &oldpartition, sizeof(oldpartition))) ! 502: rewritelabel(special, fso, lp); ! 503: exit(0); ! 504: } ! 505: ! 506: #ifdef COMPAT ! 507: struct disklabel * ! 508: getdisklabel(s, fd, type) ! 509: char *s, *type; ! 510: int fd; ! 511: { ! 512: static struct disklabel lab; ! 513: struct disklabel *getdiskbyname(); ! 514: ! 515: if (ioctl(fd, DIOCGDINFO, (char *)&lab) < 0) { ! 516: if (type == NULL) { ! 517: perror("ioctl (GDINFO)"); ! 518: fatal( ! 519: "%s: can't read disk label; disk type must be specified", s); ! 520: } ! 521: unlabelled++; ! 522: return (getdiskbyname(type)); ! 523: } ! 524: return (&lab); ! 525: } ! 526: #else ! 527: struct disklabel * ! 528: getdisklabel(s, fd) ! 529: char *s; ! 530: int fd; ! 531: { ! 532: static struct disklabel lab; ! 533: ! 534: if (ioctl(fd, DIOCGDINFO, (char *)&lab) < 0) { ! 535: perror("ioctl (GDINFO)"); ! 536: fatal("%s: can't read disk label", s); ! 537: } ! 538: return (&lab); ! 539: } ! 540: #endif ! 541: ! 542: rewritelabel(s, fd, lp) ! 543: char *s; ! 544: int fd; ! 545: register struct disklabel *lp; ! 546: { ! 547: ! 548: #ifdef COMPAT ! 549: if (unlabelled) ! 550: return; ! 551: #endif ! 552: lp->d_checksum = 0; ! 553: lp->d_checksum = dkcksum(lp); ! 554: if (ioctl(fd, DIOCWDINFO, (char *)lp) < 0) { ! 555: perror("ioctl (WDINFO)"); ! 556: fatal("%s: can't rewrite disk label", s); ! 557: } ! 558: #if vax ! 559: if (lp->d_type == DTYPE_SMD && lp->d_flags & D_BADSECT) { ! 560: register i; ! 561: int cfd; ! 562: daddr_t alt; ! 563: char specname[64]; ! 564: char blk[1024]; ! 565: char *cp; ! 566: ! 567: /* ! 568: * Make name for 'c' partition. ! 569: */ ! 570: strcpy(specname, s); ! 571: cp = specname + strlen(specname) - 1; ! 572: if (!isdigit(*cp)) ! 573: *cp = 'c'; ! 574: cfd = open(specname, O_WRONLY); ! 575: if (cfd < 0) { ! 576: perror(specname); ! 577: exit(2); ! 578: } ! 579: bzero(blk, sizeof(blk)); ! 580: *(struct disklabel *)(blk + LABELOFFSET) = *lp; ! 581: alt = lp->d_ncylinders * lp->d_secpercyl - lp->d_nsectors; ! 582: for (i = 1; i < 11 && i < lp->d_nsectors; i += 2) { ! 583: if (lseek(cfd, (off_t)(alt + i) * lp->d_secsize, L_SET) == -1) { ! 584: perror("lseek to badsector area"); ! 585: exit(30); ! 586: } ! 587: if (write(cfd, blk, lp->d_secsize) < lp->d_secsize) { ! 588: int oerrno = errno; ! 589: fprintf(stderr, "alternate label %d ", i/2); ! 590: errno = oerrno; ! 591: perror("write"); ! 592: } ! 593: } ! 594: } ! 595: #endif ! 596: } ! 597: ! 598: /*VARARGS*/ ! 599: fatal(fmt, arg1, arg2) ! 600: char *fmt; ! 601: { ! 602: ! 603: fprintf(stderr, "newfs: "); ! 604: fprintf(stderr, fmt, arg1, arg2); ! 605: putc('\n', stderr); ! 606: exit(10); ! 607: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.