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