|
|
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.16 (Berkeley) 5/1/88";
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 many cylinders. The actual
45: * number used depends upon how much information can be stored
46: * on a single cylinder. The default is to use 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: /*
95: * For each cylinder we keep track of the availability of blocks at different
96: * rotational positions, so that we can lay out the data to be picked
97: * up with minimum rotational latency. NRPOS is the default number of
98: * rotational positions that we distinguish. With NRPOS of 8 the resolution
99: * of our summary information is 2ms for a typical 3600 rpm drive.
100: */
101: #define NRPOS 8 /* number distinct rotational positions */
102:
103:
104: int Nflag; /* run without writing file system */
105: int fssize; /* file system size */
106: int ntracks; /* # tracks/cylinder */
107: int nsectors; /* # sectors/track */
108: int nphyssectors; /* # sectors/track including spares */
109: int secpercyl; /* sectors per cylinder */
110: int trackspares = -1; /* spare sectors per track */
111: int cylspares = -1; /* spare sectors per cylinder */
112: int sectorsize; /* bytes/sector */
113: #ifdef tahoe
114: int realsectorsize; /* bytes/sector in hardware */
115: #endif
116: int rpm; /* revolutions/minute of drive */
117: int interleave; /* hardware sector interleave */
118: int trackskew = -1; /* sector 0 skew, per track */
119: int headswitch; /* head switch time, usec */
120: int trackseek; /* track-to-track seek, usec */
121: int fsize = 0; /* fragment size */
122: int bsize = 0; /* block size */
123: int cpg = DESCPG; /* cylinders/cylinder group */
124: int cpgflg; /* cylinders/cylinder group flag was given */
125: int minfree = MINFREE; /* free space threshold */
126: int opt = DEFAULTOPT; /* optimization preference (space or time) */
127: int density = NBPI; /* number of bytes per inode */
128: int maxcontig = MAXCONTIG; /* max contiguous blocks to allocate */
129: int rotdelay = ROTDELAY; /* rotational delay between blocks */
130: int maxbpg; /* maximum blocks per file in a cyl group */
131: int nrpos = NRPOS; /* # of distinguished rotational positions */
132: int bbsize = BBSIZE; /* boot block size */
133: int sbsize = SBSIZE; /* superblock size */
134: #ifdef COMPAT
135: int unlabelled;
136: #endif
137:
138: char device[MAXPATHLEN];
139:
140: extern int errno;
141: char *index();
142: char *rindex();
143:
144: main(argc, argv)
145: int argc;
146: char *argv[];
147: {
148: char *cp, *special;
149: register struct partition *pp;
150: register struct disklabel *lp;
151: struct disklabel *getdisklabel();
152: struct partition oldpartition;
153: struct stat st;
154: int fsi, fso;
155: register int i;
156: int status;
157:
158: argc--, argv++;
159: while (argc > 0 && argv[0][0] == '-') {
160: for (cp = &argv[0][1]; *cp; cp++)
161: switch (*cp) {
162:
163: case 'N':
164: Nflag++;
165: break;
166:
167: case 'S':
168: if (argc < 1)
169: fatal("-S: missing sector size");
170: argc--, argv++;
171: sectorsize = atoi(*argv);
172: if (sectorsize <= 0)
173: fatal("%s: bad sector size", *argv);
174: goto next;
175:
176: case 'a':
177: if (argc < 1)
178: fatal("-a: missing max contiguous blocks\n");
179: argc--, argv++;
180: maxcontig = atoi(*argv);
181: if (maxcontig <= 0)
182: fatal("%s: bad max contiguous blocks\n",
183: *argv);
184: goto next;
185:
186: case 'b':
187: if (argc < 1)
188: fatal("-b: missing block size");
189: argc--, argv++;
190: bsize = atoi(*argv);
191: if (bsize < MINBSIZE)
192: fatal("%s: bad block size", *argv);
193: goto next;
194:
195: case 'c':
196: if (argc < 1)
197: fatal("-c: missing cylinders/group");
198: argc--, argv++;
199: cpg = atoi(*argv);
200: if (cpg <= 0)
201: fatal("%s: bad cylinders/group", *argv);
202: cpgflg++;
203: goto next;
204:
205: case 'd':
206: if (argc < 1)
207: fatal("-d: missing rotational delay\n");
208: argc--, argv++;
209: rotdelay = atoi(*argv);
210: if (rotdelay < 0)
211: fatal("%s: bad rotational delay\n",
212: *argv);
213: goto next;
214:
215: case 'e':
216: if (argc < 1)
217: fatal("-e: missing blocks pre file in a cyl group\n");
218: argc--, argv++;
219: maxbpg = atoi(*argv);
220: if (maxbpg <= 0)
221: fatal("%s: bad blocks per file in a cyl group\n",
222: *argv);
223: goto next;
224:
225: case 'f':
226: if (argc < 1)
227: fatal("-f: missing frag size");
228: argc--, argv++;
229: fsize = atoi(*argv);
230: if (fsize <= 0)
231: fatal("%s: bad frag size", *argv);
232: goto next;
233:
234: case 'i':
235: if (argc < 1)
236: fatal("-i: missing bytes per inode\n");
237: argc--, argv++;
238: density = atoi(*argv);
239: if (density <= 0)
240: fatal("%s: bad bytes per inode\n",
241: *argv);
242: goto next;
243:
244: case 'k':
245: if (argc < 1)
246: fatal("-k: track skew");
247: argc--, argv++;
248: trackskew = atoi(*argv);
249: if (trackskew < 0)
250: fatal("%s: bad track skew", *argv);
251: goto next;
252:
253: case 'l':
254: if (argc < 1)
255: fatal("-l: interleave");
256: argc--, argv++;
257: interleave = atoi(*argv);
258: if (interleave <= 0)
259: fatal("%s: bad interleave", *argv);
260: goto next;
261:
262: case 'm':
263: if (argc < 1)
264: fatal("-m: missing free space %%\n");
265: argc--, argv++;
266: minfree = atoi(*argv);
267: if (minfree < 0 || minfree > 99)
268: fatal("%s: bad free space %%\n",
269: *argv);
270: goto next;
271:
272: case 'n':
273: if (argc < 1)
274: fatal("-n: missing rotational layout count\n");
275: argc--, argv++;
276: nrpos = atoi(*argv);
277: if (nrpos <= 0)
278: fatal("%s: bad rotational layout count\n",
279: *argv);
280: goto next;
281:
282: case 'o':
283: if (argc < 1)
284: fatal("-o: missing optimization preference");
285: argc--, argv++;
286: if (strcmp(*argv, "space") == 0)
287: opt = FS_OPTSPACE;
288: else if (strcmp(*argv, "time") == 0)
289: opt = FS_OPTTIME;
290: else
291: fatal("%s: bad optimization preference %s",
292: *argv,
293: "(options are `space' or `time')");
294: goto next;
295:
296: case 'p':
297: if (argc < 1)
298: fatal("-p: spare sectors per track");
299: argc--, argv++;
300: trackspares = atoi(*argv);
301: if (trackspares < 0)
302: fatal("%s: bad spare sectors per track", *argv);
303: goto next;
304:
305: case 'r':
306: if (argc < 1)
307: fatal("-r: missing revs/minute\n");
308: argc--, argv++;
309: rpm = atoi(*argv);
310: if (rpm <= 0)
311: fatal("%s: bad revs/minute\n", *argv);
312: goto next;
313:
314: case 's':
315: if (argc < 1)
316: fatal("-s: missing file system size");
317: argc--, argv++;
318: fssize = atoi(*argv);
319: if (fssize <= 0)
320: fatal("%s: bad file system size",
321: *argv);
322: goto next;
323:
324: case 't':
325: if (argc < 1)
326: fatal("-t: missing track total");
327: argc--, argv++;
328: ntracks = atoi(*argv);
329: if (ntracks <= 0)
330: fatal("%s: bad total tracks", *argv);
331: goto next;
332:
333: case 'u':
334: if (argc < 1)
335: fatal("-u: missing sectors/track");
336: argc--, argv++;
337: nsectors = atoi(*argv);
338: if (nsectors <= 0)
339: fatal("%s: bad sectors/track", *argv);
340: goto next;
341:
342: case 'x':
343: if (argc < 1)
344: fatal("-x: spare sectors per cylinder");
345: argc--, argv++;
346: cylspares = atoi(*argv);
347: if (cylspares < 0)
348: fatal("%s: bad spare sectors per cylinder", *argv);
349: goto next;
350:
351: default:
352: fatal("-%c: unknown flag", *cp);
353: }
354: next:
355: argc--, argv++;
356: }
357: if (argc < 1) {
358: #ifdef COMPAT
359: fprintf(stderr,
360: "usage: newfs [ fsoptions ] special-device [device-type]\n");
361: #else
362: fprintf(stderr, "usage: newfs [ fsoptions ] special-device\n");
363: #endif
364: fprintf(stderr, "where fsoptions are:\n");
365: fprintf(stderr, "\t-N do not create file system, %s\n",
366: "just print out parameters");
367: fprintf(stderr, "\t-b block size\n");
368: fprintf(stderr, "\t-f frag size\n");
369: fprintf(stderr, "\t-m minimum free space %%\n");
370: fprintf(stderr, "\t-o optimization preference %s\n",
371: "(`space' or `time')");
372: fprintf(stderr, "\t-a maximum contiguous blocks\n");
373: fprintf(stderr, "\t-d rotational delay between %s\n",
374: "contiguous blocks");
375: fprintf(stderr, "\t-e maximum blocks per file in a %s\n",
376: "cylinder group");
377: fprintf(stderr, "\t-i number of bytes per inode\n");
378: fprintf(stderr, "\t-c cylinders/group\n");
379: fprintf(stderr, "\t-n number of distinguished %s\n",
380: "rotational positions");
381: fprintf(stderr, "\t-s file system size (sectors)\n");
382: fprintf(stderr, "\t-r revolutions/minute\n");
383: fprintf(stderr, "\t-S sector size\n");
384: fprintf(stderr, "\t-u sectors/track\n");
385: fprintf(stderr, "\t-t tracks/cylinder\n");
386: fprintf(stderr, "\t-p spare sectors per track\n");
387: fprintf(stderr, "\t-x spare sectors per cylinder\n");
388: fprintf(stderr, "\t-l hardware sector interleave\n");
389: fprintf(stderr, "\t-k sector 0 skew, per track\n");
390: exit(1);
391: }
392: special = argv[0];
393: cp = rindex(special, '/');
394: if (cp != 0)
395: special = cp + 1;
396: if (*special == 'r' && special[1] != 'a' && special[1] != 'b')
397: special++;
398: (void)sprintf(device, "/dev/r%s", special);
399: special = device;
400: if (!Nflag) {
401: fso = open(special, O_WRONLY);
402: if (fso < 0) {
403: perror(special);
404: exit(1);
405: }
406: } else
407: fso = -1;
408: fsi = open(special, O_RDONLY);
409: if (fsi < 0) {
410: perror(special);
411: exit(1);
412: }
413: if (fstat(fsi, &st) < 0) {
414: fprintf(stderr, "newfs: "); perror(special);
415: exit(2);
416: }
417: if ((st.st_mode & S_IFMT) != S_IFCHR)
418: fatal("%s: not a character device", special);
419: cp = index(argv[0], '\0') - 1;
420: if (cp == 0 || (*cp < 'a' || *cp > 'h') && !isdigit(*cp))
421: fatal("%s: can't figure out file system partition", argv[0]);
422: #ifdef COMPAT
423: lp = getdisklabel(special, fsi, argv[1]);
424: #else
425: lp = getdisklabel(special, fsi);
426: #endif
427: if (isdigit(*cp))
428: pp = &lp->d_partitions[0];
429: else
430: pp = &lp->d_partitions[*cp - 'a'];
431: if (pp->p_size == 0)
432: fatal("%s: `%c' partition is unavailable", argv[0], *cp);
433: if (fssize == 0)
434: fssize = pp->p_size;
435: if (fssize > pp->p_size)
436: fatal("%s: maximum file system size on the `%c' partition is %d",
437: argv[0], *cp, pp->p_size);
438: if (rpm == 0) {
439: rpm = lp->d_rpm;
440: if (rpm <= 0)
441: rpm = 3600;
442: }
443: if (ntracks == 0) {
444: ntracks = lp->d_ntracks;
445: if (ntracks <= 0)
446: fatal("%s: no default #tracks", argv[0]);
447: }
448: if (nsectors == 0) {
449: nsectors = lp->d_nsectors;
450: if (nsectors <= 0)
451: fatal("%s: no default #sectors/track", argv[0]);
452: }
453: if (sectorsize == 0) {
454: sectorsize = lp->d_secsize;
455: if (sectorsize <= 0)
456: fatal("%s: no default sector size", argv[0]);
457: }
458: if (trackskew == -1) {
459: trackskew = lp->d_trackskew;
460: if (trackskew < 0)
461: trackskew = 0;
462: }
463: if (interleave == 0) {
464: interleave = lp->d_interleave;
465: if (interleave <= 0)
466: interleave = 1;
467: }
468: if (fsize == 0) {
469: fsize = pp->p_fsize;
470: if (fsize <= 0)
471: fsize = MAX(DFL_FRAGSIZE, lp->d_secsize);
472: }
473: if (bsize == 0) {
474: bsize = pp->p_frag * pp->p_fsize;
475: if (bsize <= 0)
476: bsize = MIN(DFL_BLKSIZE, 8 * fsize);
477: }
478: if (minfree < 10 && opt != FS_OPTSPACE) {
479: fprintf(stderr, "Warning: changing optimization to space ");
480: fprintf(stderr, "because minfree is less than 10%%\n");
481: opt = FS_OPTSPACE;
482: }
483: if (trackspares == -1) {
484: trackspares = lp->d_sparespertrack;
485: if (trackspares < 0)
486: trackspares = 0;
487: }
488: nphyssectors = nsectors + trackspares;
489: if (cylspares == -1) {
490: cylspares = lp->d_sparespercyl;
491: if (cylspares < 0)
492: cylspares = 0;
493: }
494: secpercyl = nsectors * ntracks - cylspares;
495: if (secpercyl != lp->d_secpercyl)
496: fprintf(stderr, "%s (%d) %s (%d)\n",
497: "Warning: calculated sectors per cylinder", secpercyl,
498: "disagrees with disk label", lp->d_secpercyl);
499: if (maxbpg == 0)
500: maxbpg = MAXBLKPG(bsize);
501: headswitch = lp->d_headswitch;
502: trackseek = lp->d_trkseek;
503: bbsize = lp->d_bbsize;
504: sbsize = lp->d_sbsize;
505: oldpartition = *pp;
506: #ifdef tahoe
507: realsectorsize = sectorsize;
508: if (sectorsize != DEV_BSIZE) { /* XXX */
509: int secperblk = DEV_BSIZE / sectorsize;
510:
511: sectorsize = DEV_BSIZE;
512: nsectors /= secperblk;
513: nphyssectors /= secperblk;
514: secpercyl /= secperblk;
515: fssize /= secperblk;
516: pp->p_size /= secperblk;
517: }
518: #endif
519: mkfs(pp, special, fsi, fso);
520: #ifdef tahoe
521: if (realsectorsize != DEV_BSIZE)
522: pp->p_size *= DEV_BSIZE / realsectorsize;
523: #endif
524: if (!Nflag && bcmp(pp, &oldpartition, sizeof(oldpartition)))
525: rewritelabel(special, fso, lp);
526: exit(0);
527: }
528:
529: #ifdef COMPAT
530: struct disklabel *
531: getdisklabel(s, fd, type)
532: char *s, *type;
533: int fd;
534: {
535: static struct disklabel lab;
536: struct disklabel *getdiskbyname();
537:
538: if (ioctl(fd, DIOCGDINFO, (char *)&lab) < 0) {
539: if (type == NULL) {
540: perror("ioctl (GDINFO)");
541: fatal(
542: "%s: can't read disk label; disk type must be specified", s);
543: }
544: unlabelled++;
545: return (getdiskbyname(type));
546: }
547: return (&lab);
548: }
549: #else
550: struct disklabel *
551: getdisklabel(s, fd)
552: char *s;
553: int fd;
554: {
555: static struct disklabel lab;
556:
557: if (ioctl(fd, DIOCGDINFO, (char *)&lab) < 0) {
558: perror("ioctl (GDINFO)");
559: fatal("%s: can't read disk label", s);
560: }
561: return (&lab);
562: }
563: #endif
564:
565: rewritelabel(s, fd, lp)
566: char *s;
567: int fd;
568: register struct disklabel *lp;
569: {
570:
571: #ifdef COMPAT
572: if (unlabelled)
573: return;
574: #endif
575: lp->d_checksum = 0;
576: lp->d_checksum = dkcksum(lp);
577: if (ioctl(fd, DIOCWDINFO, (char *)lp) < 0) {
578: perror("ioctl (WDINFO)");
579: fatal("%s: can't rewrite disk label", s);
580: }
581: #if vax
582: if (lp->d_type == DTYPE_SMD && lp->d_flags & D_BADSECT) {
583: register i;
584: int cfd;
585: daddr_t alt;
586: char specname[64];
587: char blk[1024];
588: char *cp;
589:
590: /*
591: * Make name for 'c' partition.
592: */
593: strcpy(specname, s);
594: cp = specname + strlen(specname) - 1;
595: if (!isdigit(*cp))
596: *cp = 'c';
597: cfd = open(specname, O_WRONLY);
598: if (cfd < 0) {
599: perror(specname);
600: exit(2);
601: }
602: bzero(blk, sizeof(blk));
603: *(struct disklabel *)(blk + LABELOFFSET) = *lp;
604: alt = lp->d_ncylinders * lp->d_secpercyl - lp->d_nsectors;
605: for (i = 1; i < 11 && i < lp->d_nsectors; i += 2) {
606: if (lseek(cfd, (off_t)(alt + i) * lp->d_secsize, L_SET) == -1) {
607: perror("lseek to badsector area");
608: exit(30);
609: }
610: if (write(cfd, blk, lp->d_secsize) < lp->d_secsize) {
611: int oerrno = errno;
612: fprintf(stderr, "alternate label %d ", i/2);
613: errno = oerrno;
614: perror("write");
615: }
616: }
617: }
618: #endif
619: }
620:
621: /*VARARGS*/
622: fatal(fmt, arg1, arg2)
623: char *fmt;
624: {
625:
626: fprintf(stderr, "newfs: ");
627: fprintf(stderr, fmt, arg1, arg2);
628: putc('\n', stderr);
629: exit(10);
630: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.