|
|
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.