xref: /csrg-svn/sbin/newfs/newfs.c (revision 34137)
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*34137Smckusick static char sccsid[] = "@(#)newfs.c	6.16 (Berkeley) 05/01/88";
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>
3010762Ssam 
3131680Skarels #define COMPAT			/* allow non-labeled disks */
3231680Skarels 
3330380Smckusick /*
3430380Smckusick  * The following two constants set the default block and fragment sizes.
3530380Smckusick  * Both constants must be a power of 2 and meet the following constraints:
3630380Smckusick  *	MINBSIZE <= DESBLKSIZE <= MAXBSIZE
3730380Smckusick  *	sectorsize <= DESFRAGSIZE <= DESBLKSIZE
3830380Smckusick  *	DESBLKSIZE / DESFRAGSIZE <= 8
3930380Smckusick  */
4030380Smckusick #define	DFL_FRAGSIZE	1024
4130380Smckusick #define	DFL_BLKSIZE	8192
4211183Ssam 
4330380Smckusick /*
44*34137Smckusick  * Cylinder groups may have up to many cylinders. The actual
4530380Smckusick  * number used depends upon how much information can be stored
46*34137Smckusick  * on a single cylinder. The default is to use 16 cylinders
4730380Smckusick  * per group.
4830380Smckusick  */
4930380Smckusick #define	DESCPG		16	/* desired fs_cpg */
5030380Smckusick 
5130380Smckusick /*
5230380Smckusick  * MINFREE gives the minimum acceptable percentage of file system
5330380Smckusick  * blocks which may be free. If the freelist drops below this level
5430380Smckusick  * only the superuser may continue to allocate blocks. This may
5530380Smckusick  * be set to 0 if no reserve of free blocks is deemed necessary,
5630380Smckusick  * however throughput drops by fifty percent if the file system
5730380Smckusick  * is run at between 90% and 100% full; thus the default value of
5830380Smckusick  * fs_minfree is 10%. With 10% free space, fragmentation is not a
5930380Smckusick  * problem, so we choose to optimize for time.
6030380Smckusick  */
6130380Smckusick #define MINFREE		10
6230380Smckusick #define DEFAULTOPT	FS_OPTTIME
6330380Smckusick 
6430380Smckusick /*
6530380Smckusick  * ROTDELAY gives the minimum number of milliseconds to initiate
6630380Smckusick  * another disk transfer on the same cylinder. It is used in
6730380Smckusick  * determining the rotationally optimal layout for disk blocks
6830380Smckusick  * within a file; the default of fs_rotdelay is 4ms.
6930380Smckusick  */
7030380Smckusick #define ROTDELAY	4
7130380Smckusick 
7230380Smckusick /*
7330380Smckusick  * MAXCONTIG sets the default for the maximum number of blocks
7430380Smckusick  * that may be allocated sequentially. Since UNIX drivers are
7530380Smckusick  * not capable of scheduling multi-block transfers, this defaults
7630380Smckusick  * to 1 (ie no contiguous blocks are allocated).
7730380Smckusick  */
7830380Smckusick #define MAXCONTIG	1
7930380Smckusick 
8030380Smckusick /*
8132309Smckusick  * MAXBLKPG determines the maximum number of data blocks which are
8232309Smckusick  * placed in a single cylinder group. The default is one indirect
8332309Smckusick  * block worth of data blocks.
8432309Smckusick  */
8532309Smckusick #define MAXBLKPG(bsize)	((bsize) / sizeof(daddr_t))
8632309Smckusick 
8732309Smckusick /*
8830380Smckusick  * Each file system has a number of inodes statically allocated.
8930380Smckusick  * We allocate one inode slot per NBPI bytes, expecting this
9030380Smckusick  * to be far more than we will ever need.
9130380Smckusick  */
9230380Smckusick #define	NBPI		2048
9330380Smckusick 
94*34137Smckusick /*
95*34137Smckusick  * For each cylinder we keep track of the availability of blocks at different
96*34137Smckusick  * rotational positions, so that we can lay out the data to be picked
97*34137Smckusick  * up with minimum rotational latency.  NRPOS is the default number of
98*34137Smckusick  * rotational positions that we distinguish.  With NRPOS of 8 the resolution
99*34137Smckusick  * of our summary information is 2ms for a typical 3600 rpm drive.
100*34137Smckusick  */
101*34137Smckusick #define	NRPOS		8	/* number distinct rotational positions */
102*34137Smckusick 
103*34137Smckusick 
10430380Smckusick int	Nflag;			/* run without writing file system */
10510762Ssam int	fssize;			/* file system size */
10610762Ssam int	ntracks;		/* # tracks/cylinder */
10710762Ssam int	nsectors;		/* # sectors/track */
10830386Smckusick int	nphyssectors;		/* # sectors/track including spares */
10930380Smckusick int	secpercyl;		/* sectors per cylinder */
11030386Smckusick int	trackspares = -1;	/* spare sectors per track */
11130386Smckusick int	cylspares = -1;		/* spare sectors per cylinder */
11210762Ssam int	sectorsize;		/* bytes/sector */
11330691Skarels #ifdef tahoe
11430691Skarels int	realsectorsize;		/* bytes/sector in hardware */
11530691Skarels #endif
11611069Ssam int	rpm;			/* revolutions/minute of drive */
11730386Smckusick int	interleave;		/* hardware sector interleave */
11830386Smckusick int	trackskew = -1;		/* sector 0 skew, per track */
11930386Smckusick int	headswitch;		/* head switch time, usec */
12030386Smckusick int	trackseek;		/* track-to-track seek, usec */
12130862Skarels int	fsize = 0;		/* fragment size */
12230862Skarels int	bsize = 0;		/* block size */
12330380Smckusick int	cpg = DESCPG;		/* cylinders/cylinder group */
12432119Smckusick int	cpgflg;			/* cylinders/cylinder group flag was given */
12530380Smckusick int	minfree = MINFREE;	/* free space threshold */
12630380Smckusick int	opt = DEFAULTOPT;	/* optimization preference (space or time) */
12730380Smckusick int	density = NBPI;		/* number of bytes per inode */
12830380Smckusick int	maxcontig = MAXCONTIG;	/* max contiguous blocks to allocate */
12930380Smckusick int	rotdelay = ROTDELAY;	/* rotational delay between blocks */
13032309Smckusick int	maxbpg;			/* maximum blocks per file in a cyl group */
131*34137Smckusick int	nrpos = NRPOS;		/* # of distinguished rotational positions */
13230691Skarels int	bbsize = BBSIZE;	/* boot block size */
13330691Skarels int	sbsize = SBSIZE;	/* superblock size */
13431680Skarels #ifdef COMPAT
13531680Skarels int	unlabelled;
13631680Skarels #endif
13710762Ssam 
13810762Ssam char	device[MAXPATHLEN];
13910762Ssam 
14030380Smckusick extern	int errno;
14110762Ssam char	*index();
14210762Ssam char	*rindex();
14310762Ssam 
14410762Ssam main(argc, argv)
14514064Smckusick 	int argc;
14610762Ssam 	char *argv[];
14710762Ssam {
14810762Ssam 	char *cp, *special;
14910762Ssam 	register struct partition *pp;
15030380Smckusick 	register struct disklabel *lp;
15130380Smckusick 	struct disklabel *getdisklabel();
15230380Smckusick 	struct partition oldpartition;
15310762Ssam 	struct stat st;
15430380Smckusick 	int fsi, fso;
15510762Ssam 	register int i;
15610762Ssam 	int status;
15710762Ssam 
15810762Ssam 	argc--, argv++;
15910762Ssam 	while (argc > 0 && argv[0][0] == '-') {
16010762Ssam 		for (cp = &argv[0][1]; *cp; cp++)
16110762Ssam 			switch (*cp) {
16210762Ssam 
16316945Smckusick 			case 'N':
16416945Smckusick 				Nflag++;
16512334Shelge 				break;
16612334Shelge 
16730380Smckusick 			case 'S':
16810762Ssam 				if (argc < 1)
16930380Smckusick 					fatal("-S: missing sector size");
17010762Ssam 				argc--, argv++;
17130380Smckusick 				sectorsize = atoi(*argv);
17230380Smckusick 				if (sectorsize <= 0)
17330380Smckusick 					fatal("%s: bad sector size", *argv);
17410762Ssam 				goto next;
17510762Ssam 
17630380Smckusick 			case 'a':
17710762Ssam 				if (argc < 1)
17832309Smckusick 					fatal("-a: missing max contiguous blocks\n");
17910762Ssam 				argc--, argv++;
18032309Smckusick 				maxcontig = atoi(*argv);
18132309Smckusick 				if (maxcontig <= 0)
18232309Smckusick 					fatal("%s: bad max contiguous blocks\n",
18332309Smckusick 						*argv);
18410762Ssam 				goto next;
18510762Ssam 
18610762Ssam 			case 'b':
18710762Ssam 				if (argc < 1)
18810762Ssam 					fatal("-b: missing block size");
18910762Ssam 				argc--, argv++;
19010762Ssam 				bsize = atoi(*argv);
19130380Smckusick 				if (bsize < MINBSIZE)
19210762Ssam 					fatal("%s: bad block size", *argv);
19310762Ssam 				goto next;
19410762Ssam 
19530380Smckusick 			case 'c':
19630380Smckusick 				if (argc < 1)
19730380Smckusick 					fatal("-c: missing cylinders/group");
19830380Smckusick 				argc--, argv++;
19930380Smckusick 				cpg = atoi(*argv);
20030380Smckusick 				if (cpg <= 0)
20130380Smckusick 					fatal("%s: bad cylinders/group", *argv);
20232119Smckusick 				cpgflg++;
20330380Smckusick 				goto next;
20430380Smckusick 
20530380Smckusick 			case 'd':
20630380Smckusick 				if (argc < 1)
20732309Smckusick 					fatal("-d: missing rotational delay\n");
20830380Smckusick 				argc--, argv++;
20932309Smckusick 				rotdelay = atoi(*argv);
21032309Smckusick 				if (rotdelay < 0)
21132309Smckusick 					fatal("%s: bad rotational delay\n",
21232309Smckusick 						*argv);
21330380Smckusick 				goto next;
21430380Smckusick 
21532309Smckusick 			case 'e':
21632309Smckusick 				if (argc < 1)
21732309Smckusick 					fatal("-e: missing blocks pre file in a cyl group\n");
21832309Smckusick 				argc--, argv++;
21932309Smckusick 				maxbpg = atoi(*argv);
22032309Smckusick 				if (maxbpg <= 0)
22132309Smckusick 					fatal("%s: bad blocks per file in a cyl group\n",
22232309Smckusick 						*argv);
22332309Smckusick 				goto next;
22432309Smckusick 
22510762Ssam 			case 'f':
22610762Ssam 				if (argc < 1)
22710762Ssam 					fatal("-f: missing frag size");
22810762Ssam 				argc--, argv++;
22910762Ssam 				fsize = atoi(*argv);
23030380Smckusick 				if (fsize <= 0)
23110762Ssam 					fatal("%s: bad frag size", *argv);
23210762Ssam 				goto next;
23310762Ssam 
23430380Smckusick 			case 'i':
23510762Ssam 				if (argc < 1)
23630380Smckusick 					fatal("-i: missing bytes per inode\n");
23710762Ssam 				argc--, argv++;
23830380Smckusick 				density = atoi(*argv);
23930380Smckusick 				if (density <= 0)
24030380Smckusick 					fatal("%s: bad bytes per inode\n",
24130380Smckusick 						*argv);
24210762Ssam 				goto next;
24310762Ssam 
24430386Smckusick 			case 'k':
24530386Smckusick 				if (argc < 1)
24630386Smckusick 					fatal("-k: track skew");
24730386Smckusick 				argc--, argv++;
24830386Smckusick 				trackskew = atoi(*argv);
24930386Smckusick 				if (trackskew < 0)
25030386Smckusick 					fatal("%s: bad track skew", *argv);
25130386Smckusick 				goto next;
25230386Smckusick 
25330386Smckusick 			case 'l':
25430386Smckusick 				if (argc < 1)
25530386Smckusick 					fatal("-l: interleave");
25630386Smckusick 				argc--, argv++;
25730386Smckusick 				interleave = atoi(*argv);
25830386Smckusick 				if (interleave <= 0)
25930386Smckusick 					fatal("%s: bad interleave", *argv);
26030386Smckusick 				goto next;
26130386Smckusick 
26211069Ssam 			case 'm':
26311069Ssam 				if (argc < 1)
26411069Ssam 					fatal("-m: missing free space %%\n");
26511069Ssam 				argc--, argv++;
26611069Ssam 				minfree = atoi(*argv);
26711069Ssam 				if (minfree < 0 || minfree > 99)
26811069Ssam 					fatal("%s: bad free space %%\n",
26911069Ssam 						*argv);
27011069Ssam 				goto next;
27111069Ssam 
272*34137Smckusick 			case 'n':
273*34137Smckusick 				if (argc < 1)
274*34137Smckusick 					fatal("-n: missing rotational layout count\n");
275*34137Smckusick 				argc--, argv++;
276*34137Smckusick 				nrpos = atoi(*argv);
277*34137Smckusick 				if (nrpos <= 0)
278*34137Smckusick 					fatal("%s: bad rotational layout count\n",
279*34137Smckusick 						*argv);
280*34137Smckusick 				goto next;
281*34137Smckusick 
28230380Smckusick 			case 'o':
28330380Smckusick 				if (argc < 1)
28430380Smckusick 					fatal("-o: missing optimization preference");
28530380Smckusick 				argc--, argv++;
28630380Smckusick 				if (strcmp(*argv, "space") == 0)
28730380Smckusick 					opt = FS_OPTSPACE;
28830380Smckusick 				else if (strcmp(*argv, "time") == 0)
28930380Smckusick 					opt = FS_OPTTIME;
29030380Smckusick 				else
29130380Smckusick 					fatal("%s: bad optimization preference %s",
29230380Smckusick 					    *argv,
29330380Smckusick 					    "(options are `space' or `time')");
29430380Smckusick 				goto next;
29530380Smckusick 
29630386Smckusick 			case 'p':
29730386Smckusick 				if (argc < 1)
29830386Smckusick 					fatal("-p: spare sectors per track");
29930386Smckusick 				argc--, argv++;
30030386Smckusick 				trackspares = atoi(*argv);
30130386Smckusick 				if (trackspares < 0)
30230386Smckusick 					fatal("%s: bad spare sectors per track", *argv);
30330386Smckusick 				goto next;
30430386Smckusick 
30511069Ssam 			case 'r':
30611069Ssam 				if (argc < 1)
30711069Ssam 					fatal("-r: missing revs/minute\n");
30811069Ssam 				argc--, argv++;
30911069Ssam 				rpm = atoi(*argv);
31030380Smckusick 				if (rpm <= 0)
31111069Ssam 					fatal("%s: bad revs/minute\n", *argv);
31211069Ssam 				goto next;
31311069Ssam 
31430380Smckusick 			case 's':
31514884Smckusick 				if (argc < 1)
31630380Smckusick 					fatal("-s: missing file system size");
31714884Smckusick 				argc--, argv++;
31830380Smckusick 				fssize = atoi(*argv);
31930380Smckusick 				if (fssize <= 0)
32030380Smckusick 					fatal("%s: bad file system size",
32114884Smckusick 						*argv);
32214884Smckusick 				goto next;
32314884Smckusick 
32430380Smckusick 			case 't':
32530380Smckusick 				if (argc < 1)
32630380Smckusick 					fatal("-t: missing track total");
32730380Smckusick 				argc--, argv++;
32830380Smckusick 				ntracks = atoi(*argv);
32930380Smckusick 				if (ntracks <= 0)
33030380Smckusick 					fatal("%s: bad total tracks", *argv);
33130380Smckusick 				goto next;
33230380Smckusick 
33332309Smckusick 			case 'u':
33432309Smckusick 				if (argc < 1)
33532309Smckusick 					fatal("-u: missing sectors/track");
33632309Smckusick 				argc--, argv++;
33732309Smckusick 				nsectors = atoi(*argv);
33832309Smckusick 				if (nsectors <= 0)
33932309Smckusick 					fatal("%s: bad sectors/track", *argv);
34032309Smckusick 				goto next;
34132309Smckusick 
34232309Smckusick 			case 'x':
34332309Smckusick 				if (argc < 1)
34432309Smckusick 					fatal("-x: spare sectors per cylinder");
34532309Smckusick 				argc--, argv++;
34632309Smckusick 				cylspares = atoi(*argv);
34732309Smckusick 				if (cylspares < 0)
34832309Smckusick 					fatal("%s: bad spare sectors per cylinder", *argv);
34932309Smckusick 				goto next;
35032309Smckusick 
35110762Ssam 			default:
35232320Sbostic 				fatal("-%c: unknown flag", *cp);
35310762Ssam 			}
35410762Ssam next:
35510762Ssam 		argc--, argv++;
35610762Ssam 	}
35730380Smckusick 	if (argc < 1) {
35831680Skarels #ifdef COMPAT
35931680Skarels 		fprintf(stderr,
36031680Skarels 		"usage: newfs [ fsoptions ] special-device [device-type]\n");
36131680Skarels #else
36230380Smckusick 		fprintf(stderr, "usage: newfs [ fsoptions ] special-device\n");
36331680Skarels #endif
36430380Smckusick 		fprintf(stderr, "where fsoptions are:\n");
36516945Smckusick 		fprintf(stderr, "\t-N do not create file system, %s\n",
36616945Smckusick 			"just print out parameters");
36711057Ssam 		fprintf(stderr, "\t-b block size\n");
36811057Ssam 		fprintf(stderr, "\t-f frag size\n");
36911069Ssam 		fprintf(stderr, "\t-m minimum free space %%\n");
37024702Smckusick 		fprintf(stderr, "\t-o optimization preference %s\n",
37124702Smckusick 			"(`space' or `time')");
37232309Smckusick 		fprintf(stderr, "\t-a maximum contiguous blocks\n");
37332309Smckusick 		fprintf(stderr, "\t-d rotational delay between %s\n",
37432309Smckusick 			"contiguous blocks");
37532309Smckusick 		fprintf(stderr, "\t-e maximum blocks per file in a %s\n",
37632309Smckusick 			"cylinder group");
37730398Smckusick 		fprintf(stderr, "\t-i number of bytes per inode\n");
37830398Smckusick 		fprintf(stderr, "\t-c cylinders/group\n");
379*34137Smckusick 		fprintf(stderr, "\t-n number of distinguished %s\n",
380*34137Smckusick 			"rotational positions");
38130398Smckusick 		fprintf(stderr, "\t-s file system size (sectors)\n");
38211069Ssam 		fprintf(stderr, "\t-r revolutions/minute\n");
38311057Ssam 		fprintf(stderr, "\t-S sector size\n");
38432309Smckusick 		fprintf(stderr, "\t-u sectors/track\n");
38530398Smckusick 		fprintf(stderr, "\t-t tracks/cylinder\n");
38630398Smckusick 		fprintf(stderr, "\t-p spare sectors per track\n");
38732309Smckusick 		fprintf(stderr, "\t-x spare sectors per cylinder\n");
38830386Smckusick 		fprintf(stderr, "\t-l hardware sector interleave\n");
38930386Smckusick 		fprintf(stderr, "\t-k sector 0 skew, per track\n");
39010762Ssam 		exit(1);
39110762Ssam 	}
39210762Ssam 	special = argv[0];
39314064Smckusick 	cp = rindex(special, '/');
39414064Smckusick 	if (cp != 0)
39514064Smckusick 		special = cp + 1;
39614321Ssam 	if (*special == 'r' && special[1] != 'a' && special[1] != 'b')
39714064Smckusick 		special++;
39832463Sbostic 	(void)sprintf(device, "/dev/r%s", special);
39932463Sbostic 	special = device;
40030380Smckusick 	if (!Nflag) {
40130380Smckusick 		fso = open(special, O_WRONLY);
40230380Smckusick 		if (fso < 0) {
40330380Smckusick 			perror(special);
40430380Smckusick 			exit(1);
40530380Smckusick 		}
40630380Smckusick 	} else
40730380Smckusick 		fso = -1;
40830380Smckusick 	fsi = open(special, O_RDONLY);
40930380Smckusick 	if (fsi < 0) {
41030380Smckusick 		perror(special);
41130380Smckusick 		exit(1);
41230380Smckusick 	}
41330380Smckusick 	if (fstat(fsi, &st) < 0) {
41411069Ssam 		fprintf(stderr, "newfs: "); perror(special);
41510762Ssam 		exit(2);
41610762Ssam 	}
41714064Smckusick 	if ((st.st_mode & S_IFMT) != S_IFCHR)
41814064Smckusick 		fatal("%s: not a character device", special);
41910762Ssam 	cp = index(argv[0], '\0') - 1;
42030380Smckusick 	if (cp == 0 || (*cp < 'a' || *cp > 'h') && !isdigit(*cp))
42110762Ssam 		fatal("%s: can't figure out file system partition", argv[0]);
42231680Skarels #ifdef COMPAT
42331680Skarels 	lp = getdisklabel(special, fsi, argv[1]);
42431680Skarels #else
42530380Smckusick 	lp = getdisklabel(special, fsi);
42631680Skarels #endif
42730380Smckusick 	if (isdigit(*cp))
42830380Smckusick 		pp = &lp->d_partitions[0];
42930380Smckusick 	else
43030380Smckusick 		pp = &lp->d_partitions[*cp - 'a'];
43130380Smckusick 	if (pp->p_size == 0)
43230380Smckusick 		fatal("%s: `%c' partition is unavailable", argv[0], *cp);
43330380Smckusick 	if (fssize == 0)
43410762Ssam 		fssize = pp->p_size;
43530380Smckusick 	if (fssize > pp->p_size)
43630380Smckusick 	       fatal("%s: maximum file system size on the `%c' partition is %d",
43730380Smckusick 			argv[0], *cp, pp->p_size);
43830380Smckusick 	if (rpm == 0) {
43930380Smckusick 		rpm = lp->d_rpm;
44030380Smckusick 		if (rpm <= 0)
44130743Skarels 			rpm = 3600;
44210762Ssam 	}
44330380Smckusick 	if (ntracks == 0) {
44430380Smckusick 		ntracks = lp->d_ntracks;
44530380Smckusick 		if (ntracks <= 0)
44630743Skarels 			fatal("%s: no default #tracks", argv[0]);
44730380Smckusick 	}
44810762Ssam 	if (nsectors == 0) {
44930380Smckusick 		nsectors = lp->d_nsectors;
45030380Smckusick 		if (nsectors <= 0)
45130743Skarels 			fatal("%s: no default #sectors/track", argv[0]);
45210762Ssam 	}
45310762Ssam 	if (sectorsize == 0) {
45430380Smckusick 		sectorsize = lp->d_secsize;
45530380Smckusick 		if (sectorsize <= 0)
45630743Skarels 			fatal("%s: no default sector size", argv[0]);
45710762Ssam 	}
45830386Smckusick 	if (trackskew == -1) {
45930386Smckusick 		trackskew = lp->d_trackskew;
46030386Smckusick 		if (trackskew < 0)
46130743Skarels 			trackskew = 0;
46230386Smckusick 	}
46330386Smckusick 	if (interleave == 0) {
46430386Smckusick 		interleave = lp->d_interleave;
46530386Smckusick 		if (interleave <= 0)
46630743Skarels 			interleave = 1;
46730386Smckusick 	}
46810762Ssam 	if (fsize == 0) {
46910762Ssam 		fsize = pp->p_fsize;
47030380Smckusick 		if (fsize <= 0)
47130380Smckusick 			fsize = MAX(DFL_FRAGSIZE, lp->d_secsize);
47210762Ssam 	}
47330380Smckusick 	if (bsize == 0) {
47430380Smckusick 		bsize = pp->p_frag * pp->p_fsize;
47530380Smckusick 		if (bsize <= 0)
47630380Smckusick 			bsize = MIN(DFL_BLKSIZE, 8 * fsize);
47711069Ssam 	}
47824702Smckusick 	if (minfree < 10 && opt != FS_OPTSPACE) {
47930380Smckusick 		fprintf(stderr, "Warning: changing optimization to space ");
48030380Smckusick 		fprintf(stderr, "because minfree is less than 10%%\n");
48124702Smckusick 		opt = FS_OPTSPACE;
48224702Smckusick 	}
48330386Smckusick 	if (trackspares == -1) {
48430386Smckusick 		trackspares = lp->d_sparespertrack;
48530386Smckusick 		if (trackspares < 0)
48630743Skarels 			trackspares = 0;
48730386Smckusick 	}
48830386Smckusick 	nphyssectors = nsectors + trackspares;
48930386Smckusick 	if (cylspares == -1) {
49030386Smckusick 		cylspares = lp->d_sparespercyl;
49130386Smckusick 		if (cylspares < 0)
49230743Skarels 			cylspares = 0;
49330386Smckusick 	}
49430386Smckusick 	secpercyl = nsectors * ntracks - cylspares;
49530380Smckusick 	if (secpercyl != lp->d_secpercyl)
49630380Smckusick 		fprintf(stderr, "%s (%d) %s (%d)\n",
49730380Smckusick 			"Warning: calculated sectors per cylinder", secpercyl,
49830380Smckusick 			"disagrees with disk label", lp->d_secpercyl);
49932321Smckusick 	if (maxbpg == 0)
50032321Smckusick 		maxbpg = MAXBLKPG(bsize);
50130386Smckusick 	headswitch = lp->d_headswitch;
50230386Smckusick 	trackseek = lp->d_trkseek;
50330691Skarels 	bbsize = lp->d_bbsize;
50430691Skarels 	sbsize = lp->d_sbsize;
50530380Smckusick 	oldpartition = *pp;
50630691Skarels #ifdef tahoe
50730691Skarels 	realsectorsize = sectorsize;
50830862Skarels 	if (sectorsize != DEV_BSIZE) {		/* XXX */
50930691Skarels 		int secperblk = DEV_BSIZE / sectorsize;
51030691Skarels 
51130691Skarels 		sectorsize = DEV_BSIZE;
51230691Skarels 		nsectors /= secperblk;
51330691Skarels 		nphyssectors /= secperblk;
51430691Skarels 		secpercyl /= secperblk;
51530691Skarels 		fssize /= secperblk;
51630691Skarels 		pp->p_size /= secperblk;
51730691Skarels 	}
51830691Skarels #endif
51930380Smckusick 	mkfs(pp, special, fsi, fso);
52030691Skarels #ifdef tahoe
52130691Skarels 	if (realsectorsize != DEV_BSIZE)
52230691Skarels 		pp->p_size *= DEV_BSIZE / realsectorsize;
52330691Skarels #endif
52430380Smckusick 	if (!Nflag && bcmp(pp, &oldpartition, sizeof(oldpartition)))
52530380Smckusick 		rewritelabel(special, fso, lp);
52630380Smckusick 	exit(0);
52730380Smckusick }
52830380Smckusick 
52931680Skarels #ifdef COMPAT
53030380Smckusick struct disklabel *
53131680Skarels getdisklabel(s, fd, type)
53231680Skarels 	char *s, *type;
53331680Skarels 	int fd;
53431680Skarels {
53531680Skarels 	static struct disklabel lab;
53631680Skarels 	struct disklabel *getdiskbyname();
53731680Skarels 
53831680Skarels 	if (ioctl(fd, DIOCGDINFO, (char *)&lab) < 0) {
53931680Skarels 		if (type == NULL) {
54031680Skarels 			perror("ioctl (GDINFO)");
54131680Skarels 			fatal(
54231680Skarels 		   "%s: can't read disk label; disk type must be specified", s);
54331680Skarels 		}
54431680Skarels 		unlabelled++;
54531680Skarels 		return (getdiskbyname(type));
54631680Skarels 	}
54731680Skarels 	return (&lab);
54831680Skarels }
54931680Skarels #else
55031680Skarels struct disklabel *
55130380Smckusick getdisklabel(s, fd)
55230380Smckusick 	char *s;
55331680Skarels 	int fd;
55430380Smckusick {
55530380Smckusick 	static struct disklabel lab;
55630380Smckusick 
55730380Smckusick 	if (ioctl(fd, DIOCGDINFO, (char *)&lab) < 0) {
55830380Smckusick 		perror("ioctl (GDINFO)");
55930380Smckusick 		fatal("%s: can't read disk label", s);
56010762Ssam 	}
56130380Smckusick 	return (&lab);
56230380Smckusick }
56331680Skarels #endif
56410762Ssam 
56530380Smckusick rewritelabel(s, fd, lp)
56630380Smckusick 	char *s;
56730380Smckusick 	int fd;
56830380Smckusick 	register struct disklabel *lp;
56930380Smckusick {
57030380Smckusick 
57131680Skarels #ifdef COMPAT
57231680Skarels 	if (unlabelled)
57331680Skarels 		return;
57431680Skarels #endif
57530380Smckusick 	lp->d_checksum = 0;
57630380Smckusick 	lp->d_checksum = dkcksum(lp);
57730380Smckusick 	if (ioctl(fd, DIOCWDINFO, (char *)lp) < 0) {
57832786Smckusick 		perror("ioctl (WDINFO)");
57930380Smckusick 		fatal("%s: can't rewrite disk label", s);
58010762Ssam 	}
58130446Skarels #if vax
58230446Skarels 	if (lp->d_type == DTYPE_SMD && lp->d_flags & D_BADSECT) {
58330446Skarels 		register i;
58430691Skarels 		int cfd;
58530446Skarels 		daddr_t alt;
58630691Skarels 		char specname[64];
58730691Skarels 		char blk[1024];
58831045Ssam 		char *cp;
58930446Skarels 
59030691Skarels 		/*
59130691Skarels 		 * Make name for 'c' partition.
59230691Skarels 		 */
59330691Skarels 		strcpy(specname, s);
59430691Skarels 		cp = specname + strlen(specname) - 1;
59530691Skarels 		if (!isdigit(*cp))
59630691Skarels 			*cp = 'c';
59730691Skarels 		cfd = open(specname, O_WRONLY);
59830691Skarels 		if (cfd < 0) {
59930691Skarels 			perror(specname);
60030691Skarels 			exit(2);
60130691Skarels 		}
60230691Skarels 		bzero(blk, sizeof(blk));
60330691Skarels 		*(struct disklabel *)(blk + LABELOFFSET) = *lp;
60430446Skarels 		alt = lp->d_ncylinders * lp->d_secpercyl - lp->d_nsectors;
60530446Skarels 		for (i = 1; i < 11 && i < lp->d_nsectors; i += 2) {
60631680Skarels 			if (lseek(cfd, (off_t)(alt + i) * lp->d_secsize, L_SET) == -1) {
60731680Skarels 				perror("lseek to badsector area");
60831680Skarels 				exit(30);
60931680Skarels 			}
61030691Skarels 			if (write(cfd, blk, lp->d_secsize) < lp->d_secsize) {
61130446Skarels 				int oerrno = errno;
61230446Skarels 				fprintf(stderr, "alternate label %d ", i/2);
61330446Skarels 				errno = oerrno;
61430446Skarels 				perror("write");
61530446Skarels 			}
61630380Smckusick 		}
61730380Smckusick 	}
61830446Skarels #endif
61910762Ssam }
62010762Ssam 
62110762Ssam /*VARARGS*/
62210762Ssam fatal(fmt, arg1, arg2)
62310762Ssam 	char *fmt;
62410762Ssam {
62510762Ssam 
62611069Ssam 	fprintf(stderr, "newfs: ");
62710762Ssam 	fprintf(stderr, fmt, arg1, arg2);
62810762Ssam 	putc('\n', stderr);
62910762Ssam 	exit(10);
63010762Ssam }
631