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