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