Annotation of src/sbin/newfs/newfs.c, Revision 1.47
1.47 ! lukem 1: /* $NetBSD: newfs.c,v 1.46 2001/08/30 14:37:26 lukem Exp $ */
1.18 cgd 2:
1.1 cgd 3: /*
1.10 mycroft 4: * Copyright (c) 1983, 1989, 1993, 1994
5: * The Regents of the University of California. All rights reserved.
1.1 cgd 6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: * 3. All advertising materials mentioning features or use of this software
16: * must display the following acknowledgement:
17: * This product includes software developed by the University of
18: * California, Berkeley and its contributors.
19: * 4. Neither the name of the University nor the names of its contributors
20: * may be used to endorse or promote products derived from this software
21: * without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33: * SUCH DAMAGE.
34: */
35:
1.25 christos 36: #include <sys/cdefs.h>
1.1 cgd 37: #ifndef lint
1.25 christos 38: __COPYRIGHT("@(#) Copyright (c) 1983, 1989, 1993, 1994\n\
39: The Regents of the University of California. All rights reserved.\n");
1.1 cgd 40: #endif /* not lint */
41:
42: #ifndef lint
1.18 cgd 43: #if 0
1.27 lukem 44: static char sccsid[] = "@(#)newfs.c 8.13 (Berkeley) 5/1/95";
1.18 cgd 45: #else
1.47 ! lukem 46: __RCSID("$NetBSD: newfs.c,v 1.46 2001/08/30 14:37:26 lukem Exp $");
1.18 cgd 47: #endif
1.1 cgd 48: #endif /* not lint */
49:
50: /*
51: * newfs: friendly front end to mkfs
52: */
53: #include <sys/param.h>
54: #include <sys/stat.h>
55: #include <sys/ioctl.h>
56: #include <sys/disklabel.h>
57: #include <sys/file.h>
58: #include <sys/mount.h>
1.19 thorpej 59: #include <sys/sysctl.h>
1.30 drochner 60: #include <sys/wait.h>
1.1 cgd 61:
1.10 mycroft 62: #include <ufs/ufs/dir.h>
1.27 lukem 63: #include <ufs/ufs/dinode.h>
1.32 fvdl 64: #include <ufs/ufs/ufsmount.h>
1.10 mycroft 65: #include <ufs/ffs/fs.h>
66:
67: #include <ctype.h>
1.37 tron 68: #include <disktab.h>
1.1 cgd 69: #include <errno.h>
1.10 mycroft 70: #include <paths.h>
1.1 cgd 71: #include <stdio.h>
1.10 mycroft 72: #include <stdlib.h>
1.1 cgd 73: #include <string.h>
1.10 mycroft 74: #include <syslog.h>
75: #include <unistd.h>
1.30 drochner 76: #include <signal.h>
1.25 christos 77: #include <err.h>
1.20 thorpej 78: #include <util.h>
1.10 mycroft 79:
80: #include "mntopts.h"
1.25 christos 81: #include "dkcksum.h"
82: #include "extern.h"
1.10 mycroft 83:
84: struct mntopt mopts[] = {
85: MOPT_STDOPTS,
86: MOPT_ASYNC,
1.22 cgd 87: MOPT_UPDATE,
1.23 tls 88: MOPT_NOATIME,
1.10 mycroft 89: { NULL },
90: };
91:
1.40 simonb 92: static struct disklabel *getdisklabel(char *, int);
93: static void rewritelabel(char *, int, struct disklabel *);
1.43 lukem 94: static int strsuftoi(const char *, const char *, int, int);
1.40 simonb 95: static void usage(void);
96: int main(int, char *[]);
1.1 cgd 97:
98: #define COMPAT /* allow non-labeled disks */
99:
100: /*
101: * The following two constants set the default block and fragment sizes.
102: * Both constants must be a power of 2 and meet the following constraints:
103: * MINBSIZE <= DESBLKSIZE <= MAXBSIZE
104: * sectorsize <= DESFRAGSIZE <= DESBLKSIZE
105: * DESBLKSIZE / DESFRAGSIZE <= 8
106: */
107: #define DFL_FRAGSIZE 1024
108: #define DFL_BLKSIZE 8192
109:
110: /*
1.43 lukem 111: * Default sector size.
112: */
113: #define DFL_SECSIZE 512
114:
115: /*
1.1 cgd 116: * Cylinder groups may have up to many cylinders. The actual
117: * number used depends upon how much information can be stored
118: * on a single cylinder. The default is to use 16 cylinders
119: * per group.
120: */
121: #define DESCPG 16 /* desired fs_cpg */
122:
123: /*
124: * ROTDELAY gives the minimum number of milliseconds to initiate
125: * another disk transfer on the same cylinder. It is used in
126: * determining the rotationally optimal layout for disk blocks
1.13 mycroft 127: * within a file; the default of fs_rotdelay is 0ms.
1.1 cgd 128: */
1.13 mycroft 129: #define ROTDELAY 0
1.1 cgd 130:
131: /*
132: * MAXBLKPG determines the maximum number of data blocks which are
133: * placed in a single cylinder group. The default is one indirect
134: * block worth of data blocks.
135: */
136: #define MAXBLKPG(bsize) ((bsize) / sizeof(daddr_t))
137:
138: /*
139: * Each file system has a number of inodes statically allocated.
140: * We allocate one inode slot per NFPI fragments, expecting this
141: * to be far more than we will ever need.
142: */
143: #define NFPI 4
144:
145: /*
146: * For each cylinder we keep track of the availability of blocks at different
147: * rotational positions, so that we can lay out the data to be picked
148: * up with minimum rotational latency. NRPOS is the default number of
149: * rotational positions that we distinguish. With NRPOS of 8 the resolution
1.13 mycroft 150: * of our summary information is 2ms for a typical 3600 rpm drive. Caching
151: * and zoning pretty much defeats rotational optimization, so we now use a
152: * default of 1.
1.1 cgd 153: */
1.13 mycroft 154: #define NRPOS 1 /* number distinct rotational positions */
1.1 cgd 155:
156:
157: int mfs; /* run as the memory based filesystem */
158: int Nflag; /* run without writing file system */
1.10 mycroft 159: int Oflag; /* format as an 4.3BSD file system */
1.1 cgd 160: int fssize; /* file system size */
161: int ntracks; /* # tracks/cylinder */
162: int nsectors; /* # sectors/track */
163: int nphyssectors; /* # sectors/track including spares */
164: int secpercyl; /* sectors per cylinder */
165: int trackspares = -1; /* spare sectors per track */
166: int cylspares = -1; /* spare sectors per cylinder */
167: int sectorsize; /* bytes/sector */
168: int rpm; /* revolutions/minute of drive */
169: int interleave; /* hardware sector interleave */
170: int trackskew = -1; /* sector 0 skew, per track */
171: int fsize = 0; /* fragment size */
172: int bsize = 0; /* block size */
173: int cpg = DESCPG; /* cylinders/cylinder group */
174: int cpgflg; /* cylinders/cylinder group flag was given */
175: int minfree = MINFREE; /* free space threshold */
176: int opt = DEFAULTOPT; /* optimization preference (space or time) */
177: int density; /* number of bytes per inode */
1.36 mycroft 178: int maxcontig = 0; /* max contiguous blocks to allocate */
1.1 cgd 179: int rotdelay = ROTDELAY; /* rotational delay between blocks */
180: int maxbpg; /* maximum blocks per file in a cyl group */
181: int nrpos = NRPOS; /* # of distinguished rotational positions */
1.47 ! lukem 182: int avgfilesize = AVFILESIZ;/* expected average file size */
! 183: int avgfpdir = AFPDIR; /* expected number of files per directory */
1.1 cgd 184: int bbsize = BBSIZE; /* boot block size */
185: int sbsize = SBSIZE; /* superblock size */
1.10 mycroft 186: int mntflags = MNT_ASYNC; /* flags to be passed to mount */
1.1 cgd 187: u_long memleft; /* virtual memory available */
188: caddr_t membase; /* start address of memory based filesystem */
1.43 lukem 189: int needswap; /* Filesystem not in native byte order */
1.1 cgd 190: #ifdef COMPAT
191: char *disktype;
192: int unlabeled;
193: #endif
194:
195: char device[MAXPATHLEN];
196:
1.10 mycroft 197: int
1.40 simonb 198: main(int argc, char *argv[])
1.1 cgd 199: {
1.25 christos 200: struct partition *pp;
201: struct disklabel *lp;
1.14 cgd 202: struct disklabel mfsfakelabel;
1.1 cgd 203: struct partition oldpartition;
204: struct stat st;
1.10 mycroft 205: struct statfs *mp;
1.43 lukem 206: int ch, fsi, fso, len, maxpartitions, n, Fflag, Zflag;
207: char *cp, *endp, *s1, *s2, *special;
208: const char *opstring;
209: long long llsize;
1.30 drochner 210: #ifdef MFS
211: char mountfromname[100];
212: pid_t pid, res;
213: struct statfs sf;
214: int status;
215: #endif
1.1 cgd 216:
1.43 lukem 217: cp = NULL;
218: fsi = fso = -1;
219: Fflag = Zflag = 0;
1.42 cgd 220: if (strstr(getprogname(), "mfs")) {
1.1 cgd 221: mfs = 1;
222: Nflag++;
223: }
224:
1.19 thorpej 225: maxpartitions = getmaxpartitions();
226: if (maxpartitions > 26)
1.25 christos 227: errx(1, "insane maxpartitions value %d", maxpartitions);
1.19 thorpej 228:
1.10 mycroft 229: opstring = mfs ?
1.47 ! lukem 230: "NT:a:b:c:d:e:f:g:h:i:m:o:s:" :
! 231: "B:FNOS:T:Za:b:c:d:e:f:g:h:i:k:l:m:n:o:p:r:s:t:u:x:";
1.26 lukem 232: while ((ch = getopt(argc, argv, opstring)) != -1)
1.10 mycroft 233: switch (ch) {
1.33 bouyer 234: case 'B':
235: if (strcmp(optarg, "be") == 0) {
236: #if BYTE_ORDER == LITTLE_ENDIAN
237: needswap = 1;
238: #endif
239: } else if (strcmp(optarg, "le") == 0) {
240: #if BYTE_ORDER == BIG_ENDIAN
241: needswap = 1;
242: #endif
243: } else
244: usage();
245: break;
1.43 lukem 246: case 'F':
247: Fflag = 1;
248: break;
1.10 mycroft 249: case 'N':
250: Nflag = 1;
1.1 cgd 251: break;
1.10 mycroft 252: case 'O':
253: Oflag = 1;
1.1 cgd 254: break;
255: case 'S':
1.43 lukem 256: sectorsize = strsuftoi("sector size",
257: optarg, 1, INT_MAX);
1.1 cgd 258: break;
259: #ifdef COMPAT
260: case 'T':
261: disktype = optarg;
262: break;
263: #endif
1.43 lukem 264: case 'Z':
265: Zflag = 1;
266: break;
1.1 cgd 267: case 'a':
1.43 lukem 268: maxcontig = strsuftoi("maximum contiguous blocks",
269: optarg, 1, INT_MAX);
1.1 cgd 270: break;
271: case 'b':
1.43 lukem 272: bsize = strsuftoi("block size",
273: optarg, MINBSIZE, INT_MAX);
1.1 cgd 274: break;
275: case 'c':
1.43 lukem 276: cpg = strsuftoi("cylinders per group",
277: optarg, 1, INT_MAX);
1.1 cgd 278: cpgflg++;
279: break;
280: case 'd':
1.43 lukem 281: rotdelay = strsuftoi("rotational delay",
282: optarg, 0, INT_MAX);
1.1 cgd 283: break;
284: case 'e':
1.43 lukem 285: maxbpg = strsuftoi(
286: "blocks per file in a cylinder group",
287: optarg, 1, INT_MAX);
1.1 cgd 288: break;
289: case 'f':
1.43 lukem 290: fsize = strsuftoi("fragment size",
291: optarg, 1, INT_MAX);
1.1 cgd 292: break;
1.47 ! lukem 293: case 'g':
! 294: avgfilesize = strsuftoi("average file size",
! 295: optarg, 1, INT_MAX);
! 296: break;
! 297: case 'h':
! 298: avgfpdir = strsuftoi("expected files per directory",
! 299: optarg, 1, INT_MAX);
! 300: break;
1.1 cgd 301: case 'i':
1.43 lukem 302: density = strsuftoi("bytes per inode",
303: optarg, 1, INT_MAX);
1.1 cgd 304: break;
305: case 'k':
1.43 lukem 306: trackskew = strsuftoi("track skew",
307: optarg, 0, INT_MAX);
1.1 cgd 308: break;
309: case 'l':
1.43 lukem 310: interleave = strsuftoi("interleave",
311: optarg, 1, INT_MAX);
1.1 cgd 312: break;
313: case 'm':
1.43 lukem 314: minfree = strsuftoi("free space %",
315: optarg, 0, 99);
1.1 cgd 316: break;
317: case 'n':
1.43 lukem 318: nrpos = strsuftoi("rotational layout count",
319: optarg, 1, INT_MAX);
1.1 cgd 320: break;
321: case 'o':
1.10 mycroft 322: if (mfs)
1.27 lukem 323: getmntopts(optarg, mopts, &mntflags, 0);
1.10 mycroft 324: else {
325: if (strcmp(optarg, "space") == 0)
326: opt = FS_OPTSPACE;
327: else if (strcmp(optarg, "time") == 0)
328: opt = FS_OPTTIME;
329: else
1.25 christos 330: errx(1, "%s %s",
331: "unknown optimization preference: ",
332: "use `space' or `time'.");
1.10 mycroft 333: }
1.1 cgd 334: break;
335: case 'p':
1.43 lukem 336: trackspares = strsuftoi("spare sectors per track",
337: optarg, 0, INT_MAX);
1.1 cgd 338: break;
339: case 'r':
1.43 lukem 340: rpm = strsuftoi("revolutions per minute",
341: optarg, 1, INT_MAX);
1.1 cgd 342: break;
343: case 's':
1.43 lukem 344: llsize = strtoll(optarg, &endp, 10);
345: if (endp[0] != '\0' && endp[1] != '\0')
346: llsize = -1;
347: else {
348: int ssiz;
349:
350: ssiz = (sectorsize ? sectorsize : DFL_SECSIZE);
351: switch (tolower((unsigned char)endp[0])) {
352: case 'b':
353: llsize /= ssiz;
354: break;
355: case 'k':
356: llsize *= 1024 / ssiz;
357: break;
358: case 'm':
359: llsize *= 1024 * 1024 / ssiz;
360: break;
361: case 'g':
362: llsize *= 1024 * 1024 * 1024 / ssiz;
363: break;
364: case '\0':
365: case 's':
366: break;
367: default:
368: llsize = -1;
1.41 simonb 369: }
370: }
1.43 lukem 371: if (llsize > INT_MAX)
372: errx(1, "file system size `%s' is too large.",
373: optarg);
374: if (llsize <= 0)
375: errx(1,
376: "`%s' is not a valid number for file system size.",
377: optarg);
378: fssize = (int)llsize;
1.1 cgd 379: break;
380: case 't':
1.43 lukem 381: ntracks = strsuftoi("total tracks",
382: optarg, 1, INT_MAX);
1.1 cgd 383: break;
384: case 'u':
1.43 lukem 385: nsectors = strsuftoi("sectors per track",
386: optarg, 1, INT_MAX);
1.1 cgd 387: break;
388: case 'x':
1.43 lukem 389: cylspares = strsuftoi("spare sectors per cylinder",
390: optarg, 0, INT_MAX);
1.1 cgd 391: break;
392: case '?':
393: default:
394: usage();
395: }
396: argc -= optind;
397: argv += optind;
398:
399: if (argc != 2 && (mfs || argc != 1))
400: usage();
401:
402: special = argv[0];
1.43 lukem 403: if ((mfs && !strcmp(special, "swap")) || Fflag) {
1.14 cgd 404: /*
1.43 lukem 405: * it's an MFS mounted on "swap" or a file system image;
406: * fake up a label. XXX
1.14 cgd 407: */
1.43 lukem 408: if (!sectorsize)
409: sectorsize = DFL_SECSIZE;
410:
411: if (Fflag && (stat(special, &st) != -1 && !S_ISREG(st.st_mode)))
412: errx(1, "%s is not a regular file", special);
413: if (Fflag && !Nflag) { /* creating image in a regular file */
1.44 lukem 414: if (fssize == 0)
415: errx(1, "need to specify size when using -F");
1.43 lukem 416: fso = open(special, O_RDWR | O_CREAT | O_TRUNC, 0777);
417: if (fso == -1)
418: err(1, "can't open file %s", special);
1.44 lukem 419: if ((fsi = dup(fso)) == -1)
420: err(1, "can't dup(2) image fd");
1.43 lukem 421: if (ftruncate(fso, (off_t)fssize * sectorsize) == -1)
422: err(1, "can't resize %s to %d",
423: special, fssize);
424:
425: if (Zflag) { /* pre-zero the file */
426: char *buf;
1.45 lukem 427: int bufsize, i;
428: off_t bufrem;
429: struct statfs sfs;
430:
431: if (fstatfs(fso, &sfs) == -1) {
432: warn("can't fstatfs `%s'", special);
433: bufsize = 8192;
434: } else
435: bufsize = sfs.f_iosize;
1.43 lukem 436:
1.45 lukem 437: if ((buf = calloc(1, bufsize)) == NULL)
1.43 lukem 438: err(1, "can't malloc buffer of %d",
1.45 lukem 439: bufsize);
440: bufrem = fssize * sectorsize;
1.43 lukem 441: printf(
1.45 lukem 442: "Creating file system image in `%s', size %lld bytes, in %d byte chunks.\n",
443: special, (long long)bufrem, bufsize);
444: while (bufrem > 0) {
445: i = write(fso, buf,
446: MIN(bufsize, bufrem));
447: if (i == -1)
448: err(1, "writing image");
449: bufrem -= i;
1.43 lukem 450: }
451: }
452:
453: }
1.14 cgd 454:
455: memset(&mfsfakelabel, 0, sizeof(mfsfakelabel));
1.43 lukem 456: mfsfakelabel.d_secsize = sectorsize;
457: mfsfakelabel.d_nsectors = 64; /* these 3 add up to 16MB */
1.14 cgd 458: mfsfakelabel.d_ntracks = 16;
459: mfsfakelabel.d_ncylinders = 16;
1.43 lukem 460: mfsfakelabel.d_secpercyl =
461: mfsfakelabel.d_nsectors * mfsfakelabel.d_ntracks;
462: mfsfakelabel.d_secperunit =
463: mfsfakelabel.d_ncylinders * mfsfakelabel.d_secpercyl;
1.14 cgd 464: mfsfakelabel.d_rpm = 3600;
465: mfsfakelabel.d_interleave = 1;
466: mfsfakelabel.d_npartitions = 1;
1.43 lukem 467: mfsfakelabel.d_partitions[0].p_size = mfsfakelabel.d_secperunit;
1.14 cgd 468: mfsfakelabel.d_partitions[0].p_fsize = 1024;
469: mfsfakelabel.d_partitions[0].p_frag = 8;
470: mfsfakelabel.d_partitions[0].p_cpg = 16;
471:
472: lp = &mfsfakelabel;
473: pp = &mfsfakelabel.d_partitions[0];
474:
475: goto havelabel;
476: }
1.11 mycroft 477: cp = strrchr(special, '/');
1.43 lukem 478: if (cp == NULL) {
1.1 cgd 479: /*
480: * No path prefix; try /dev/r%s then /dev/%s.
481: */
1.43 lukem 482: (void)snprintf(device, sizeof(device), "%sr%s",
483: _PATH_DEV, special);
1.1 cgd 484: if (stat(device, &st) == -1)
1.34 mycroft 485: (void)snprintf(device, sizeof(device), "%s%s",
486: _PATH_DEV, special);
1.1 cgd 487: special = device;
488: }
1.10 mycroft 489: if (Nflag) {
490: fso = -1;
491: } else {
1.1 cgd 492: fso = open(special, O_WRONLY);
493: if (fso < 0)
1.28 enami 494: err(1, "%s: open", special);
1.10 mycroft 495:
496: /* Bail if target special is mounted */
497: n = getmntinfo(&mp, MNT_NOWAIT);
498: if (n == 0)
1.28 enami 499: err(1, "%s: getmntinfo", special);
1.10 mycroft 500:
501: len = sizeof(_PATH_DEV) - 1;
502: s1 = special;
503: if (strncmp(_PATH_DEV, s1, len) == 0)
504: s1 += len;
505:
506: while (--n >= 0) {
507: s2 = mp->f_mntfromname;
508: if (strncmp(_PATH_DEV, s2, len) == 0) {
509: s2 += len - 1;
510: *s2 = 'r';
511: }
512: if (strcmp(s1, s2) == 0 || strcmp(s1, &s2[1]) == 0)
1.25 christos 513: errx(1, "%s is mounted on %s",
1.10 mycroft 514: special, mp->f_mntonname);
515: ++mp;
516: }
517: }
518: if (mfs && disktype != NULL) {
519: lp = (struct disklabel *)getdiskbyname(disktype);
520: if (lp == NULL)
1.25 christos 521: errx(1, "%s: unknown disk type", disktype);
1.10 mycroft 522: pp = &lp->d_partitions[1];
523: } else {
524: fsi = open(special, O_RDONLY);
525: if (fsi < 0)
1.28 enami 526: err(1, "%s: open", special);
1.10 mycroft 527: if (fstat(fsi, &st) < 0)
1.28 enami 528: err(1, "%s: fstat", special);
1.15 mycroft 529: if (!S_ISCHR(st.st_mode) && !mfs)
1.25 christos 530: warnx("%s: not a character-special device", special);
1.11 mycroft 531: cp = strchr(argv[0], '\0') - 1;
1.25 christos 532: if (cp == 0 || ((*cp < 'a' || *cp > ('a' + maxpartitions - 1))
533: && !isdigit(*cp)))
534: errx(1, "can't figure out file system partition");
1.1 cgd 535: #ifdef COMPAT
1.10 mycroft 536: if (!mfs && disktype == NULL)
537: disktype = argv[1];
1.1 cgd 538: #endif
1.10 mycroft 539: lp = getdisklabel(special, fsi);
540: if (isdigit(*cp))
541: pp = &lp->d_partitions[0];
542: else
543: pp = &lp->d_partitions[*cp - 'a'];
544: if (pp->p_size == 0)
1.25 christos 545: errx(1, "`%c' partition is unavailable", *cp);
1.10 mycroft 546: if (pp->p_fstype == FS_BOOT)
1.25 christos 547: errx(1, "`%c' partition overlaps boot program", *cp);
1.10 mycroft 548: }
1.43 lukem 549:
550: havelabel:
1.1 cgd 551: if (fssize == 0)
552: fssize = pp->p_size;
1.43 lukem 553: if (fssize > pp->p_size && !mfs && !Fflag)
1.25 christos 554: errx(1, "maximum file system size on the `%c' partition is %d",
555: *cp, pp->p_size);
1.1 cgd 556: if (rpm == 0) {
557: rpm = lp->d_rpm;
558: if (rpm <= 0)
559: rpm = 3600;
560: }
561: if (ntracks == 0) {
562: ntracks = lp->d_ntracks;
563: if (ntracks <= 0)
1.25 christos 564: errx(1, "no default #tracks");
1.1 cgd 565: }
566: if (nsectors == 0) {
567: nsectors = lp->d_nsectors;
568: if (nsectors <= 0)
1.25 christos 569: errx(1, "no default #sectors/track");
1.1 cgd 570: }
571: if (sectorsize == 0) {
572: sectorsize = lp->d_secsize;
573: if (sectorsize <= 0)
1.25 christos 574: errx(1, "no default sector size");
1.1 cgd 575: }
576: if (trackskew == -1) {
577: trackskew = lp->d_trackskew;
578: if (trackskew < 0)
579: trackskew = 0;
580: }
581: if (interleave == 0) {
582: interleave = lp->d_interleave;
583: if (interleave <= 0)
584: interleave = 1;
585: }
586: if (fsize == 0) {
587: fsize = pp->p_fsize;
588: if (fsize <= 0)
589: fsize = MAX(DFL_FRAGSIZE, lp->d_secsize);
590: }
591: if (bsize == 0) {
592: bsize = pp->p_frag * pp->p_fsize;
593: if (bsize <= 0)
594: bsize = MIN(DFL_BLKSIZE, 8 * fsize);
1.38 wrstuden 595: }
596: if (cpgflg == 0) {
597: if (pp->p_cpg != 0)
598: cpg = pp->p_cpg;
1.1 cgd 599: }
1.10 mycroft 600: /*
601: * Maxcontig sets the default for the maximum number of blocks
602: * that may be allocated sequentially. With filesystem clustering
603: * it is possible to allocate contiguous blocks up to the maximum
604: * transfer size permitted by the controller or buffering.
605: */
606: if (maxcontig == 0)
1.27 lukem 607: maxcontig = MAX(1, MIN(MAXPHYS, MAXBSIZE) / bsize);
1.1 cgd 608: if (density == 0)
609: density = NFPI * fsize;
1.8 cgd 610: if (minfree < MINFREE && opt != FS_OPTSPACE) {
1.25 christos 611: warnx("%s %s %d%%", "Warning: changing optimization to space",
612: "because minfree is less than", MINFREE);
1.1 cgd 613: opt = FS_OPTSPACE;
614: }
615: if (trackspares == -1) {
616: trackspares = lp->d_sparespertrack;
617: if (trackspares < 0)
618: trackspares = 0;
619: }
620: nphyssectors = nsectors + trackspares;
621: if (cylspares == -1) {
622: cylspares = lp->d_sparespercyl;
623: if (cylspares < 0)
624: cylspares = 0;
625: }
626: secpercyl = nsectors * ntracks - cylspares;
627: if (secpercyl != lp->d_secpercyl)
1.25 christos 628: warnx("%s (%d) %s (%u)\n",
1.1 cgd 629: "Warning: calculated sectors per cylinder", secpercyl,
630: "disagrees with disk label", lp->d_secpercyl);
631: if (maxbpg == 0)
632: maxbpg = MAXBLKPG(bsize);
633: #ifdef notdef /* label may be 0 if faked up by kernel */
634: bbsize = lp->d_bbsize;
635: sbsize = lp->d_sbsize;
636: #endif
637: oldpartition = *pp;
638: mkfs(pp, special, fsi, fso);
1.43 lukem 639: if (!Nflag && memcmp(pp, &oldpartition, sizeof(oldpartition)) && !Fflag)
1.1 cgd 640: rewritelabel(special, fso, lp);
641: if (!Nflag)
642: close(fso);
643: close(fsi);
644: #ifdef MFS
645: if (mfs) {
646: struct mfs_args args;
647:
1.30 drochner 648: switch (pid = fork()) {
649: case -1:
650: perror("mfs");
651: exit(10);
652: case 0:
1.34 mycroft 653: (void)snprintf(mountfromname, sizeof(mountfromname),
654: "mfs:%d", getpid());
1.30 drochner 655: break;
656: default:
1.34 mycroft 657: (void)snprintf(mountfromname, sizeof(mountfromname),
658: "mfs:%d", pid);
1.30 drochner 659: for (;;) {
660: /*
661: * spin until the mount succeeds
662: * or the child exits
663: */
664: usleep(1);
665:
666: /*
667: * XXX Here is a race condition: another process
668: * can mount a filesystem which hides our
669: * ramdisk before we see the success.
670: */
671: if (statfs(argv[1], &sf) < 0)
672: err(88, "statfs %s", argv[1]);
673: if (!strcmp(sf.f_mntfromname, mountfromname) &&
674: !strncmp(sf.f_mntonname, argv[1],
675: MNAMELEN) &&
676: !strcmp(sf.f_fstypename, "mfs"))
677: exit(0);
678:
679: res = waitpid(pid, &status, WNOHANG);
680: if (res == -1)
681: err(11, "waitpid");
682: if (res != pid)
683: continue;
1.31 drochner 684: if (WIFEXITED(status)) {
685: if (WEXITSTATUS(status) == 0)
686: exit(0);
1.30 drochner 687: errx(1, "%s: mount: %s", argv[1],
688: strerror(WEXITSTATUS(status)));
1.31 drochner 689: } else
1.30 drochner 690: errx(11, "abnormal termination");
691: }
692: /* NOTREACHED */
693: }
694:
695: (void) setsid();
696: (void) close(0);
697: (void) close(1);
698: (void) close(2);
699: (void) chdir("/");
700:
701: args.fspec = mountfromname;
1.10 mycroft 702: args.export.ex_root = -2;
703: if (mntflags & MNT_RDONLY)
704: args.export.ex_flags = MNT_EXRDONLY;
705: else
706: args.export.ex_flags = 0;
1.1 cgd 707: args.base = membase;
708: args.size = fssize * sectorsize;
709: if (mount(MOUNT_MFS, argv[1], mntflags, &args) < 0)
1.30 drochner 710: exit(errno); /* parent prints message */
1.1 cgd 711: }
712: #endif
713: exit(0);
714: }
715:
716: #ifdef COMPAT
1.39 is 717: const char lmsg[] = "%s: can't read disk label; disk type must be specified";
1.1 cgd 718: #else
1.39 is 719: const char lmsg[] = "%s: can't read disk label";
1.1 cgd 720: #endif
721:
1.25 christos 722: static struct disklabel *
1.40 simonb 723: getdisklabel(char *s, volatile int fd)
724: /* XXX why is fs volatile?! */
1.1 cgd 725: {
726: static struct disklabel lab;
727:
1.24 tls 728: if (ioctl(fd, DIOCGDINFO, &lab) < 0) {
1.1 cgd 729: #ifdef COMPAT
730: if (disktype) {
1.25 christos 731: struct disklabel *lp;
1.1 cgd 732:
733: unlabeled++;
734: lp = getdiskbyname(disktype);
735: if (lp == NULL)
1.25 christos 736: errx(1, "%s: unknown disk type", disktype);
1.1 cgd 737: return (lp);
738: }
739: #endif
1.10 mycroft 740: warn("ioctl (GDINFO)");
1.25 christos 741: errx(1, lmsg, s);
1.1 cgd 742: }
743: return (&lab);
744: }
745:
1.25 christos 746: static void
1.40 simonb 747: rewritelabel(char *s, volatile int fd, struct disklabel *lp)
748: /* XXX why is fd volatile?! */
1.1 cgd 749: {
750: #ifdef COMPAT
751: if (unlabeled)
752: return;
753: #endif
754: lp->d_checksum = 0;
755: lp->d_checksum = dkcksum(lp);
756: if (ioctl(fd, DIOCWDINFO, (char *)lp) < 0) {
1.10 mycroft 757: warn("ioctl (WDINFO)");
1.25 christos 758: errx(1, "%s: can't rewrite disk label", s);
1.1 cgd 759: }
1.35 matt 760: #if __vax__
1.1 cgd 761: if (lp->d_type == DTYPE_SMD && lp->d_flags & D_BADSECT) {
1.25 christos 762: int i;
1.1 cgd 763: int cfd;
764: daddr_t alt;
765: char specname[64];
766: char blk[1024];
767: char *cp;
768:
769: /*
770: * Make name for 'c' partition.
771: */
772: strcpy(specname, s);
773: cp = specname + strlen(specname) - 1;
774: if (!isdigit(*cp))
775: *cp = 'c';
776: cfd = open(specname, O_WRONLY);
777: if (cfd < 0)
1.28 enami 778: err(1, "%s: open", specname);
1.11 mycroft 779: memset(blk, 0, sizeof(blk));
1.1 cgd 780: *(struct disklabel *)(blk + LABELOFFSET) = *lp;
781: alt = lp->d_ncylinders * lp->d_secpercyl - lp->d_nsectors;
782: for (i = 1; i < 11 && i < lp->d_nsectors; i += 2) {
1.17 cgd 783: off_t offset;
784:
785: offset = alt + i;
786: offset *= lp->d_secsize;
787: if (lseek(cfd, offset, SEEK_SET) == -1)
1.25 christos 788: err(1, "lseek to badsector area: ");
1.1 cgd 789: if (write(cfd, blk, lp->d_secsize) < lp->d_secsize)
1.10 mycroft 790: warn("alternate label %d write", i/2);
1.1 cgd 791: }
792: close(cfd);
793: }
794: #endif
795: }
796:
1.43 lukem 797: static int
798: strsuftoi(const char *desc, const char *arg, int min, int max)
799: {
800: long long result;
801: char *ep;
802:
803: errno = 0;
804: result = strtoll(arg, &ep, 10);
805: if (ep[0] != '\0' && ep[1] != '\0')
806: errx(1, "%s `%s' is not a valid number.", desc, arg);
807: switch (tolower((unsigned char)ep[0])) {
808: case '\0':
809: case 'b':
810: break;
811: case 'k':
812: result <<= 10;
813: break;
814: case 'm':
815: result <<= 20;
816: break;
817: case 'g':
818: result <<= 30;
819: break;
820: default:
821: errx(1, "`%s' is not a valid suffix for %s.", ep, desc);
822: }
823: if (result < min)
824: errx(1, "%s `%s' (%lld) is less than minimum (%d).",
825: desc, arg, result, min);
826: if (result > max)
827: errx(1, "%s `%s' (%lld) is greater than maximum (%d).",
828: desc, arg, result, max);
829: return ((int)result);
830: }
831:
1.25 christos 832: static void
1.40 simonb 833: usage(void)
1.1 cgd 834: {
1.43 lukem 835:
1.1 cgd 836: if (mfs) {
837: fprintf(stderr,
1.43 lukem 838: "usage: %s [ fsoptions ] special-device mount-point\n",
1.42 cgd 839: getprogname());
1.1 cgd 840: } else
841: fprintf(stderr,
1.43 lukem 842: "usage: %s [ fsoptions ] special-device%s\n",
1.42 cgd 843: getprogname(),
1.1 cgd 844: #ifdef COMPAT
845: " [device-type]");
846: #else
847: "");
848: #endif
849: fprintf(stderr, "where fsoptions are:\n");
1.43 lukem 850: if (!mfs) {
851: fprintf(stderr,
852: "\t-B byteorder\tbyte order (`be' or `le')\n");
853: fprintf(stderr,
854: "\t-F\t\tcreate file system image in regular file\n");
855: }
856: fprintf(stderr, "\t-N\t\tdo not create file system, "
857: "just print out parameters\n");
858: if (!mfs) {
859: fprintf(stderr,
860: "\t-O\t\tcreate a 4.3BSD format filesystem\n");
861: fprintf(stderr,
862: "\t-S secsize\tsector size\n");
863: }
1.1 cgd 864: #ifdef COMPAT
1.43 lukem 865: fprintf(stderr, "\t-T disktype\tdisk type\n");
1.1 cgd 866: #endif
1.43 lukem 867: if (!mfs)
868: fprintf(stderr,
869: "\t-Z\t\tpre-zero the image file (with -F)\n");
870: fprintf(stderr, "\t-a maxcontig\tmaximum contiguous blocks\n");
871: fprintf(stderr, "\t-b bsize\tblock size\n");
872: fprintf(stderr, "\t-c cpg\t\tcylinders/group\n");
873: fprintf(stderr, "\t-d rotdelay\trotational delay between "
874: "contiguous blocks\n");
875: fprintf(stderr, "\t-e maxbpg\tmaximum blocks per file "
876: "in a cylinder group\n");
877: fprintf(stderr, "\t-f fsize\tfragment size\n");
1.47 ! lukem 878: fprintf(stderr, "\t-g average file size\n");
! 879: fprintf(stderr, "\t-h average files per directory\n");
1.43 lukem 880: fprintf(stderr, "\t-i density\tnumber of bytes per inode\n");
881: if (!mfs) {
882: fprintf(stderr,
883: "\t-k trackskew\tsector 0 skew, per track\n");
884: fprintf(stderr,
885: "\t-l interleave\thardware sector interleave\n");
886: }
887: fprintf(stderr, "\t-m minfree\tminimum free space %%\n");
888: if (!mfs)
889: fprintf(stderr,
890: "\t-n nrpos\tnumber of distinguished "
891: "rotational positions\n");
892: fprintf(stderr, "\t-o optim\toptimization preference "
893: "(`space' or `time')\n");
894: if (!mfs)
895: fprintf(stderr,
896: "\t-p trackspares\tspare sectors per track\n");
897: fprintf(stderr, "\t-s fssize\tfile system size (sectors)\n");
898: if (!mfs) {
899: fprintf(stderr,
900: "\t-r rpm\t\trevolutions/minute\n");
901: fprintf(stderr,
902: "\t-t ntracks\ttracks/cylinder\n");
903: fprintf(stderr,
904: "\t-u nsectors\tsectors/track\n");
905: fprintf(stderr,
906: "\t-x cylspares\tspare sectors per cylinder\n");
907: }
1.1 cgd 908: exit(1);
909: }
CVSweb <webmaster@jp.NetBSD.org>