xref: /csrg-svn/sbin/newfs/newfs.c (revision 37951)
121159Sdist /*
221159Sdist  * Copyright (c) 1983 Regents of the University of California.
321159Sdist  * All rights reserved.  The Berkeley software License Agreement
421159Sdist  * specifies the terms and conditions for redistribution.
521159Sdist  */
621159Sdist 
710762Ssam #ifndef lint
821159Sdist char copyright[] =
921159Sdist "@(#) Copyright (c) 1983 Regents of the University of California.\n\
1021159Sdist  All rights reserved.\n";
1121159Sdist #endif not lint
1210762Ssam 
1321159Sdist #ifndef lint
14*37951Sbostic static char sccsid[] = "@(#)newfs.c	6.17 (Berkeley) 05/11/89";
1521159Sdist #endif not lint
1621159Sdist 
1710762Ssam /*
1811069Ssam  * newfs: friendly front end to mkfs
1910762Ssam  */
2010762Ssam #include <sys/param.h>
2110762Ssam #include <sys/stat.h>
2210762Ssam #include <sys/fs.h>
2313603Ssam #include <sys/dir.h>
2430380Smckusick #include <sys/ioctl.h>
2530380Smckusick #include <sys/disklabel.h>
2630380Smckusick #include <sys/file.h>
2710762Ssam 
2810762Ssam #include <stdio.h>
2930380Smckusick #include <ctype.h>
30*37951Sbostic #include <paths.h>
3110762Ssam 
3231680Skarels #define COMPAT			/* allow non-labeled disks */
3331680Skarels 
3430380Smckusick /*
3530380Smckusick  * The following two constants set the default block and fragment sizes.
3630380Smckusick  * Both constants must be a power of 2 and meet the following constraints:
3730380Smckusick  *	MINBSIZE <= DESBLKSIZE <= MAXBSIZE
3830380Smckusick  *	sectorsize <= DESFRAGSIZE <= DESBLKSIZE
3930380Smckusick  *	DESBLKSIZE / DESFRAGSIZE <= 8
4030380Smckusick  */
4130380Smckusick #define	DFL_FRAGSIZE	1024
4230380Smckusick #define	DFL_BLKSIZE	8192
4311183Ssam 
4430380Smckusick /*
4534137Smckusick  * Cylinder groups may have up to many cylinders. The actual
4630380Smckusick  * number used depends upon how much information can be stored
4734137Smckusick  * on a single cylinder. The default is to use 16 cylinders
4830380Smckusick  * per group.
4930380Smckusick  */
5030380Smckusick #define	DESCPG		16	/* desired fs_cpg */
5130380Smckusick 
5230380Smckusick /*
5330380Smckusick  * MINFREE gives the minimum acceptable percentage of file system
5430380Smckusick  * blocks which may be free. If the freelist drops below this level
5530380Smckusick  * only the superuser may continue to allocate blocks. This may
5630380Smckusick  * be set to 0 if no reserve of free blocks is deemed necessary,
5730380Smckusick  * however throughput drops by fifty percent if the file system
5830380Smckusick  * is run at between 90% and 100% full; thus the default value of
5930380Smckusick  * fs_minfree is 10%. With 10% free space, fragmentation is not a
6030380Smckusick  * problem, so we choose to optimize for time.
6130380Smckusick  */
6230380Smckusick #define MINFREE		10
6330380Smckusick #define DEFAULTOPT	FS_OPTTIME
6430380Smckusick 
6530380Smckusick /*
6630380Smckusick  * ROTDELAY gives the minimum number of milliseconds to initiate
6730380Smckusick  * another disk transfer on the same cylinder. It is used in
6830380Smckusick  * determining the rotationally optimal layout for disk blocks
6930380Smckusick  * within a file; the default of fs_rotdelay is 4ms.
7030380Smckusick  */
7130380Smckusick #define ROTDELAY	4
7230380Smckusick 
7330380Smckusick /*
7430380Smckusick  * MAXCONTIG sets the default for the maximum number of blocks
7530380Smckusick  * that may be allocated sequentially. Since UNIX drivers are
7630380Smckusick  * not capable of scheduling multi-block transfers, this defaults
7730380Smckusick  * to 1 (ie no contiguous blocks are allocated).
7830380Smckusick  */
7930380Smckusick #define MAXCONTIG	1
8030380Smckusick 
8130380Smckusick /*
8232309Smckusick  * MAXBLKPG determines the maximum number of data blocks which are
8332309Smckusick  * placed in a single cylinder group. The default is one indirect
8432309Smckusick  * block worth of data blocks.
8532309Smckusick  */
8632309Smckusick #define MAXBLKPG(bsize)	((bsize) / sizeof(daddr_t))
8732309Smckusick 
8832309Smckusick /*
8930380Smckusick  * Each file system has a number of inodes statically allocated.
9030380Smckusick  * We allocate one inode slot per NBPI bytes, expecting this
9130380Smckusick  * to be far more than we will ever need.
9230380Smckusick  */
9330380Smckusick #define	NBPI		2048
9430380Smckusick 
9534137Smckusick /*
9634137Smckusick  * For each cylinder we keep track of the availability of blocks at different
9734137Smckusick  * rotational positions, so that we can lay out the data to be picked
9834137Smckusick  * up with minimum rotational latency.  NRPOS is the default number of
9934137Smckusick  * rotational positions that we distinguish.  With NRPOS of 8 the resolution
10034137Smckusick  * of our summary information is 2ms for a typical 3600 rpm drive.
10134137Smckusick  */
10234137Smckusick #define	NRPOS		8	/* number distinct rotational positions */
10334137Smckusick 
10434137Smckusick 
10530380Smckusick int	Nflag;			/* run without writing file system */
10610762Ssam int	fssize;			/* file system size */
10710762Ssam int	ntracks;		/* # tracks/cylinder */
10810762Ssam int	nsectors;		/* # sectors/track */
10930386Smckusick int	nphyssectors;		/* # sectors/track including spares */
11030380Smckusick int	secpercyl;		/* sectors per cylinder */
11130386Smckusick int	trackspares = -1;	/* spare sectors per track */
11230386Smckusick int	cylspares = -1;		/* spare sectors per cylinder */
11310762Ssam int	sectorsize;		/* bytes/sector */
11430691Skarels #ifdef tahoe
11530691Skarels int	realsectorsize;		/* bytes/sector in hardware */
11630691Skarels #endif
11711069Ssam int	rpm;			/* revolutions/minute of drive */
11830386Smckusick int	interleave;		/* hardware sector interleave */
11930386Smckusick int	trackskew = -1;		/* sector 0 skew, per track */
12030386Smckusick int	headswitch;		/* head switch time, usec */
12130386Smckusick int	trackseek;		/* track-to-track seek, usec */
12230862Skarels int	fsize = 0;		/* fragment size */
12330862Skarels int	bsize = 0;		/* block size */
12430380Smckusick int	cpg = DESCPG;		/* cylinders/cylinder group */
12532119Smckusick int	cpgflg;			/* cylinders/cylinder group flag was given */
12630380Smckusick int	minfree = MINFREE;	/* free space threshold */
12730380Smckusick int	opt = DEFAULTOPT;	/* optimization preference (space or time) */
12830380Smckusick int	density = NBPI;		/* number of bytes per inode */
12930380Smckusick int	maxcontig = MAXCONTIG;	/* max contiguous blocks to allocate */
13030380Smckusick int	rotdelay = ROTDELAY;	/* rotational delay between blocks */
13132309Smckusick int	maxbpg;			/* maximum blocks per file in a cyl group */
13234137Smckusick int	nrpos = NRPOS;		/* # of distinguished rotational positions */
13330691Skarels int	bbsize = BBSIZE;	/* boot block size */
13430691Skarels int	sbsize = SBSIZE;	/* superblock size */
13531680Skarels #ifdef COMPAT
13631680Skarels int	unlabelled;
13731680Skarels #endif
13810762Ssam 
13910762Ssam char	device[MAXPATHLEN];
14010762Ssam 
14130380Smckusick extern	int errno;
14210762Ssam char	*index();
14310762Ssam char	*rindex();
14410762Ssam 
14510762Ssam main(argc, argv)
14614064Smckusick 	int argc;
14710762Ssam 	char *argv[];
14810762Ssam {
14910762Ssam 	char *cp, *special;
15010762Ssam 	register struct partition *pp;
15130380Smckusick 	register struct disklabel *lp;
15230380Smckusick 	struct disklabel *getdisklabel();
15330380Smckusick 	struct partition oldpartition;
15410762Ssam 	struct stat st;
15530380Smckusick 	int fsi, fso;
15610762Ssam 	register int i;
15710762Ssam 	int status;
15810762Ssam 
15910762Ssam 	argc--, argv++;
16010762Ssam 	while (argc > 0 && argv[0][0] == '-') {
16110762Ssam 		for (cp = &argv[0][1]; *cp; cp++)
16210762Ssam 			switch (*cp) {
16310762Ssam 
16416945Smckusick 			case 'N':
16516945Smckusick 				Nflag++;
16612334Shelge 				break;
16712334Shelge 
16830380Smckusick 			case 'S':
16910762Ssam 				if (argc < 1)
17030380Smckusick 					fatal("-S: missing sector size");
17110762Ssam 				argc--, argv++;
17230380Smckusick 				sectorsize = atoi(*argv);
17330380Smckusick 				if (sectorsize <= 0)
17430380Smckusick 					fatal("%s: bad sector size", *argv);
17510762Ssam 				goto next;
17610762Ssam 
17730380Smckusick 			case 'a':
17810762Ssam 				if (argc < 1)
17932309Smckusick 					fatal("-a: missing max contiguous blocks\n");
18010762Ssam 				argc--, argv++;
18132309Smckusick 				maxcontig = atoi(*argv);
18232309Smckusick 				if (maxcontig <= 0)
18332309Smckusick 					fatal("%s: bad max contiguous blocks\n",
18432309Smckusick 						*argv);
18510762Ssam 				goto next;
18610762Ssam 
18710762Ssam 			case 'b':
18810762Ssam 				if (argc < 1)
18910762Ssam 					fatal("-b: missing block size");
19010762Ssam 				argc--, argv++;
19110762Ssam 				bsize = atoi(*argv);
19230380Smckusick 				if (bsize < MINBSIZE)
19310762Ssam 					fatal("%s: bad block size", *argv);
19410762Ssam 				goto next;
19510762Ssam 
19630380Smckusick 			case 'c':
19730380Smckusick 				if (argc < 1)
19830380Smckusick 					fatal("-c: missing cylinders/group");
19930380Smckusick 				argc--, argv++;
20030380Smckusick 				cpg = atoi(*argv);
20130380Smckusick 				if (cpg <= 0)
20230380Smckusick 					fatal("%s: bad cylinders/group", *argv);
20332119Smckusick 				cpgflg++;
20430380Smckusick 				goto next;
20530380Smckusick 
20630380Smckusick 			case 'd':
20730380Smckusick 				if (argc < 1)
20832309Smckusick 					fatal("-d: missing rotational delay\n");
20930380Smckusick 				argc--, argv++;
21032309Smckusick 				rotdelay = atoi(*argv);
21132309Smckusick 				if (rotdelay < 0)
21232309Smckusick 					fatal("%s: bad rotational delay\n",
21332309Smckusick 						*argv);
21430380Smckusick 				goto next;
21530380Smckusick 
21632309Smckusick 			case 'e':
21732309Smckusick 				if (argc < 1)
21832309Smckusick 					fatal("-e: missing blocks pre file in a cyl group\n");
21932309Smckusick 				argc--, argv++;
22032309Smckusick 				maxbpg = atoi(*argv);
22132309Smckusick 				if (maxbpg <= 0)
22232309Smckusick 					fatal("%s: bad blocks per file in a cyl group\n",
22332309Smckusick 						*argv);
22432309Smckusick 				goto next;
22532309Smckusick 
22610762Ssam 			case 'f':
22710762Ssam 				if (argc < 1)
22810762Ssam 					fatal("-f: missing frag size");
22910762Ssam 				argc--, argv++;
23010762Ssam 				fsize = atoi(*argv);
23130380Smckusick 				if (fsize <= 0)
23210762Ssam 					fatal("%s: bad frag size", *argv);
23310762Ssam 				goto next;
23410762Ssam 
23530380Smckusick 			case 'i':
23610762Ssam 				if (argc < 1)
23730380Smckusick 					fatal("-i: missing bytes per inode\n");
23810762Ssam 				argc--, argv++;
23930380Smckusick 				density = atoi(*argv);
24030380Smckusick 				if (density <= 0)
24130380Smckusick 					fatal("%s: bad bytes per inode\n",
24230380Smckusick 						*argv);
24310762Ssam 				goto next;
24410762Ssam 
24530386Smckusick 			case 'k':
24630386Smckusick 				if (argc < 1)
24730386Smckusick 					fatal("-k: track skew");
24830386Smckusick 				argc--, argv++;
24930386Smckusick 				trackskew = atoi(*argv);
25030386Smckusick 				if (trackskew < 0)
25130386Smckusick 					fatal("%s: bad track skew", *argv);
25230386Smckusick 				goto next;
25330386Smckusick 
25430386Smckusick 			case 'l':
25530386Smckusick 				if (argc < 1)
25630386Smckusick 					fatal("-l: interleave");
25730386Smckusick 				argc--, argv++;
25830386Smckusick 				interleave = atoi(*argv);
25930386Smckusick 				if (interleave <= 0)
26030386Smckusick 					fatal("%s: bad interleave", *argv);
26130386Smckusick 				goto next;
26230386Smckusick 
26311069Ssam 			case 'm':
26411069Ssam 				if (argc < 1)
26511069Ssam 					fatal("-m: missing free space %%\n");
26611069Ssam 				argc--, argv++;
26711069Ssam 				minfree = atoi(*argv);
26811069Ssam 				if (minfree < 0 || minfree > 99)
26911069Ssam 					fatal("%s: bad free space %%\n",
27011069Ssam 						*argv);
27111069Ssam 				goto next;
27211069Ssam 
27334137Smckusick 			case 'n':
27434137Smckusick 				if (argc < 1)
27534137Smckusick 					fatal("-n: missing rotational layout count\n");
27634137Smckusick 				argc--, argv++;
27734137Smckusick 				nrpos = atoi(*argv);
27834137Smckusick 				if (nrpos <= 0)
27934137Smckusick 					fatal("%s: bad rotational layout count\n",
28034137Smckusick 						*argv);
28134137Smckusick 				goto next;
28234137Smckusick 
28330380Smckusick 			case 'o':
28430380Smckusick 				if (argc < 1)
28530380Smckusick 					fatal("-o: missing optimization preference");
28630380Smckusick 				argc--, argv++;
28730380Smckusick 				if (strcmp(*argv, "space") == 0)
28830380Smckusick 					opt = FS_OPTSPACE;
28930380Smckusick 				else if (strcmp(*argv, "time") == 0)
29030380Smckusick 					opt = FS_OPTTIME;
29130380Smckusick 				else
29230380Smckusick 					fatal("%s: bad optimization preference %s",
29330380Smckusick 					    *argv,
29430380Smckusick 					    "(options are `space' or `time')");
29530380Smckusick 				goto next;
29630380Smckusick 
29730386Smckusick 			case 'p':
29830386Smckusick 				if (argc < 1)
29930386Smckusick 					fatal("-p: spare sectors per track");
30030386Smckusick 				argc--, argv++;
30130386Smckusick 				trackspares = atoi(*argv);
30230386Smckusick 				if (trackspares < 0)
30330386Smckusick 					fatal("%s: bad spare sectors per track", *argv);
30430386Smckusick 				goto next;
30530386Smckusick 
30611069Ssam 			case 'r':
30711069Ssam 				if (argc < 1)
30811069Ssam 					fatal("-r: missing revs/minute\n");
30911069Ssam 				argc--, argv++;
31011069Ssam 				rpm = atoi(*argv);
31130380Smckusick 				if (rpm <= 0)
31211069Ssam 					fatal("%s: bad revs/minute\n", *argv);
31311069Ssam 				goto next;
31411069Ssam 
31530380Smckusick 			case 's':
31614884Smckusick 				if (argc < 1)
31730380Smckusick 					fatal("-s: missing file system size");
31814884Smckusick 				argc--, argv++;
31930380Smckusick 				fssize = atoi(*argv);
32030380Smckusick 				if (fssize <= 0)
32130380Smckusick 					fatal("%s: bad file system size",
32214884Smckusick 						*argv);
32314884Smckusick 				goto next;
32414884Smckusick 
32530380Smckusick 			case 't':
32630380Smckusick 				if (argc < 1)
32730380Smckusick 					fatal("-t: missing track total");
32830380Smckusick 				argc--, argv++;
32930380Smckusick 				ntracks = atoi(*argv);
33030380Smckusick 				if (ntracks <= 0)
33130380Smckusick 					fatal("%s: bad total tracks", *argv);
33230380Smckusick 				goto next;
33330380Smckusick 
33432309Smckusick 			case 'u':
33532309Smckusick 				if (argc < 1)
33632309Smckusick 					fatal("-u: missing sectors/track");
33732309Smckusick 				argc--, argv++;
33832309Smckusick 				nsectors = atoi(*argv);
33932309Smckusick 				if (nsectors <= 0)
34032309Smckusick 					fatal("%s: bad sectors/track", *argv);
34132309Smckusick 				goto next;
34232309Smckusick 
34332309Smckusick 			case 'x':
34432309Smckusick 				if (argc < 1)
34532309Smckusick 					fatal("-x: spare sectors per cylinder");
34632309Smckusick 				argc--, argv++;
34732309Smckusick 				cylspares = atoi(*argv);
34832309Smckusick 				if (cylspares < 0)
34932309Smckusick 					fatal("%s: bad spare sectors per cylinder", *argv);
35032309Smckusick 				goto next;
35132309Smckusick 
35210762Ssam 			default:
35332320Sbostic 				fatal("-%c: unknown flag", *cp);
35410762Ssam 			}
35510762Ssam next:
35610762Ssam 		argc--, argv++;
35710762Ssam 	}
35830380Smckusick 	if (argc < 1) {
35931680Skarels #ifdef COMPAT
36031680Skarels 		fprintf(stderr,
36131680Skarels 		"usage: newfs [ fsoptions ] special-device [device-type]\n");
36231680Skarels #else
36330380Smckusick 		fprintf(stderr, "usage: newfs [ fsoptions ] special-device\n");
36431680Skarels #endif
36530380Smckusick 		fprintf(stderr, "where fsoptions are:\n");
36616945Smckusick 		fprintf(stderr, "\t-N do not create file system, %s\n",
36716945Smckusick 			"just print out parameters");
36811057Ssam 		fprintf(stderr, "\t-b block size\n");
36911057Ssam 		fprintf(stderr, "\t-f frag size\n");
37011069Ssam 		fprintf(stderr, "\t-m minimum free space %%\n");
37124702Smckusick 		fprintf(stderr, "\t-o optimization preference %s\n",
37224702Smckusick 			"(`space' or `time')");
37332309Smckusick 		fprintf(stderr, "\t-a maximum contiguous blocks\n");
37432309Smckusick 		fprintf(stderr, "\t-d rotational delay between %s\n",
37532309Smckusick 			"contiguous blocks");
37632309Smckusick 		fprintf(stderr, "\t-e maximum blocks per file in a %s\n",
37732309Smckusick 			"cylinder group");
37830398Smckusick 		fprintf(stderr, "\t-i number of bytes per inode\n");
37930398Smckusick 		fprintf(stderr, "\t-c cylinders/group\n");
38034137Smckusick 		fprintf(stderr, "\t-n number of distinguished %s\n",
38134137Smckusick 			"rotational positions");
38230398Smckusick 		fprintf(stderr, "\t-s file system size (sectors)\n");
38311069Ssam 		fprintf(stderr, "\t-r revolutions/minute\n");
38411057Ssam 		fprintf(stderr, "\t-S sector size\n");
38532309Smckusick 		fprintf(stderr, "\t-u sectors/track\n");
38630398Smckusick 		fprintf(stderr, "\t-t tracks/cylinder\n");
38730398Smckusick 		fprintf(stderr, "\t-p spare sectors per track\n");
38832309Smckusick 		fprintf(stderr, "\t-x spare sectors per cylinder\n");
38930386Smckusick 		fprintf(stderr, "\t-l hardware sector interleave\n");
39030386Smckusick 		fprintf(stderr, "\t-k sector 0 skew, per track\n");
39110762Ssam 		exit(1);
39210762Ssam 	}
39310762Ssam 	special = argv[0];
39414064Smckusick 	cp = rindex(special, '/');
39514064Smckusick 	if (cp != 0)
39614064Smckusick 		special = cp + 1;
39714321Ssam 	if (*special == 'r' && special[1] != 'a' && special[1] != 'b')
39814064Smckusick 		special++;
399*37951Sbostic 	(void)sprintf(device, "%s/r%s", _PATH_DEV, special);
40032463Sbostic 	special = device;
40130380Smckusick 	if (!Nflag) {
40230380Smckusick 		fso = open(special, O_WRONLY);
40330380Smckusick 		if (fso < 0) {
40430380Smckusick 			perror(special);
40530380Smckusick 			exit(1);
40630380Smckusick 		}
40730380Smckusick 	} else
40830380Smckusick 		fso = -1;
40930380Smckusick 	fsi = open(special, O_RDONLY);
41030380Smckusick 	if (fsi < 0) {
41130380Smckusick 		perror(special);
41230380Smckusick 		exit(1);
41330380Smckusick 	}
41430380Smckusick 	if (fstat(fsi, &st) < 0) {
41511069Ssam 		fprintf(stderr, "newfs: "); perror(special);
41610762Ssam 		exit(2);
41710762Ssam 	}
41814064Smckusick 	if ((st.st_mode & S_IFMT) != S_IFCHR)
41914064Smckusick 		fatal("%s: not a character device", special);
42010762Ssam 	cp = index(argv[0], '\0') - 1;
42130380Smckusick 	if (cp == 0 || (*cp < 'a' || *cp > 'h') && !isdigit(*cp))
42210762Ssam 		fatal("%s: can't figure out file system partition", argv[0]);
42331680Skarels #ifdef COMPAT
42431680Skarels 	lp = getdisklabel(special, fsi, argv[1]);
42531680Skarels #else
42630380Smckusick 	lp = getdisklabel(special, fsi);
42731680Skarels #endif
42830380Smckusick 	if (isdigit(*cp))
42930380Smckusick 		pp = &lp->d_partitions[0];
43030380Smckusick 	else
43130380Smckusick 		pp = &lp->d_partitions[*cp - 'a'];
43230380Smckusick 	if (pp->p_size == 0)
43330380Smckusick 		fatal("%s: `%c' partition is unavailable", argv[0], *cp);
43430380Smckusick 	if (fssize == 0)
43510762Ssam 		fssize = pp->p_size;
43630380Smckusick 	if (fssize > pp->p_size)
43730380Smckusick 	       fatal("%s: maximum file system size on the `%c' partition is %d",
43830380Smckusick 			argv[0], *cp, pp->p_size);
43930380Smckusick 	if (rpm == 0) {
44030380Smckusick 		rpm = lp->d_rpm;
44130380Smckusick 		if (rpm <= 0)
44230743Skarels 			rpm = 3600;
44310762Ssam 	}
44430380Smckusick 	if (ntracks == 0) {
44530380Smckusick 		ntracks = lp->d_ntracks;
44630380Smckusick 		if (ntracks <= 0)
44730743Skarels 			fatal("%s: no default #tracks", argv[0]);
44830380Smckusick 	}
44910762Ssam 	if (nsectors == 0) {
45030380Smckusick 		nsectors = lp->d_nsectors;
45130380Smckusick 		if (nsectors <= 0)
45230743Skarels 			fatal("%s: no default #sectors/track", argv[0]);
45310762Ssam 	}
45410762Ssam 	if (sectorsize == 0) {
45530380Smckusick 		sectorsize = lp->d_secsize;
45630380Smckusick 		if (sectorsize <= 0)
45730743Skarels 			fatal("%s: no default sector size", argv[0]);
45810762Ssam 	}
45930386Smckusick 	if (trackskew == -1) {
46030386Smckusick 		trackskew = lp->d_trackskew;
46130386Smckusick 		if (trackskew < 0)
46230743Skarels 			trackskew = 0;
46330386Smckusick 	}
46430386Smckusick 	if (interleave == 0) {
46530386Smckusick 		interleave = lp->d_interleave;
46630386Smckusick 		if (interleave <= 0)
46730743Skarels 			interleave = 1;
46830386Smckusick 	}
46910762Ssam 	if (fsize == 0) {
47010762Ssam 		fsize = pp->p_fsize;
47130380Smckusick 		if (fsize <= 0)
47230380Smckusick 			fsize = MAX(DFL_FRAGSIZE, lp->d_secsize);
47310762Ssam 	}
47430380Smckusick 	if (bsize == 0) {
47530380Smckusick 		bsize = pp->p_frag * pp->p_fsize;
47630380Smckusick 		if (bsize <= 0)
47730380Smckusick 			bsize = MIN(DFL_BLKSIZE, 8 * fsize);
47811069Ssam 	}
47924702Smckusick 	if (minfree < 10 && opt != FS_OPTSPACE) {
48030380Smckusick 		fprintf(stderr, "Warning: changing optimization to space ");
48130380Smckusick 		fprintf(stderr, "because minfree is less than 10%%\n");
48224702Smckusick 		opt = FS_OPTSPACE;
48324702Smckusick 	}
48430386Smckusick 	if (trackspares == -1) {
48530386Smckusick 		trackspares = lp->d_sparespertrack;
48630386Smckusick 		if (trackspares < 0)
48730743Skarels 			trackspares = 0;
48830386Smckusick 	}
48930386Smckusick 	nphyssectors = nsectors + trackspares;
49030386Smckusick 	if (cylspares == -1) {
49130386Smckusick 		cylspares = lp->d_sparespercyl;
49230386Smckusick 		if (cylspares < 0)
49330743Skarels 			cylspares = 0;
49430386Smckusick 	}
49530386Smckusick 	secpercyl = nsectors * ntracks - cylspares;
49630380Smckusick 	if (secpercyl != lp->d_secpercyl)
49730380Smckusick 		fprintf(stderr, "%s (%d) %s (%d)\n",
49830380Smckusick 			"Warning: calculated sectors per cylinder", secpercyl,
49930380Smckusick 			"disagrees with disk label", lp->d_secpercyl);
50032321Smckusick 	if (maxbpg == 0)
50132321Smckusick 		maxbpg = MAXBLKPG(bsize);
50230386Smckusick 	headswitch = lp->d_headswitch;
50330386Smckusick 	trackseek = lp->d_trkseek;
50430691Skarels 	bbsize = lp->d_bbsize;
50530691Skarels 	sbsize = lp->d_sbsize;
50630380Smckusick 	oldpartition = *pp;
50730691Skarels #ifdef tahoe
50830691Skarels 	realsectorsize = sectorsize;
50930862Skarels 	if (sectorsize != DEV_BSIZE) {		/* XXX */
51030691Skarels 		int secperblk = DEV_BSIZE / sectorsize;
51130691Skarels 
51230691Skarels 		sectorsize = DEV_BSIZE;
51330691Skarels 		nsectors /= secperblk;
51430691Skarels 		nphyssectors /= secperblk;
51530691Skarels 		secpercyl /= secperblk;
51630691Skarels 		fssize /= secperblk;
51730691Skarels 		pp->p_size /= secperblk;
51830691Skarels 	}
51930691Skarels #endif
52030380Smckusick 	mkfs(pp, special, fsi, fso);
52130691Skarels #ifdef tahoe
52230691Skarels 	if (realsectorsize != DEV_BSIZE)
52330691Skarels 		pp->p_size *= DEV_BSIZE / realsectorsize;
52430691Skarels #endif
52530380Smckusick 	if (!Nflag && bcmp(pp, &oldpartition, sizeof(oldpartition)))
52630380Smckusick 		rewritelabel(special, fso, lp);
52730380Smckusick 	exit(0);
52830380Smckusick }
52930380Smckusick 
53031680Skarels #ifdef COMPAT
53130380Smckusick struct disklabel *
53231680Skarels getdisklabel(s, fd, type)
53331680Skarels 	char *s, *type;
53431680Skarels 	int fd;
53531680Skarels {
53631680Skarels 	static struct disklabel lab;
53731680Skarels 	struct disklabel *getdiskbyname();
53831680Skarels 
53931680Skarels 	if (ioctl(fd, DIOCGDINFO, (char *)&lab) < 0) {
54031680Skarels 		if (type == NULL) {
54131680Skarels 			perror("ioctl (GDINFO)");
54231680Skarels 			fatal(
54331680Skarels 		   "%s: can't read disk label; disk type must be specified", s);
54431680Skarels 		}
54531680Skarels 		unlabelled++;
54631680Skarels 		return (getdiskbyname(type));
54731680Skarels 	}
54831680Skarels 	return (&lab);
54931680Skarels }
55031680Skarels #else
55131680Skarels struct disklabel *
55230380Smckusick getdisklabel(s, fd)
55330380Smckusick 	char *s;
55431680Skarels 	int fd;
55530380Smckusick {
55630380Smckusick 	static struct disklabel lab;
55730380Smckusick 
55830380Smckusick 	if (ioctl(fd, DIOCGDINFO, (char *)&lab) < 0) {
55930380Smckusick 		perror("ioctl (GDINFO)");
56030380Smckusick 		fatal("%s: can't read disk label", s);
56110762Ssam 	}
56230380Smckusick 	return (&lab);
56330380Smckusick }
56431680Skarels #endif
56510762Ssam 
56630380Smckusick rewritelabel(s, fd, lp)
56730380Smckusick 	char *s;
56830380Smckusick 	int fd;
56930380Smckusick 	register struct disklabel *lp;
57030380Smckusick {
57130380Smckusick 
57231680Skarels #ifdef COMPAT
57331680Skarels 	if (unlabelled)
57431680Skarels 		return;
57531680Skarels #endif
57630380Smckusick 	lp->d_checksum = 0;
57730380Smckusick 	lp->d_checksum = dkcksum(lp);
57830380Smckusick 	if (ioctl(fd, DIOCWDINFO, (char *)lp) < 0) {
57932786Smckusick 		perror("ioctl (WDINFO)");
58030380Smckusick 		fatal("%s: can't rewrite disk label", s);
58110762Ssam 	}
58230446Skarels #if vax
58330446Skarels 	if (lp->d_type == DTYPE_SMD && lp->d_flags & D_BADSECT) {
58430446Skarels 		register i;
58530691Skarels 		int cfd;
58630446Skarels 		daddr_t alt;
58730691Skarels 		char specname[64];
58830691Skarels 		char blk[1024];
58931045Ssam 		char *cp;
59030446Skarels 
59130691Skarels 		/*
59230691Skarels 		 * Make name for 'c' partition.
59330691Skarels 		 */
59430691Skarels 		strcpy(specname, s);
59530691Skarels 		cp = specname + strlen(specname) - 1;
59630691Skarels 		if (!isdigit(*cp))
59730691Skarels 			*cp = 'c';
59830691Skarels 		cfd = open(specname, O_WRONLY);
59930691Skarels 		if (cfd < 0) {
60030691Skarels 			perror(specname);
60130691Skarels 			exit(2);
60230691Skarels 		}
60330691Skarels 		bzero(blk, sizeof(blk));
60430691Skarels 		*(struct disklabel *)(blk + LABELOFFSET) = *lp;
60530446Skarels 		alt = lp->d_ncylinders * lp->d_secpercyl - lp->d_nsectors;
60630446Skarels 		for (i = 1; i < 11 && i < lp->d_nsectors; i += 2) {
60731680Skarels 			if (lseek(cfd, (off_t)(alt + i) * lp->d_secsize, L_SET) == -1) {
60831680Skarels 				perror("lseek to badsector area");
60931680Skarels 				exit(30);
61031680Skarels 			}
61130691Skarels 			if (write(cfd, blk, lp->d_secsize) < lp->d_secsize) {
61230446Skarels 				int oerrno = errno;
61330446Skarels 				fprintf(stderr, "alternate label %d ", i/2);
61430446Skarels 				errno = oerrno;
61530446Skarels 				perror("write");
61630446Skarels 			}
61730380Smckusick 		}
61830380Smckusick 	}
61930446Skarels #endif
62010762Ssam }
62110762Ssam 
62210762Ssam /*VARARGS*/
62310762Ssam fatal(fmt, arg1, arg2)
62410762Ssam 	char *fmt;
62510762Ssam {
62610762Ssam 
62711069Ssam 	fprintf(stderr, "newfs: ");
62810762Ssam 	fprintf(stderr, fmt, arg1, arg2);
62910762Ssam 	putc('\n', stderr);
63010762Ssam 	exit(10);
63110762Ssam }
632