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