xref: /illumos-gate/usr/src/cmd/fs.d/ufs/mkfs/mkfs.c (revision bbf21555)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5d1a180b0Smaheshvs  * Common Development and Distribution License (the "License").
6d1a180b0Smaheshvs  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
2123a1cceaSRoger A. Faulkner 
227c478bd9Sstevel@tonic-gate /*
2323a1cceaSRoger A. Faulkner  * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
27fe12dc75SToomas Soome /*	All Rights Reserved	*/
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate /*
307c478bd9Sstevel@tonic-gate  * University Copyright- Copyright (c) 1982, 1986, 1988
317c478bd9Sstevel@tonic-gate  * The Regents of the University of California
327c478bd9Sstevel@tonic-gate  * All Rights Reserved
337c478bd9Sstevel@tonic-gate  *
347c478bd9Sstevel@tonic-gate  * University Acknowledgment- Portions of this document are derived from
357c478bd9Sstevel@tonic-gate  * software developed by the University of California, Berkeley, and its
367c478bd9Sstevel@tonic-gate  * contributors.
377c478bd9Sstevel@tonic-gate  */
387c478bd9Sstevel@tonic-gate 
396a1a5bb9SJohn Levon /*
406a1a5bb9SJohn Levon  * Copyright (c) 2018, Joyent, Inc.
416a1a5bb9SJohn Levon  */
426a1a5bb9SJohn Levon 
437c478bd9Sstevel@tonic-gate /*
447c478bd9Sstevel@tonic-gate  * The maximum supported file system size (in sectors) is the
457c478bd9Sstevel@tonic-gate  * number of frags that can be represented in an int32_t field
467c478bd9Sstevel@tonic-gate  * (INT_MAX) times the maximum number of sectors per frag.  Since
477c478bd9Sstevel@tonic-gate  * the maximum frag size is MAXBSIZE, the maximum number of sectors
487c478bd9Sstevel@tonic-gate  * per frag is MAXBSIZE/DEV_BSIZE.
497c478bd9Sstevel@tonic-gate  */
507c478bd9Sstevel@tonic-gate #define	FS_MAX	(((diskaddr_t)INT_MAX) * (MAXBSIZE/DEV_BSIZE))
517c478bd9Sstevel@tonic-gate 
527c478bd9Sstevel@tonic-gate /*
537c478bd9Sstevel@tonic-gate  * make file system for cylinder-group style file systems
547c478bd9Sstevel@tonic-gate  *
557c478bd9Sstevel@tonic-gate  * usage:
567c478bd9Sstevel@tonic-gate  *
577c478bd9Sstevel@tonic-gate  *    mkfs [-F FSType] [-V] [-G [-P]] [-M dirname] [-m] [options]
587c478bd9Sstevel@tonic-gate  *	[-o specific_options]  special size
597c478bd9Sstevel@tonic-gate  *	[nsect ntrack bsize fsize cpg	minfree	rps nbpi opt apc rotdelay
607c478bd9Sstevel@tonic-gate  *	  2     3      4     5     6	7	8   9	 10  11  12
617c478bd9Sstevel@tonic-gate  *	nrpos maxcontig mtb]
627c478bd9Sstevel@tonic-gate  *	13    14	15
637c478bd9Sstevel@tonic-gate  *
647c478bd9Sstevel@tonic-gate  *  where specific_options are:
657c478bd9Sstevel@tonic-gate  *	N - no create
667c478bd9Sstevel@tonic-gate  *	nsect - The number of sectors per track
677c478bd9Sstevel@tonic-gate  *	ntrack - The number of tracks per cylinder
687c478bd9Sstevel@tonic-gate  *	bsize - block size
697c478bd9Sstevel@tonic-gate  *	fragsize - fragment size
707c478bd9Sstevel@tonic-gate  *	cgsize - The number of disk cylinders per cylinder group.
71fe12dc75SToomas Soome  *	free - minimum free space
727c478bd9Sstevel@tonic-gate  *	rps - rotational speed (rev/sec).
737c478bd9Sstevel@tonic-gate  *	nbpi - number of data bytes per allocated inode
747c478bd9Sstevel@tonic-gate  *	opt - optimization (space, time)
757c478bd9Sstevel@tonic-gate  *	apc - number of alternates
767c478bd9Sstevel@tonic-gate  *	gap - gap size
777c478bd9Sstevel@tonic-gate  *	nrpos - number of rotational positions
787c478bd9Sstevel@tonic-gate  *	maxcontig - maximum number of logical blocks that will be
797c478bd9Sstevel@tonic-gate  *		allocated contiguously before inserting rotational delay
807c478bd9Sstevel@tonic-gate  *	mtb - if "y", set up file system for eventual growth to over a
817c478bd9Sstevel@tonic-gate  *		a terabyte
827c478bd9Sstevel@tonic-gate  * -P Do not grow the file system, but print on stdout the maximal
837c478bd9Sstevel@tonic-gate  *    size in sectors to which the file system can be increased. The calculated
847c478bd9Sstevel@tonic-gate  *    size is limited by the value provided by the operand size.
857c478bd9Sstevel@tonic-gate  *
867c478bd9Sstevel@tonic-gate  * Note that -P is a project-private interface and together with -G intended
877c478bd9Sstevel@tonic-gate  * to be used only by the growfs script. It is therefore purposely not
887c478bd9Sstevel@tonic-gate  * documented in the man page.
897c478bd9Sstevel@tonic-gate  * The -P option is covered by PSARC case 2003/422.
907c478bd9Sstevel@tonic-gate  */
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate /*
937c478bd9Sstevel@tonic-gate  * The following constants set the defaults used for the number
947c478bd9Sstevel@tonic-gate  * of sectors/track (fs_nsect), and number of tracks/cyl (fs_ntrak).
957c478bd9Sstevel@tonic-gate  *
967c478bd9Sstevel@tonic-gate  *			NSECT		NTRAK
977c478bd9Sstevel@tonic-gate  *	72MB CDC	18		9
987c478bd9Sstevel@tonic-gate  *	30MB CDC	18		5
997c478bd9Sstevel@tonic-gate  *	720KB Diskette	9		2
1006451fdbcSvsakar  *
1016451fdbcSvsakar  * However the defaults will be different for disks larger than CHSLIMIT.
1027c478bd9Sstevel@tonic-gate  */
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate #define	DFLNSECT	32
1057c478bd9Sstevel@tonic-gate #define	DFLNTRAK	16
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate /*
1086451fdbcSvsakar  * The following default sectors and tracks values are used for
1096451fdbcSvsakar  * non-efi disks that are larger than the CHS addressing limit. The
1106451fdbcSvsakar  * existing default cpg of 16 (DESCPG) holds good for larger disks too.
1117c478bd9Sstevel@tonic-gate  */
1126451fdbcSvsakar #define	DEF_SECTORS_EFI	128
1136451fdbcSvsakar #define	DEF_TRACKS_EFI	48
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate /*
1167c478bd9Sstevel@tonic-gate  * The maximum number of cylinders in a group depends upon how much
1177c478bd9Sstevel@tonic-gate  * information can be stored on a single cylinder. The default is to
1187c478bd9Sstevel@tonic-gate  * use 16 cylinders per group.  This is effectively tradition - it was
1197c478bd9Sstevel@tonic-gate  * the largest value acceptable under SunOs 4.1
1207c478bd9Sstevel@tonic-gate  */
1217c478bd9Sstevel@tonic-gate #define	DESCPG		16	/* desired fs_cpg */
1227c478bd9Sstevel@tonic-gate 
1236451fdbcSvsakar /*
1246451fdbcSvsakar  * The following two constants set the default block and fragment sizes.
1256451fdbcSvsakar  * Both constants must be a power of 2 and meet the following constraints:
1266451fdbcSvsakar  *	MINBSIZE <= DESBLKSIZE <= MAXBSIZE
1276451fdbcSvsakar  *	DEV_BSIZE <= DESFRAGSIZE <= DESBLKSIZE
1286451fdbcSvsakar  *	DESBLKSIZE / DESFRAGSIZE <= 8
1296451fdbcSvsakar  */
1306451fdbcSvsakar #define	DESBLKSIZE	8192
1316451fdbcSvsakar #define	DESFRAGSIZE	1024
1326451fdbcSvsakar 
1337c478bd9Sstevel@tonic-gate /*
1347c478bd9Sstevel@tonic-gate  * MINFREE gives the minimum acceptable percentage of file system
1357c478bd9Sstevel@tonic-gate  * blocks which may be free. If the freelist drops below this level
1367c478bd9Sstevel@tonic-gate  * only the superuser may continue to allocate blocks. This may
1377c478bd9Sstevel@tonic-gate  * be set to 0 if no reserve of free blocks is deemed necessary,
1387c478bd9Sstevel@tonic-gate  * however throughput drops by fifty percent if the file system
1397c478bd9Sstevel@tonic-gate  * is run at between 90% and 100% full; thus the default value of
1407c478bd9Sstevel@tonic-gate  * fs_minfree is 10%. With 10% free space, fragmentation is not a
1417c478bd9Sstevel@tonic-gate  * problem, so we choose to optimize for time.
1427c478bd9Sstevel@tonic-gate  */
1437c478bd9Sstevel@tonic-gate #define	MINFREE		10
1447c478bd9Sstevel@tonic-gate #define	DEFAULTOPT	FS_OPTTIME
1457c478bd9Sstevel@tonic-gate 
1467c478bd9Sstevel@tonic-gate /*
1477c478bd9Sstevel@tonic-gate  * ROTDELAY gives the minimum number of milliseconds to initiate
1487c478bd9Sstevel@tonic-gate  * another disk transfer on the same cylinder. It is no longer used
1497c478bd9Sstevel@tonic-gate  * and will always default to 0.
1507c478bd9Sstevel@tonic-gate  */
1517c478bd9Sstevel@tonic-gate #define	ROTDELAY	0
1527c478bd9Sstevel@tonic-gate 
1537c478bd9Sstevel@tonic-gate /*
1547c478bd9Sstevel@tonic-gate  * MAXBLKPG determines the maximum number of data blocks which are
1557c478bd9Sstevel@tonic-gate  * placed in a single cylinder group. The default is one indirect
1567c478bd9Sstevel@tonic-gate  * block worth of data blocks.
1577c478bd9Sstevel@tonic-gate  */
1587c478bd9Sstevel@tonic-gate #define	MAXBLKPG(bsize)	((bsize) / sizeof (daddr32_t))
1597c478bd9Sstevel@tonic-gate 
1607c478bd9Sstevel@tonic-gate /*
1617c478bd9Sstevel@tonic-gate  * Each file system has a number of inodes statically allocated.
1627c478bd9Sstevel@tonic-gate  * We allocate one inode slot per NBPI bytes, expecting this
1637c478bd9Sstevel@tonic-gate  * to be far more than we will ever need.
1647c478bd9Sstevel@tonic-gate  */
1657c478bd9Sstevel@tonic-gate #define	NBPI		2048	/* Number Bytes Per Inode */
1667c478bd9Sstevel@tonic-gate #define	MTB_NBPI	(MB)	/* Number Bytes Per Inode for multi-terabyte */
1677c478bd9Sstevel@tonic-gate 
1687c478bd9Sstevel@tonic-gate /*
1697c478bd9Sstevel@tonic-gate  * Disks are assumed to rotate at 60HZ, unless otherwise specified.
1707c478bd9Sstevel@tonic-gate  */
1717c478bd9Sstevel@tonic-gate #define	DEFHZ		60
1727c478bd9Sstevel@tonic-gate 
1737c478bd9Sstevel@tonic-gate /*
1747c478bd9Sstevel@tonic-gate  * Cylinder group related limits.
1757c478bd9Sstevel@tonic-gate  *
1767c478bd9Sstevel@tonic-gate  * For each cylinder we keep track of the availability of blocks at different
1777c478bd9Sstevel@tonic-gate  * rotational positions, so that we can lay out the data to be picked
1787c478bd9Sstevel@tonic-gate  * up with minimum rotational latency.  NRPOS is the number of rotational
1797c478bd9Sstevel@tonic-gate  * positions which we distinguish.  With NRPOS 8 the resolution of our
1807c478bd9Sstevel@tonic-gate  * summary information is 2ms for a typical 3600 rpm drive.
1817c478bd9Sstevel@tonic-gate  */
1827c478bd9Sstevel@tonic-gate #define	NRPOS		8	/* number distinct rotational positions */
1837c478bd9Sstevel@tonic-gate 
1846451fdbcSvsakar #ifdef DEBUG
1856451fdbcSvsakar #define	dprintf(x)	printf x
1866451fdbcSvsakar #else
1876451fdbcSvsakar #define	dprintf(x)
1886451fdbcSvsakar #endif
1896451fdbcSvsakar 
1906451fdbcSvsakar /*
1916451fdbcSvsakar  * For the -N option, when calculating the backup superblocks, do not print
1926451fdbcSvsakar  * them if we are not really sure. We may have to try an alternate method of
1936451fdbcSvsakar  * arriving at the superblocks. So defer printing till a handful of superblocks
1946451fdbcSvsakar  * look good.
1956451fdbcSvsakar  */
1966451fdbcSvsakar #define	tprintf(x)	if (Nflag && retry) \
1976d24e334Svsakar 				(void) strncat(tmpbuf, x, strlen(x)); \
1986451fdbcSvsakar 			else \
1996451fdbcSvsakar 				(void) fprintf(stderr, x);
2006451fdbcSvsakar 
2016451fdbcSvsakar #define	ALTSB		32	/* Location of first backup superblock */
2026451fdbcSvsakar 
2037c478bd9Sstevel@tonic-gate /*
2047c478bd9Sstevel@tonic-gate  * range_check "user_supplied" flag values.
2057c478bd9Sstevel@tonic-gate  */
2067c478bd9Sstevel@tonic-gate #define	RC_DEFAULT	0
2077c478bd9Sstevel@tonic-gate #define	RC_KEYWORD	1
2087c478bd9Sstevel@tonic-gate #define	RC_POSITIONAL	2
2097c478bd9Sstevel@tonic-gate 
210303bf60bSsdebnath /*
211303bf60bSsdebnath  * ufs hole
212303bf60bSsdebnath  */
213303bf60bSsdebnath #define	UFS_HOLE	-1
214303bf60bSsdebnath 
2157c478bd9Sstevel@tonic-gate #ifndef	STANDALONE
2167c478bd9Sstevel@tonic-gate #include	<stdio.h>
2177c478bd9Sstevel@tonic-gate #include	<sys/mnttab.h>
2187c478bd9Sstevel@tonic-gate #endif
2197c478bd9Sstevel@tonic-gate 
2207c478bd9Sstevel@tonic-gate #include	<stdlib.h>
2217c478bd9Sstevel@tonic-gate #include	<unistd.h>
2227c478bd9Sstevel@tonic-gate #include	<malloc.h>
2237c478bd9Sstevel@tonic-gate #include	<string.h>
2247c478bd9Sstevel@tonic-gate #include	<strings.h>
2257c478bd9Sstevel@tonic-gate #include	<ctype.h>
2267c478bd9Sstevel@tonic-gate #include	<errno.h>
2277c478bd9Sstevel@tonic-gate #include	<sys/param.h>
2287c478bd9Sstevel@tonic-gate #include	<time.h>
2297c478bd9Sstevel@tonic-gate #include	<sys/types.h>
2307c478bd9Sstevel@tonic-gate #include	<sys/sysmacros.h>
2317c478bd9Sstevel@tonic-gate #include	<sys/vnode.h>
2327c478bd9Sstevel@tonic-gate #include	<sys/fs/ufs_fsdir.h>
2337c478bd9Sstevel@tonic-gate #include	<sys/fs/ufs_inode.h>
2347c478bd9Sstevel@tonic-gate #include	<sys/fs/ufs_fs.h>
2357c478bd9Sstevel@tonic-gate #include	<sys/fs/ufs_log.h>
2367c478bd9Sstevel@tonic-gate #include	<sys/mntent.h>
2377c478bd9Sstevel@tonic-gate #include	<sys/filio.h>
2387c478bd9Sstevel@tonic-gate #include	<limits.h>
2397c478bd9Sstevel@tonic-gate #include	<sys/int_const.h>
2407c478bd9Sstevel@tonic-gate #include	<signal.h>
2417c478bd9Sstevel@tonic-gate #include	<sys/efi_partition.h>
2426a1a5bb9SJohn Levon #include	<fslib.h>
2437c478bd9Sstevel@tonic-gate #include	"roll_log.h"
2447c478bd9Sstevel@tonic-gate 
2457c478bd9Sstevel@tonic-gate #define	bcopy(f, t, n)    (void) memcpy(t, f, n)
2467c478bd9Sstevel@tonic-gate #define	bzero(s, n)	(void) memset(s, 0, n)
2477c478bd9Sstevel@tonic-gate #define	bcmp(s, d, n)	memcmp(s, d, n)
2487c478bd9Sstevel@tonic-gate 
2497c478bd9Sstevel@tonic-gate #define	index(s, r)	strchr(s, r)
2507c478bd9Sstevel@tonic-gate #define	rindex(s, r)	strrchr(s, r)
2517c478bd9Sstevel@tonic-gate 
2527c478bd9Sstevel@tonic-gate #include	<sys/stat.h>
2537c478bd9Sstevel@tonic-gate #include	<sys/statvfs.h>
2547c478bd9Sstevel@tonic-gate #include	<locale.h>
2557c478bd9Sstevel@tonic-gate #include	<fcntl.h>
256fe12dc75SToomas Soome #include	<sys/isa_defs.h>	/* for ENDIAN defines */
2577c478bd9Sstevel@tonic-gate #include	<sys/vtoc.h>
2587c478bd9Sstevel@tonic-gate 
2597c478bd9Sstevel@tonic-gate #include	<sys/dkio.h>
2607c478bd9Sstevel@tonic-gate #include	<sys/asynch.h>
2617c478bd9Sstevel@tonic-gate 
2627c478bd9Sstevel@tonic-gate extern offset_t	llseek();
2637c478bd9Sstevel@tonic-gate extern char	*getfullblkname();
2647c478bd9Sstevel@tonic-gate extern long	lrand48();
2657c478bd9Sstevel@tonic-gate 
2667c478bd9Sstevel@tonic-gate extern int	optind;
2677c478bd9Sstevel@tonic-gate extern char	*optarg;
2687c478bd9Sstevel@tonic-gate 
2697c478bd9Sstevel@tonic-gate 
2707c478bd9Sstevel@tonic-gate /*
2717c478bd9Sstevel@tonic-gate  * The size of a cylinder group is calculated by CGSIZE. The maximum size
2727c478bd9Sstevel@tonic-gate  * is limited by the fact that cylinder groups are at most one block.
2737c478bd9Sstevel@tonic-gate  * Its size is derived from the size of the maps maintained in the
2747c478bd9Sstevel@tonic-gate  * cylinder group and the (struct cg) size.
2757c478bd9Sstevel@tonic-gate  */
2767c478bd9Sstevel@tonic-gate #define	CGSIZE(fs) \
2777c478bd9Sstevel@tonic-gate 	/* base cg		*/ (sizeof (struct cg) + \
2787c478bd9Sstevel@tonic-gate 	/* blktot size	*/ (fs)->fs_cpg * sizeof (long) + \
2797c478bd9Sstevel@tonic-gate 	/* blks size	*/ (fs)->fs_cpg * (fs)->fs_nrpos * sizeof (short) + \
2807c478bd9Sstevel@tonic-gate 	/* inode map	*/ howmany((fs)->fs_ipg, NBBY) + \
2817c478bd9Sstevel@tonic-gate 	/* block map */ howmany((fs)->fs_cpg * (fs)->fs_spc / NSPF(fs), NBBY))
2827c478bd9Sstevel@tonic-gate 
2837c478bd9Sstevel@tonic-gate /*
2847c478bd9Sstevel@tonic-gate  * We limit the size of the inode map to be no more than a
2857c478bd9Sstevel@tonic-gate  * third of the cylinder group space, since we must leave at
2867c478bd9Sstevel@tonic-gate  * least an equal amount of space for the block map.
2877c478bd9Sstevel@tonic-gate  *
2887c478bd9Sstevel@tonic-gate  * N.B.: MAXIpG must be a multiple of INOPB(fs).
2897c478bd9Sstevel@tonic-gate  */
2907c478bd9Sstevel@tonic-gate #define	MAXIpG(fs)	roundup((fs)->fs_bsize * NBBY / 3, INOPB(fs))
2917c478bd9Sstevel@tonic-gate 
2927c478bd9Sstevel@tonic-gate /*
2937c478bd9Sstevel@tonic-gate  * Same as MAXIpG, but parameterized by the block size (b) and the
2947c478bd9Sstevel@tonic-gate  * cylinder group divisor (d), which is the reciprocal of the fraction of the
2957c478bd9Sstevel@tonic-gate  * cylinder group overhead block that is used for the inode map.  So for
2967c478bd9Sstevel@tonic-gate  * example, if d = 5, the macro's computation assumes that 1/5 of the
2977c478bd9Sstevel@tonic-gate  * cylinder group overhead block can be dedicated to the inode map.
2987c478bd9Sstevel@tonic-gate  */
2997c478bd9Sstevel@tonic-gate #define	MAXIpG_B(b, d)	roundup((b) * NBBY / (d), (b) / sizeof (struct dinode))
3007c478bd9Sstevel@tonic-gate 
3017c478bd9Sstevel@tonic-gate #define	UMASK		0755
3027c478bd9Sstevel@tonic-gate #define	MAXINOPB	(MAXBSIZE / sizeof (struct dinode))
3037c478bd9Sstevel@tonic-gate #define	POWEROF2(num)	(((num) & ((num) - 1)) == 0)
3047c478bd9Sstevel@tonic-gate #define	MB		(1024*1024)
3057c478bd9Sstevel@tonic-gate #define	BETWEEN(x, l, h)	((x) >= (l) && (x) <= (h))
3067c478bd9Sstevel@tonic-gate 
3077c478bd9Sstevel@tonic-gate /*
3087c478bd9Sstevel@tonic-gate  * Used to set the inode generation number. Since both inodes and dinodes
3097c478bd9Sstevel@tonic-gate  * are dealt with, we really need a pointer to an icommon here.
3107c478bd9Sstevel@tonic-gate  */
3117c478bd9Sstevel@tonic-gate #define	IRANDOMIZE(icp)	(icp)->ic_gen = lrand48();
3127c478bd9Sstevel@tonic-gate 
3137c478bd9Sstevel@tonic-gate /*
3147c478bd9Sstevel@tonic-gate  * Flags for number()
3157c478bd9Sstevel@tonic-gate  */
3167c478bd9Sstevel@tonic-gate #define	ALLOW_PERCENT	0x01	/* allow trailing `%' on number */
3177c478bd9Sstevel@tonic-gate #define	ALLOW_MS1	0x02	/* allow trailing `ms', state 1 */
3187c478bd9Sstevel@tonic-gate #define	ALLOW_MS2	0x04	/* allow trailing `ms', state 2 */
3197c478bd9Sstevel@tonic-gate #define	ALLOW_END_ONLY	0x08	/* must be at end of number & suffixes */
3207c478bd9Sstevel@tonic-gate 
3217c478bd9Sstevel@tonic-gate #define	MAXAIO	1000	/* maximum number of outstanding I/O's we'll manage */
3227c478bd9Sstevel@tonic-gate #define	BLOCK	1	/* block in aiowait */
3237c478bd9Sstevel@tonic-gate #define	NOBLOCK	0	/* don't block in aiowait */
3247c478bd9Sstevel@tonic-gate 
3257c478bd9Sstevel@tonic-gate #define	RELEASE 1	/* free an aio buffer after use */
3267c478bd9Sstevel@tonic-gate #define	SAVE	0	/* don't free the buffer */
3277c478bd9Sstevel@tonic-gate 
3287c478bd9Sstevel@tonic-gate typedef struct aio_trans {
3297c478bd9Sstevel@tonic-gate 	aio_result_t resultbuf;
3307c478bd9Sstevel@tonic-gate 	diskaddr_t bno;
3317c478bd9Sstevel@tonic-gate 	char *buffer;
3327c478bd9Sstevel@tonic-gate 	int size;
3337c478bd9Sstevel@tonic-gate 	int release;
3347c478bd9Sstevel@tonic-gate 	struct aio_trans *next;
3357c478bd9Sstevel@tonic-gate } aio_trans;
3367c478bd9Sstevel@tonic-gate 
3377c478bd9Sstevel@tonic-gate typedef struct aio_results {
3387c478bd9Sstevel@tonic-gate 	int max;
3397c478bd9Sstevel@tonic-gate 	int outstanding;
3407c478bd9Sstevel@tonic-gate 	int maxpend;
3417c478bd9Sstevel@tonic-gate 	aio_trans *trans;
3427c478bd9Sstevel@tonic-gate } aio_results;
3437c478bd9Sstevel@tonic-gate 
3447c478bd9Sstevel@tonic-gate int aio_inited = 0;
3457c478bd9Sstevel@tonic-gate aio_results results;
3467c478bd9Sstevel@tonic-gate 
3477c478bd9Sstevel@tonic-gate /*
3487c478bd9Sstevel@tonic-gate  * Allow up to MAXBUF aio requests that each have a unique buffer.
3497c478bd9Sstevel@tonic-gate  * More aio's might be done, but not using memory through the getbuf()
3507c478bd9Sstevel@tonic-gate  * interface.  This can be raised, but you run into the potential of
3517c478bd9Sstevel@tonic-gate  * using more memory than is physically available on the machine,
3527c478bd9Sstevel@tonic-gate  * and if you start swapping, you can forget about performance.
3537c478bd9Sstevel@tonic-gate  * To prevent this, we also limit the total memory used for a given
3547c478bd9Sstevel@tonic-gate  * type of buffer to MAXBUFMEM.
3557c478bd9Sstevel@tonic-gate  *
3567c478bd9Sstevel@tonic-gate  * Tests indicate a cylinder group's worth of inodes takes:
3577c478bd9Sstevel@tonic-gate  *
3587c478bd9Sstevel@tonic-gate  *	NBPI	Size of Inode Buffer
3597c478bd9Sstevel@tonic-gate  *	 2k	1688k
3607c478bd9Sstevel@tonic-gate  *	 8k	 424k
3617c478bd9Sstevel@tonic-gate  *
3627c478bd9Sstevel@tonic-gate  * initcg() stores all the inodes for a cylinder group in one buffer,
3637c478bd9Sstevel@tonic-gate  * so allowing 20 buffers could take 32 MB if not limited by MAXBUFMEM.
3647c478bd9Sstevel@tonic-gate  */
3657c478bd9Sstevel@tonic-gate #define	MAXBUF		20
3667c478bd9Sstevel@tonic-gate #define	MAXBUFMEM	(8 * 1024 * 1024)
3677c478bd9Sstevel@tonic-gate 
3687c478bd9Sstevel@tonic-gate /*
3697c478bd9Sstevel@tonic-gate  * header information for buffers managed by getbuf() and freebuf()
3707c478bd9Sstevel@tonic-gate  */
3717c478bd9Sstevel@tonic-gate typedef struct bufhdr {
3727c478bd9Sstevel@tonic-gate 	struct bufhdr *head;
3737c478bd9Sstevel@tonic-gate 	struct bufhdr *next;
3747c478bd9Sstevel@tonic-gate } bufhdr;
3757c478bd9Sstevel@tonic-gate 
3767c478bd9Sstevel@tonic-gate int bufhdrsize;
3777c478bd9Sstevel@tonic-gate 
3787c478bd9Sstevel@tonic-gate bufhdr inodebuf = { NULL, NULL };
3797c478bd9Sstevel@tonic-gate bufhdr cgsumbuf = { NULL, NULL };
3807c478bd9Sstevel@tonic-gate 
3817c478bd9Sstevel@tonic-gate #define	SECTORS_PER_TERABYTE	(1LL << 31)
3827c478bd9Sstevel@tonic-gate /*
3837c478bd9Sstevel@tonic-gate  * The following constant specifies an upper limit for file system size
3847c478bd9Sstevel@tonic-gate  * that is actually a lot bigger than we expect to support with UFS. (Since
3857c478bd9Sstevel@tonic-gate  * it's specified in sectors, the file system size would be 2**44 * 512,
3867c478bd9Sstevel@tonic-gate  * which is 2**53, which is 8192 Terabytes.)  However, it's useful
3877c478bd9Sstevel@tonic-gate  * for checking the basic sanity of a size value that is input on the
3887c478bd9Sstevel@tonic-gate  * command line.
3897c478bd9Sstevel@tonic-gate  */
3907c478bd9Sstevel@tonic-gate #define	FS_SIZE_UPPER_LIMIT	0x100000000000LL
3917c478bd9Sstevel@tonic-gate 
3927c478bd9Sstevel@tonic-gate /*
3937c478bd9Sstevel@tonic-gate  * Forward declarations
3947c478bd9Sstevel@tonic-gate  */
3957c478bd9Sstevel@tonic-gate static char *getbuf(bufhdr *bufhead, int size);
3967c478bd9Sstevel@tonic-gate static void freebuf(char *buf);
3977c478bd9Sstevel@tonic-gate static void freetrans(aio_trans *transp);
3987c478bd9Sstevel@tonic-gate static aio_trans *get_aiop();
3997c478bd9Sstevel@tonic-gate static aio_trans *wait_for_write(int block);
4007c478bd9Sstevel@tonic-gate static void initcg(int cylno);
4017c478bd9Sstevel@tonic-gate static void fsinit();
4027c478bd9Sstevel@tonic-gate static int makedir(struct direct *protodir, int entries);
4037c478bd9Sstevel@tonic-gate static void iput(struct inode *ip);
4047c478bd9Sstevel@tonic-gate static void rdfs(diskaddr_t bno, int size, char *bf);
4057c478bd9Sstevel@tonic-gate static void wtfs(diskaddr_t bno, int size, char *bf);
4067c478bd9Sstevel@tonic-gate static void awtfs(diskaddr_t bno, int size, char *bf, int release);
4077c478bd9Sstevel@tonic-gate static void wtfs_breakup(diskaddr_t bno, int size, char *bf);
4087c478bd9Sstevel@tonic-gate static int isblock(struct fs *fs, unsigned char *cp, int h);
4097c478bd9Sstevel@tonic-gate static void clrblock(struct fs *fs, unsigned char *cp, int h);
4107c478bd9Sstevel@tonic-gate static void setblock(struct fs *fs, unsigned char *cp, int h);
411f45bbb21SToomas Soome static void usage(void) __NORETURN;
4127c478bd9Sstevel@tonic-gate static void dump_fscmd(char *fsys, int fsi);
4137c478bd9Sstevel@tonic-gate static uint64_t number(uint64_t d_value, char *param, int flags);
4147c478bd9Sstevel@tonic-gate static int match(char *s);
4157c478bd9Sstevel@tonic-gate static char checkopt(char *optim);
4167c478bd9Sstevel@tonic-gate static char checkmtb(char *mtbarg);
4177c478bd9Sstevel@tonic-gate static void range_check(long *varp, char *name, long minimum,
4187c478bd9Sstevel@tonic-gate     long maximum, long def_val, int user_supplied);
4197c478bd9Sstevel@tonic-gate static void range_check_64(uint64_t *varp, char *name, uint64_t minimum,
4207c478bd9Sstevel@tonic-gate     uint64_t maximum, uint64_t def_val, int user_supplied);
4217c478bd9Sstevel@tonic-gate static daddr32_t alloc(int size, int mode);
4227c478bd9Sstevel@tonic-gate static diskaddr_t get_max_size(int fd);
4237c478bd9Sstevel@tonic-gate static long get_max_track_size(int fd);
4247c478bd9Sstevel@tonic-gate static void block_sigint(sigset_t *old_mask);
4257c478bd9Sstevel@tonic-gate static void unblock_sigint(sigset_t *old_mask);
4267c478bd9Sstevel@tonic-gate static void recover_from_sigint(int signum);
4277c478bd9Sstevel@tonic-gate static int confirm_abort(void);
42823a1cceaSRoger A. Faulkner static int getaline(FILE *fp, char *loc, int maxlen);
4297c478bd9Sstevel@tonic-gate static void flush_writes(void);
4307c478bd9Sstevel@tonic-gate static long compute_maxcpg(long, long, long, long, long);
4317c478bd9Sstevel@tonic-gate static int in_64bit_mode(void);
4327c478bd9Sstevel@tonic-gate static int validate_size(int fd, diskaddr_t size);
433355d6bb5Sswilcox static void dump_sblock(void);
4347c478bd9Sstevel@tonic-gate 
435140e9cb2Sprabahar /*
436140e9cb2Sprabahar  * Workaround for mkfs to function properly on disks attached to XMIT 2.X
437140e9cb2Sprabahar  * controller. If the address is not aligned at 8 byte boundary, mkfs on
438140e9cb2Sprabahar  * disks attached to XMIT 2.X controller exhibts un-predictable behaviour.
439140e9cb2Sprabahar  */
440140e9cb2Sprabahar #define	XMIT_2_X_ALIGN	8
441140e9cb2Sprabahar #pragma	align XMIT_2_X_ALIGN(fsun, altfsun, cgun)
442140e9cb2Sprabahar 
4437c478bd9Sstevel@tonic-gate union {
4447c478bd9Sstevel@tonic-gate 	struct fs fs;
4457c478bd9Sstevel@tonic-gate 	char pad[SBSIZE];
4466451fdbcSvsakar } fsun, altfsun;
4477c478bd9Sstevel@tonic-gate #define	sblock	fsun.fs
4486451fdbcSvsakar #define	altsblock	altfsun.fs
4497c478bd9Sstevel@tonic-gate 
4507c478bd9Sstevel@tonic-gate struct	csum *fscs;
4517c478bd9Sstevel@tonic-gate 
4527c478bd9Sstevel@tonic-gate union cgun {
4537c478bd9Sstevel@tonic-gate 	struct cg cg;
4547c478bd9Sstevel@tonic-gate 	char pad[MAXBSIZE];
4557c478bd9Sstevel@tonic-gate } cgun;
4567c478bd9Sstevel@tonic-gate 
4577c478bd9Sstevel@tonic-gate #define	acg	cgun.cg
4587c478bd9Sstevel@tonic-gate /*
4597c478bd9Sstevel@tonic-gate  * Size of screen in cols in which to fit output
4607c478bd9Sstevel@tonic-gate  */
4617c478bd9Sstevel@tonic-gate #define	WIDTH	80
4627c478bd9Sstevel@tonic-gate 
4637c478bd9Sstevel@tonic-gate struct dinode zino[MAXBSIZE / sizeof (struct dinode)];
4647c478bd9Sstevel@tonic-gate 
4657c478bd9Sstevel@tonic-gate /*
4667c478bd9Sstevel@tonic-gate  * file descriptors used for rdfs(fsi) and wtfs(fso).
4677c478bd9Sstevel@tonic-gate  * Initialized to an illegal file descriptor number.
4687c478bd9Sstevel@tonic-gate  */
4697c478bd9Sstevel@tonic-gate int	fsi = -1;
4707c478bd9Sstevel@tonic-gate int	fso = -1;
4717c478bd9Sstevel@tonic-gate 
4727c478bd9Sstevel@tonic-gate /*
4737c478bd9Sstevel@tonic-gate  * The BIG parameter is machine dependent.  It should be a longlong integer
4747c478bd9Sstevel@tonic-gate  * constant that can be used by the number parser to check the validity
4757c478bd9Sstevel@tonic-gate  * of numeric parameters.
4767c478bd9Sstevel@tonic-gate  */
4777c478bd9Sstevel@tonic-gate 
4787c478bd9Sstevel@tonic-gate #define	BIG		0x7fffffffffffffffLL
4797c478bd9Sstevel@tonic-gate 
4807c478bd9Sstevel@tonic-gate /* Used to indicate to number() that a bogus value should cause us to exit */
4817c478bd9Sstevel@tonic-gate #define	NO_DEFAULT	LONG_MIN
4827c478bd9Sstevel@tonic-gate 
4836451fdbcSvsakar /*
4846451fdbcSvsakar  * INVALIDSBLIMIT is the number of bad backup superblocks that will be
4856451fdbcSvsakar  * tolerated before we decide to try arriving at a different set of them
4866451fdbcSvsakar  * using a different logic. This is applicable for non-EFI disks only.
4876451fdbcSvsakar  */
4886451fdbcSvsakar #define	INVALIDSBLIMIT	10
4896451fdbcSvsakar 
4907c478bd9Sstevel@tonic-gate /*
4917c478bd9Sstevel@tonic-gate  * The *_flag variables are used to indicate that the user specified
4927c478bd9Sstevel@tonic-gate  * the values, rather than that we made them up ourselves.  We can
4937c478bd9Sstevel@tonic-gate  * complain about the user giving us bogus values.
4947c478bd9Sstevel@tonic-gate  */
4957c478bd9Sstevel@tonic-gate 
4967c478bd9Sstevel@tonic-gate /* semi-constants */
4977c478bd9Sstevel@tonic-gate long	sectorsize = DEV_BSIZE;		/* bytes/sector from param.h */
4987c478bd9Sstevel@tonic-gate long	bbsize = BBSIZE;		/* boot block size */
4997c478bd9Sstevel@tonic-gate long	sbsize = SBSIZE;		/* superblock size */
5007c478bd9Sstevel@tonic-gate 
5017c478bd9Sstevel@tonic-gate /* parameters */
5027c478bd9Sstevel@tonic-gate diskaddr_t	fssize_db;		/* file system size in disk blocks */
5037c478bd9Sstevel@tonic-gate diskaddr_t	fssize_frag;		/* file system size in frags */
5047c478bd9Sstevel@tonic-gate long	cpg;				/* cylinders/cylinder group */
5057c478bd9Sstevel@tonic-gate int	cpg_flag = RC_DEFAULT;
5067c478bd9Sstevel@tonic-gate long	rotdelay = -1;			/* rotational delay between blocks */
5077c478bd9Sstevel@tonic-gate int	rotdelay_flag = RC_DEFAULT;
5087c478bd9Sstevel@tonic-gate long	maxcontig;			/* max contiguous blocks to allocate */
5097c478bd9Sstevel@tonic-gate int	maxcontig_flag = RC_DEFAULT;
5107c478bd9Sstevel@tonic-gate long	nsect = DFLNSECT;		/* sectors per track */
5117c478bd9Sstevel@tonic-gate int	nsect_flag = RC_DEFAULT;
5127c478bd9Sstevel@tonic-gate long	ntrack = DFLNTRAK;		/* tracks per cylinder group */
5137c478bd9Sstevel@tonic-gate int	ntrack_flag = RC_DEFAULT;
5147c478bd9Sstevel@tonic-gate long	bsize = DESBLKSIZE;		/* filesystem block size */
5157c478bd9Sstevel@tonic-gate int	bsize_flag = RC_DEFAULT;
516fe12dc75SToomas Soome long	fragsize = DESFRAGSIZE;		/* filesystem fragment size */
5177c478bd9Sstevel@tonic-gate int	fragsize_flag = RC_DEFAULT;
518fe12dc75SToomas Soome long	minfree = MINFREE;		/* fs_minfree */
5197c478bd9Sstevel@tonic-gate int	minfree_flag = RC_DEFAULT;
5207c478bd9Sstevel@tonic-gate long	rps = DEFHZ;			/* revolutions/second of drive */
5217c478bd9Sstevel@tonic-gate int	rps_flag = RC_DEFAULT;
5227c478bd9Sstevel@tonic-gate long	nbpi = NBPI;			/* number of bytes per inode */
5237c478bd9Sstevel@tonic-gate int	nbpi_flag = RC_DEFAULT;
5247c478bd9Sstevel@tonic-gate long	nrpos = NRPOS;			/* number of rotational positions */
5257c478bd9Sstevel@tonic-gate int	nrpos_flag = RC_DEFAULT;
5267c478bd9Sstevel@tonic-gate long	apc = 0;			/* alternate sectors per cylinder */
5277c478bd9Sstevel@tonic-gate int	apc_flag = RC_DEFAULT;
5287c478bd9Sstevel@tonic-gate char	opt = 't';			/* optimization style, `t' or `s' */
5297c478bd9Sstevel@tonic-gate char	mtb = 'n';			/* multi-terabyte format, 'y' or 'n' */
530d50c8f90Svsakar #define	DEFAULT_SECT_TRAK_CPG	(nsect_flag == RC_DEFAULT && \
531d50c8f90Svsakar 				ntrack_flag == RC_DEFAULT && \
532d50c8f90Svsakar 				cpg_flag == RC_DEFAULT)
5337c478bd9Sstevel@tonic-gate 
5347c478bd9Sstevel@tonic-gate long	debug = 0;			/* enable debugging output */
5357c478bd9Sstevel@tonic-gate 
5367c478bd9Sstevel@tonic-gate int	spc_flag = 0;			/* alternate sectors specified or */
5377c478bd9Sstevel@tonic-gate 					/* found */
5387c478bd9Sstevel@tonic-gate 
5397c478bd9Sstevel@tonic-gate /* global state */
5407c478bd9Sstevel@tonic-gate int	Nflag;		/* do not write to disk */
5417c478bd9Sstevel@tonic-gate int	mflag;		/* return the command line used to create this FS */
542355d6bb5Sswilcox int	rflag;		/* report the superblock in an easily-parsed form */
543355d6bb5Sswilcox int	Rflag;		/* dump the superblock in binary */
5447c478bd9Sstevel@tonic-gate char	*fsys;
5457c478bd9Sstevel@tonic-gate time_t	mkfstime;
5467c478bd9Sstevel@tonic-gate char	*string;
5476451fdbcSvsakar int	label_type;
5487c478bd9Sstevel@tonic-gate 
5497c478bd9Sstevel@tonic-gate /*
5507c478bd9Sstevel@tonic-gate  * logging support
5517c478bd9Sstevel@tonic-gate  */
5525f10ef69SYuri Pankov int	islog;			/* true if ufs logging is enabled */
5535f10ef69SYuri Pankov int	islogok;		/* true if ufs log state is good */
5545f10ef69SYuri Pankov int	waslog;			/* true when ufs logging disabled during grow */
5557c478bd9Sstevel@tonic-gate 
5567c478bd9Sstevel@tonic-gate /*
5577c478bd9Sstevel@tonic-gate  * growfs defines, globals, and forward references
5587c478bd9Sstevel@tonic-gate  */
5597c478bd9Sstevel@tonic-gate #define	NOTENOUGHSPACE 33
5607c478bd9Sstevel@tonic-gate int		grow;
561d50c8f90Svsakar #define	GROW_WITH_DEFAULT_TRAK	(grow && ntrack_flag == RC_DEFAULT)
562d50c8f90Svsakar 
5637c478bd9Sstevel@tonic-gate static int	Pflag;		/* probe to which size the fs can be grown */
5647c478bd9Sstevel@tonic-gate int		ismounted;
5657c478bd9Sstevel@tonic-gate char		*directory;
5667c478bd9Sstevel@tonic-gate diskaddr_t	grow_fssize;
5677c478bd9Sstevel@tonic-gate long		grow_fs_size;
5687c478bd9Sstevel@tonic-gate long		grow_fs_ncg;
5697c478bd9Sstevel@tonic-gate diskaddr_t		grow_fs_csaddr;
5707c478bd9Sstevel@tonic-gate long		grow_fs_cssize;
5717c478bd9Sstevel@tonic-gate int		grow_fs_clean;
5727c478bd9Sstevel@tonic-gate struct csum	*grow_fscs;
5737c478bd9Sstevel@tonic-gate diskaddr_t		grow_sifrag;
5747c478bd9Sstevel@tonic-gate int		test;
5757c478bd9Sstevel@tonic-gate int		testforce;
5767c478bd9Sstevel@tonic-gate diskaddr_t		testfrags;
5777c478bd9Sstevel@tonic-gate int		inlockexit;
5787c478bd9Sstevel@tonic-gate int		isbad;
5797c478bd9Sstevel@tonic-gate 
580f45bbb21SToomas Soome void		lockexit(int) __NORETURN;
5817c478bd9Sstevel@tonic-gate void		randomgeneration(void);
5827c478bd9Sstevel@tonic-gate void		checksummarysize(void);
5836451fdbcSvsakar int		checksblock(struct fs, int);
5847c478bd9Sstevel@tonic-gate void		growinit(char *);
5857c478bd9Sstevel@tonic-gate void		checkdev(char *, char  *);
5867c478bd9Sstevel@tonic-gate void		checkmount(struct mnttab *, char *);
5877c478bd9Sstevel@tonic-gate struct dinode	*gdinode(ino_t);
5887c478bd9Sstevel@tonic-gate int		csfraginrange(daddr32_t);
5897c478bd9Sstevel@tonic-gate struct csfrag	*findcsfrag(daddr32_t, struct csfrag **);
5907c478bd9Sstevel@tonic-gate void		checkindirect(ino_t, daddr32_t *, daddr32_t, int);
5917c478bd9Sstevel@tonic-gate void		addcsfrag(ino_t, daddr32_t, struct csfrag **);
5927c478bd9Sstevel@tonic-gate void		delcsfrag(daddr32_t, struct csfrag **);
5937c478bd9Sstevel@tonic-gate void		checkdirect(ino_t, daddr32_t *, daddr32_t *, int);
5947c478bd9Sstevel@tonic-gate void		findcsfragino(void);
5957c478bd9Sstevel@tonic-gate void		fixindirect(daddr32_t, int);
5967c478bd9Sstevel@tonic-gate void		fixdirect(caddr_t, daddr32_t, daddr32_t *, int);
5977c478bd9Sstevel@tonic-gate void		fixcsfragino(void);
5987c478bd9Sstevel@tonic-gate void		extendsummaryinfo(void);
5997c478bd9Sstevel@tonic-gate int		notenoughspace(void);
6007c478bd9Sstevel@tonic-gate void		unalloccsfragino(void);
6017c478bd9Sstevel@tonic-gate void		unalloccsfragfree(void);
6027c478bd9Sstevel@tonic-gate void		findcsfragfree(void);
6037c478bd9Sstevel@tonic-gate void		copycsfragino(void);
6047c478bd9Sstevel@tonic-gate void		rdcg(long);
6057c478bd9Sstevel@tonic-gate void		wtcg(void);
6067c478bd9Sstevel@tonic-gate void		flcg(void);
6077c478bd9Sstevel@tonic-gate void		allocfrags(long, daddr32_t *, long *);
6087c478bd9Sstevel@tonic-gate void		alloccsfragino(void);
6097c478bd9Sstevel@tonic-gate void		alloccsfragfree(void);
6107c478bd9Sstevel@tonic-gate void		freefrags(daddr32_t, long, long);
6117c478bd9Sstevel@tonic-gate int		findfreerange(long *, long *);
6127c478bd9Sstevel@tonic-gate void		resetallocinfo(void);
6137c478bd9Sstevel@tonic-gate void		extendcg(long);
6147c478bd9Sstevel@tonic-gate void		ulockfs(void);
6157c478bd9Sstevel@tonic-gate void		wlockfs(void);
6167c478bd9Sstevel@tonic-gate void		clockfs(void);
6177c478bd9Sstevel@tonic-gate void		wtsb(void);
6187c478bd9Sstevel@tonic-gate static int64_t	checkfragallocated(daddr32_t);
619fe12dc75SToomas Soome static struct csum	*read_summaryinfo(struct fs *);
620fe12dc75SToomas Soome static diskaddr_t	probe_summaryinfo();
6217c478bd9Sstevel@tonic-gate 
622d1a180b0Smaheshvs int
main(int argc,char * argv[])6237c478bd9Sstevel@tonic-gate main(int argc, char *argv[])
6247c478bd9Sstevel@tonic-gate {
6257c478bd9Sstevel@tonic-gate 	long i, mincpc, mincpg, ibpcl;
6267c478bd9Sstevel@tonic-gate 	long cylno, rpos, blk, j, warn = 0;
6277c478bd9Sstevel@tonic-gate 	long mincpgcnt, maxcpg;
6287c478bd9Sstevel@tonic-gate 	uint64_t used, bpcg, inospercg;
6297c478bd9Sstevel@tonic-gate 	long mapcramped, inodecramped;
6307c478bd9Sstevel@tonic-gate 	long postblsize, rotblsize, totalsbsize;
6317c478bd9Sstevel@tonic-gate 	FILE *mnttab;
6327c478bd9Sstevel@tonic-gate 	struct mnttab mntp;
6337c478bd9Sstevel@tonic-gate 	char *special;
6347c478bd9Sstevel@tonic-gate 	struct statvfs64 fs;
6356451fdbcSvsakar 	struct dk_geom dkg;
63665908c77Syu, larry liu - Sun Microsystems - Beijing China 	struct dk_minfo dkminfo;
6377c478bd9Sstevel@tonic-gate 	char pbuf[sizeof (uint64_t) * 3 + 1];
6386451fdbcSvsakar 	char *tmpbuf;
6397c478bd9Sstevel@tonic-gate 	int width, plen;
6407c478bd9Sstevel@tonic-gate 	uint64_t num;
6417c478bd9Sstevel@tonic-gate 	int c, saverr;
6427c478bd9Sstevel@tonic-gate 	diskaddr_t max_fssize;
6437c478bd9Sstevel@tonic-gate 	long tmpmaxcontig = -1;
6447c478bd9Sstevel@tonic-gate 	struct sigaction sigact;
6457c478bd9Sstevel@tonic-gate 	uint64_t nbytes64;
6467c478bd9Sstevel@tonic-gate 	int remaining_cg;
6477c478bd9Sstevel@tonic-gate 	int do_dot = 0;
6488b7c2cdfSws 	int use_efi_dflts = 0, retry = 0, isremovable = 0, ishotpluggable = 0;
6496d24e334Svsakar 	int invalid_sb_cnt, ret, skip_this_sb, cg_too_small;
6506d24e334Svsakar 	int geom_nsect, geom_ntrack, geom_cpg;
6517c478bd9Sstevel@tonic-gate 
6527c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
6537c478bd9Sstevel@tonic-gate 
6547c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
6557c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN "SYS_TEST"
6567c478bd9Sstevel@tonic-gate #endif
6577c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
6587c478bd9Sstevel@tonic-gate 
6597c478bd9Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "F:bmo:VPGM:T:t:")) != EOF) {
6607c478bd9Sstevel@tonic-gate 		switch (c) {
6617c478bd9Sstevel@tonic-gate 
6627c478bd9Sstevel@tonic-gate 		case 'F':
6637c478bd9Sstevel@tonic-gate 			string = optarg;
6647c478bd9Sstevel@tonic-gate 			if (strcmp(string, "ufs") != 0)
6657c478bd9Sstevel@tonic-gate 				usage();
6667c478bd9Sstevel@tonic-gate 			break;
6677c478bd9Sstevel@tonic-gate 
6687c478bd9Sstevel@tonic-gate 		case 'm':	/* return command line used to create this FS */
6697c478bd9Sstevel@tonic-gate 			mflag++;
6707c478bd9Sstevel@tonic-gate 			break;
6717c478bd9Sstevel@tonic-gate 
6727c478bd9Sstevel@tonic-gate 		case 'o':
6737c478bd9Sstevel@tonic-gate 			/*
6747c478bd9Sstevel@tonic-gate 			 * ufs specific options.
6757c478bd9Sstevel@tonic-gate 			 */
6767c478bd9Sstevel@tonic-gate 			string = optarg;
6777c478bd9Sstevel@tonic-gate 			while (*string != '\0') {
6787c478bd9Sstevel@tonic-gate 				if (match("nsect=")) {
6797c478bd9Sstevel@tonic-gate 					nsect = number(DFLNSECT, "nsect", 0);
6807c478bd9Sstevel@tonic-gate 					nsect_flag = RC_KEYWORD;
6817c478bd9Sstevel@tonic-gate 				} else if (match("ntrack=")) {
6827c478bd9Sstevel@tonic-gate 					ntrack = number(DFLNTRAK, "ntrack", 0);
6837c478bd9Sstevel@tonic-gate 					ntrack_flag = RC_KEYWORD;
6847c478bd9Sstevel@tonic-gate 				} else if (match("bsize=")) {
6857c478bd9Sstevel@tonic-gate 					bsize = number(DESBLKSIZE, "bsize", 0);
6867c478bd9Sstevel@tonic-gate 					bsize_flag = RC_KEYWORD;
6877c478bd9Sstevel@tonic-gate 				} else if (match("fragsize=")) {
6887c478bd9Sstevel@tonic-gate 					fragsize = number(DESFRAGSIZE,
6897c478bd9Sstevel@tonic-gate 					    "fragsize", 0);
6907c478bd9Sstevel@tonic-gate 					fragsize_flag = RC_KEYWORD;
6917c478bd9Sstevel@tonic-gate 				} else if (match("cgsize=")) {
6927c478bd9Sstevel@tonic-gate 					cpg = number(DESCPG, "cgsize", 0);
6937c478bd9Sstevel@tonic-gate 					cpg_flag = RC_KEYWORD;
6947c478bd9Sstevel@tonic-gate 				} else if (match("free=")) {
6957c478bd9Sstevel@tonic-gate 					minfree = number(MINFREE, "free",
6967c478bd9Sstevel@tonic-gate 					    ALLOW_PERCENT);
6977c478bd9Sstevel@tonic-gate 					minfree_flag = RC_KEYWORD;
6987c478bd9Sstevel@tonic-gate 				} else if (match("maxcontig=")) {
6997c478bd9Sstevel@tonic-gate 					tmpmaxcontig =
7007c478bd9Sstevel@tonic-gate 					    number(-1, "maxcontig", 0);
7017c478bd9Sstevel@tonic-gate 					maxcontig_flag = RC_KEYWORD;
7027c478bd9Sstevel@tonic-gate 				} else if (match("nrpos=")) {
7037c478bd9Sstevel@tonic-gate 					nrpos = number(NRPOS, "nrpos", 0);
7047c478bd9Sstevel@tonic-gate 					nrpos_flag = RC_KEYWORD;
7057c478bd9Sstevel@tonic-gate 				} else if (match("rps=")) {
7067c478bd9Sstevel@tonic-gate 					rps = number(DEFHZ, "rps", 0);
7077c478bd9Sstevel@tonic-gate 					rps_flag = RC_KEYWORD;
7087c478bd9Sstevel@tonic-gate 				} else if (match("nbpi=")) {
7097c478bd9Sstevel@tonic-gate 					nbpi = number(NBPI, "nbpi", 0);
7107c478bd9Sstevel@tonic-gate 					nbpi_flag = RC_KEYWORD;
7117c478bd9Sstevel@tonic-gate 				} else if (match("opt=")) {
7127c478bd9Sstevel@tonic-gate 					opt = checkopt(string);
7137c478bd9Sstevel@tonic-gate 				} else if (match("mtb=")) {
7147c478bd9Sstevel@tonic-gate 					mtb = checkmtb(string);
7157c478bd9Sstevel@tonic-gate 				} else if (match("apc=")) {
7167c478bd9Sstevel@tonic-gate 					apc = number(0, "apc", 0);
7177c478bd9Sstevel@tonic-gate 					apc_flag = RC_KEYWORD;
7187c478bd9Sstevel@tonic-gate 				} else if (match("gap=")) {
7197c478bd9Sstevel@tonic-gate 					(void) number(0, "gap", ALLOW_MS1);
7207c478bd9Sstevel@tonic-gate 					rotdelay = ROTDELAY;
7217c478bd9Sstevel@tonic-gate 					rotdelay_flag = RC_DEFAULT;
7227c478bd9Sstevel@tonic-gate 				} else if (match("debug=")) {
7237c478bd9Sstevel@tonic-gate 					debug = number(0, "debug", 0);
7247c478bd9Sstevel@tonic-gate 				} else if (match("N")) {
7257c478bd9Sstevel@tonic-gate 					Nflag++;
726355d6bb5Sswilcox 				} else if (match("calcsb")) {
727355d6bb5Sswilcox 					rflag++;
728355d6bb5Sswilcox 					Nflag++;
729355d6bb5Sswilcox 				} else if (match("calcbinsb")) {
730355d6bb5Sswilcox 					rflag++;
731355d6bb5Sswilcox 					Rflag++;
732355d6bb5Sswilcox 					Nflag++;
7337c478bd9Sstevel@tonic-gate 				} else if (*string == '\0') {
7347c478bd9Sstevel@tonic-gate 					break;
7357c478bd9Sstevel@tonic-gate 				} else {
7367c478bd9Sstevel@tonic-gate 					(void) fprintf(stderr, gettext(
737d50c8f90Svsakar 					    "illegal option: %s\n"), string);
7387c478bd9Sstevel@tonic-gate 					usage();
7397c478bd9Sstevel@tonic-gate 				}
7407c478bd9Sstevel@tonic-gate 
7417c478bd9Sstevel@tonic-gate 				if (*string == ',') string++;
7427c478bd9Sstevel@tonic-gate 				if (*string == ' ') string++;
7437c478bd9Sstevel@tonic-gate 			}
7447c478bd9Sstevel@tonic-gate 			break;
7457c478bd9Sstevel@tonic-gate 
7467c478bd9Sstevel@tonic-gate 		case 'V':
7477c478bd9Sstevel@tonic-gate 			{
7487c478bd9Sstevel@tonic-gate 				char	*opt_text;
7497c478bd9Sstevel@tonic-gate 				int	opt_count;
7507c478bd9Sstevel@tonic-gate 
7517c478bd9Sstevel@tonic-gate 				(void) fprintf(stdout, gettext("mkfs -F ufs "));
7527c478bd9Sstevel@tonic-gate 				for (opt_count = 1; opt_count < argc;
753d50c8f90Svsakar 				    opt_count++) {
7547c478bd9Sstevel@tonic-gate 					opt_text = argv[opt_count];
7557c478bd9Sstevel@tonic-gate 					if (opt_text)
756d50c8f90Svsakar 						(void) fprintf(stdout, " %s ",
757d50c8f90Svsakar 						    opt_text);
7587c478bd9Sstevel@tonic-gate 				}
7597c478bd9Sstevel@tonic-gate 				(void) fprintf(stdout, "\n");
7607c478bd9Sstevel@tonic-gate 			}
7617c478bd9Sstevel@tonic-gate 			break;
7627c478bd9Sstevel@tonic-gate 
7637c478bd9Sstevel@tonic-gate 		case 'b':	/* do nothing for this */
7647c478bd9Sstevel@tonic-gate 			break;
7657c478bd9Sstevel@tonic-gate 
7667c478bd9Sstevel@tonic-gate 		case 'M':	/* grow the mounted file system */
7677c478bd9Sstevel@tonic-gate 			directory = optarg;
7687c478bd9Sstevel@tonic-gate 
7697c478bd9Sstevel@tonic-gate 			/* FALLTHROUGH */
7707c478bd9Sstevel@tonic-gate 		case 'G':	/* grow the file system */
7717c478bd9Sstevel@tonic-gate 			grow = 1;
7727c478bd9Sstevel@tonic-gate 			break;
773fe12dc75SToomas Soome 		case 'P':	/* probe the file system growing size	*/
7747c478bd9Sstevel@tonic-gate 			Pflag = 1;
7757c478bd9Sstevel@tonic-gate 			grow = 1; /* probe mode implies fs growing	*/
7767c478bd9Sstevel@tonic-gate 			break;
7777c478bd9Sstevel@tonic-gate 		case 'T':	/* For testing */
7787c478bd9Sstevel@tonic-gate 			testforce = 1;
7797c478bd9Sstevel@tonic-gate 
7807c478bd9Sstevel@tonic-gate 			/* FALLTHROUGH */
7817c478bd9Sstevel@tonic-gate 		case 't':
7827c478bd9Sstevel@tonic-gate 			test = 1;
7837c478bd9Sstevel@tonic-gate 			string = optarg;
7847c478bd9Sstevel@tonic-gate 			testfrags = number(NO_DEFAULT, "testfrags", 0);
7857c478bd9Sstevel@tonic-gate 			break;
7867c478bd9Sstevel@tonic-gate 
7877c478bd9Sstevel@tonic-gate 		case '?':
7887c478bd9Sstevel@tonic-gate 			usage();
7897c478bd9Sstevel@tonic-gate 			break;
7907c478bd9Sstevel@tonic-gate 		}
7917c478bd9Sstevel@tonic-gate 	}
7927c478bd9Sstevel@tonic-gate #ifdef MKFS_DEBUG
7937c478bd9Sstevel@tonic-gate 	/*
7947c478bd9Sstevel@tonic-gate 	 * Turning on MKFS_DEBUG causes mkfs to produce a filesystem
7957c478bd9Sstevel@tonic-gate 	 * that can be reproduced by setting the time to 0 and seeding
7967c478bd9Sstevel@tonic-gate 	 * the random number generator to a constant.
7977c478bd9Sstevel@tonic-gate 	 */
7987c478bd9Sstevel@tonic-gate 	mkfstime = 0;	/* reproducible results */
7997c478bd9Sstevel@tonic-gate #else
8007c478bd9Sstevel@tonic-gate 	(void) time(&mkfstime);
8017c478bd9Sstevel@tonic-gate #endif
8027c478bd9Sstevel@tonic-gate 
8037c478bd9Sstevel@tonic-gate 	if (optind >= (argc - 1)) {
8047c478bd9Sstevel@tonic-gate 		if (optind > (argc - 1)) {
8057c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
8067c478bd9Sstevel@tonic-gate 			    gettext("special not specified\n"));
8077c478bd9Sstevel@tonic-gate 			usage();
8087c478bd9Sstevel@tonic-gate 		} else if (mflag == 0) {
8097c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
8107c478bd9Sstevel@tonic-gate 			    gettext("size not specified\n"));
8117c478bd9Sstevel@tonic-gate 			usage();
8127c478bd9Sstevel@tonic-gate 		}
8137c478bd9Sstevel@tonic-gate 	}
8147c478bd9Sstevel@tonic-gate 	argc -= optind;
8157c478bd9Sstevel@tonic-gate 	argv = &argv[optind];
8167c478bd9Sstevel@tonic-gate 
8177c478bd9Sstevel@tonic-gate 	fsys = argv[0];
8187c478bd9Sstevel@tonic-gate 	fsi = open64(fsys, O_RDONLY);
8197c478bd9Sstevel@tonic-gate 	if (fsi < 0) {
8207c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext("%s: cannot open\n"), fsys);
8217c478bd9Sstevel@tonic-gate 		lockexit(32);
8227c478bd9Sstevel@tonic-gate 	}
8237c478bd9Sstevel@tonic-gate 
8247c478bd9Sstevel@tonic-gate 	if (mflag) {
8257c478bd9Sstevel@tonic-gate 		dump_fscmd(fsys, fsi);
8267c478bd9Sstevel@tonic-gate 		lockexit(0);
8277c478bd9Sstevel@tonic-gate 	}
8287c478bd9Sstevel@tonic-gate 
8297c478bd9Sstevel@tonic-gate 	/*
8307c478bd9Sstevel@tonic-gate 	 * The task of setting all of the configuration parameters for a
8317c478bd9Sstevel@tonic-gate 	 * UFS file system is basically a matter of solving n equations
8327c478bd9Sstevel@tonic-gate 	 * in m variables.  Typically, m is greater than n, so there is
8337c478bd9Sstevel@tonic-gate 	 * usually more than one valid solution.  Since this is usually
8347c478bd9Sstevel@tonic-gate 	 * an under-constrained problem, it's not always obvious what the
8357c478bd9Sstevel@tonic-gate 	 * "best" configuration is.
8367c478bd9Sstevel@tonic-gate 	 *
8377c478bd9Sstevel@tonic-gate 	 * In general, the approach is to
8387c478bd9Sstevel@tonic-gate 	 * 1. Determine the values for the file system parameters
8397c478bd9Sstevel@tonic-gate 	 *    that are externally contrained and therefore not adjustable
8407c478bd9Sstevel@tonic-gate 	 *    by mkfs (such as the device's size and maxtransfer size).
8417c478bd9Sstevel@tonic-gate 	 * 2. Acquire the user's requested setting for all configuration
8427c478bd9Sstevel@tonic-gate 	 *    values that can be set on the command line.
8437c478bd9Sstevel@tonic-gate 	 * 3. Determine the final value of all configuration values, by
8447c478bd9Sstevel@tonic-gate 	 *    the following approach:
8457c478bd9Sstevel@tonic-gate 	 *	- set the file system block size (fs_bsize).  Although
8467c478bd9Sstevel@tonic-gate 	 *	  this could be regarded as an adjustable parameter, in
8477c478bd9Sstevel@tonic-gate 	 *	  fact, it's pretty much a constant.  At this time, it's
8487c478bd9Sstevel@tonic-gate 	 *	  generally set to 8k (with older hardware, it can
8497c478bd9Sstevel@tonic-gate 	 *	  sometimes make sense to set it to 4k, but those
8507c478bd9Sstevel@tonic-gate 	 *	  situations are pretty rare now).
8517c478bd9Sstevel@tonic-gate 	 *	- re-adjust the maximum file system size based on the
8527c478bd9Sstevel@tonic-gate 	 *	  value of the file system block size.  Since the
8537c478bd9Sstevel@tonic-gate 	 *	  frag size can't be any larger than a file system
8547c478bd9Sstevel@tonic-gate 	 *	  block, and the number of frags in the file system
8557c478bd9Sstevel@tonic-gate 	 *	  has to fit into 31 bits, the file system block size
8567c478bd9Sstevel@tonic-gate 	 *	  affects the maximum file system size.
8577c478bd9Sstevel@tonic-gate 	 *	- now that the real maximum file system is known, set the
8587c478bd9Sstevel@tonic-gate 	 *	  actual size of the file system to be created to
8597c478bd9Sstevel@tonic-gate 	 *	  MIN(requested size, maximum file system size).
8607c478bd9Sstevel@tonic-gate 	 *	- now validate, and if necessary, adjust the following
8617c478bd9Sstevel@tonic-gate 	 *	  values:
8627c478bd9Sstevel@tonic-gate 	 *		rotdelay
8637c478bd9Sstevel@tonic-gate 	 *		nsect
8647c478bd9Sstevel@tonic-gate 	 *		maxcontig
8657c478bd9Sstevel@tonic-gate 	 *		apc
8667c478bd9Sstevel@tonic-gate 	 *		frag_size
8677c478bd9Sstevel@tonic-gate 	 *		rps
8687c478bd9Sstevel@tonic-gate 	 *		minfree
8697c478bd9Sstevel@tonic-gate 	 *		nrpos
8707c478bd9Sstevel@tonic-gate 	 *		nrack
8717c478bd9Sstevel@tonic-gate 	 *		nbpi
8727c478bd9Sstevel@tonic-gate 	 *	- calculate maxcpg (the maximum value of the cylinders-per-
8737c478bd9Sstevel@tonic-gate 	 *	  cylinder-group configuration parameters).  There are two
8747c478bd9Sstevel@tonic-gate 	 *	  algorithms for calculating maxcpg:  an old one, which is
8757c478bd9Sstevel@tonic-gate 	 *	  used for file systems of less than 1 terabyte, and a
8767c478bd9Sstevel@tonic-gate 	 *	  new one, implemented in the function compute_maxcpg(),
8777c478bd9Sstevel@tonic-gate 	 *	  which is used for file systems of greater than 1 TB.
8787c478bd9Sstevel@tonic-gate 	 *	  The difference between them is that compute_maxcpg()
8797c478bd9Sstevel@tonic-gate 	 *	  really tries to maximize the cpg value.  The old
8807c478bd9Sstevel@tonic-gate 	 *	  algorithm fails to take advantage of smaller frags and
8817c478bd9Sstevel@tonic-gate 	 *	  lower inode density when determining the maximum cpg,
8827c478bd9Sstevel@tonic-gate 	 *	  and thus comes up with much lower numbers in some
8837c478bd9Sstevel@tonic-gate 	 *	  configurations.  At some point, we might use the
8847c478bd9Sstevel@tonic-gate 	 *	  new algorithm for determining maxcpg for all file
8857c478bd9Sstevel@tonic-gate 	 *	  systems, but at this time, the changes implemented for
8867c478bd9Sstevel@tonic-gate 	 *	  multi-terabyte UFS are NOT being automatically applied
8877c478bd9Sstevel@tonic-gate 	 *	  to UFS file systems of less than a terabyte (in the
8887c478bd9Sstevel@tonic-gate 	 *	  interest of not changing existing UFS policy too much
8897c478bd9Sstevel@tonic-gate 	 *	  until the ramifications of the changes are well-understood
8907c478bd9Sstevel@tonic-gate 	 *	  and have been evaluated for their effects on performance.)
8917c478bd9Sstevel@tonic-gate 	 *	- check the current values of the configuration parameters
8927c478bd9Sstevel@tonic-gate 	 *	  against the various constraints imposed by UFS.  These
8937c478bd9Sstevel@tonic-gate 	 *	  include:
8947c478bd9Sstevel@tonic-gate 	 *		* There must be at least one inode in each
8957c478bd9Sstevel@tonic-gate 	 *		  cylinder group.
8967c478bd9Sstevel@tonic-gate 	 *		* The cylinder group overhead block, which
8977c478bd9Sstevel@tonic-gate 	 *		  contains the inode and frag bigmaps, must fit
8987c478bd9Sstevel@tonic-gate 	 *		  within one file system block.
8997c478bd9Sstevel@tonic-gate 	 *		* The space required for inode maps should
9007c478bd9Sstevel@tonic-gate 	 *		  occupy no more than a third of the cylinder
9017c478bd9Sstevel@tonic-gate 	 *		  group overhead block.
9027c478bd9Sstevel@tonic-gate 	 *		* The rotational position tables have to fit
9037c478bd9Sstevel@tonic-gate 	 *		  within the available space in the super block.
9047c478bd9Sstevel@tonic-gate 	 *	  Adjust the configuration values that can be adjusted
9057c478bd9Sstevel@tonic-gate 	 *	  so that these constraints are satisfied.  The
9067c478bd9Sstevel@tonic-gate 	 *	  configuration values that are adjustable are:
9077c478bd9Sstevel@tonic-gate 	 *		* frag size
9087c478bd9Sstevel@tonic-gate 	 *		* cylinders per group
9097c478bd9Sstevel@tonic-gate 	 *		* inode density (can be increased)
9107c478bd9Sstevel@tonic-gate 	 *		* number of rotational positions (the rotational
9117c478bd9Sstevel@tonic-gate 	 *		  position tables are eliminated altogether if
9127c478bd9Sstevel@tonic-gate 	 *		  there isn't enough room for them.)
9137c478bd9Sstevel@tonic-gate 	 * 4. Set the values for all the dependent configuration
9147c478bd9Sstevel@tonic-gate 	 *    values (those that aren't settable on the command
9157c478bd9Sstevel@tonic-gate 	 *    line and which are completely dependent on the
9167c478bd9Sstevel@tonic-gate 	 *    adjustable parameters).  This include cpc (cycles
9177c478bd9Sstevel@tonic-gate 	 *    per cylinder, spc (sectors-per-cylinder), and many others.
9187c478bd9Sstevel@tonic-gate 	 */
9197c478bd9Sstevel@tonic-gate 
920d50c8f90Svsakar 	/*
921d50c8f90Svsakar 	 * Figure out the partition size and initialize the label_type.
922d50c8f90Svsakar 	 */
9237c478bd9Sstevel@tonic-gate 	max_fssize = get_max_size(fsi);
9247c478bd9Sstevel@tonic-gate 
9257c478bd9Sstevel@tonic-gate 	/*
9267c478bd9Sstevel@tonic-gate 	 * Get and check positional arguments, if any.
9277c478bd9Sstevel@tonic-gate 	 */
9287c478bd9Sstevel@tonic-gate 	switch (argc - 1) {
9297c478bd9Sstevel@tonic-gate 	default:
9307c478bd9Sstevel@tonic-gate 		usage();
9317c478bd9Sstevel@tonic-gate 		/*NOTREACHED*/
9327c478bd9Sstevel@tonic-gate 	case 15:
9337c478bd9Sstevel@tonic-gate 		mtb = checkmtb(argv[15]);
9347c478bd9Sstevel@tonic-gate 		/* FALLTHROUGH */
9357c478bd9Sstevel@tonic-gate 	case 14:
9367c478bd9Sstevel@tonic-gate 		string = argv[14];
9377c478bd9Sstevel@tonic-gate 		tmpmaxcontig = number(-1, "maxcontig", 0);
9387c478bd9Sstevel@tonic-gate 		maxcontig_flag = RC_POSITIONAL;
9397c478bd9Sstevel@tonic-gate 		/* FALLTHROUGH */
9407c478bd9Sstevel@tonic-gate 	case 13:
9417c478bd9Sstevel@tonic-gate 		string = argv[13];
9427c478bd9Sstevel@tonic-gate 		nrpos = number(NRPOS, "nrpos", 0);
9437c478bd9Sstevel@tonic-gate 		nrpos_flag = RC_POSITIONAL;
9447c478bd9Sstevel@tonic-gate 		/* FALLTHROUGH */
9457c478bd9Sstevel@tonic-gate 	case 12:
9467c478bd9Sstevel@tonic-gate 		string = argv[12];
9477c478bd9Sstevel@tonic-gate 		rotdelay = ROTDELAY;
9487c478bd9Sstevel@tonic-gate 		rotdelay_flag = RC_DEFAULT;
9497c478bd9Sstevel@tonic-gate 		/* FALLTHROUGH */
9507c478bd9Sstevel@tonic-gate 	case 11:
9517c478bd9Sstevel@tonic-gate 		string = argv[11];
9527c478bd9Sstevel@tonic-gate 		apc = number(0, "apc", 0);
9537c478bd9Sstevel@tonic-gate 		apc_flag = RC_POSITIONAL;
9547c478bd9Sstevel@tonic-gate 		/* FALLTHROUGH */
9557c478bd9Sstevel@tonic-gate 	case 10:
9567c478bd9Sstevel@tonic-gate 		opt = checkopt(argv[10]);
9577c478bd9Sstevel@tonic-gate 		/* FALLTHROUGH */
9587c478bd9Sstevel@tonic-gate 	case 9:
9597c478bd9Sstevel@tonic-gate 		string = argv[9];
9607c478bd9Sstevel@tonic-gate 		nbpi = number(NBPI, "nbpi", 0);
9617c478bd9Sstevel@tonic-gate 		nbpi_flag = RC_POSITIONAL;
9627c478bd9Sstevel@tonic-gate 		/* FALLTHROUGH */
9637c478bd9Sstevel@tonic-gate 	case 8:
9647c478bd9Sstevel@tonic-gate 		string = argv[8];
9657c478bd9Sstevel@tonic-gate 		rps = number(DEFHZ, "rps", 0);
9667c478bd9Sstevel@tonic-gate 		rps_flag = RC_POSITIONAL;
9677c478bd9Sstevel@tonic-gate 		/* FALLTHROUGH */
9687c478bd9Sstevel@tonic-gate 	case 7:
9697c478bd9Sstevel@tonic-gate 		string = argv[7];
9707c478bd9Sstevel@tonic-gate 		minfree = number(MINFREE, "free", ALLOW_PERCENT);
9717c478bd9Sstevel@tonic-gate 		minfree_flag = RC_POSITIONAL;
9727c478bd9Sstevel@tonic-gate 		/* FALLTHROUGH */
9737c478bd9Sstevel@tonic-gate 	case 6:
9747c478bd9Sstevel@tonic-gate 		string = argv[6];
9757c478bd9Sstevel@tonic-gate 		cpg = number(DESCPG, "cgsize", 0);
9767c478bd9Sstevel@tonic-gate 		cpg_flag = RC_POSITIONAL;
9777c478bd9Sstevel@tonic-gate 		/* FALLTHROUGH */
9787c478bd9Sstevel@tonic-gate 	case 5:
9797c478bd9Sstevel@tonic-gate 		string = argv[5];
9807c478bd9Sstevel@tonic-gate 		fragsize = number(DESFRAGSIZE, "fragsize", 0);
9817c478bd9Sstevel@tonic-gate 		fragsize_flag = RC_POSITIONAL;
9827c478bd9Sstevel@tonic-gate 		/* FALLTHROUGH */
9837c478bd9Sstevel@tonic-gate 	case 4:
9847c478bd9Sstevel@tonic-gate 		string = argv[4];
9857c478bd9Sstevel@tonic-gate 		bsize = number(DESBLKSIZE, "bsize", 0);
9867c478bd9Sstevel@tonic-gate 		bsize_flag = RC_POSITIONAL;
9877c478bd9Sstevel@tonic-gate 		/* FALLTHROUGH */
9887c478bd9Sstevel@tonic-gate 	case 3:
9897c478bd9Sstevel@tonic-gate 		string = argv[3];
9907c478bd9Sstevel@tonic-gate 		ntrack = number(DFLNTRAK, "ntrack", 0);
9917c478bd9Sstevel@tonic-gate 		ntrack_flag = RC_POSITIONAL;
9927c478bd9Sstevel@tonic-gate 		/* FALLTHROUGH */
9937c478bd9Sstevel@tonic-gate 	case 2:
9947c478bd9Sstevel@tonic-gate 		string = argv[2];
9957c478bd9Sstevel@tonic-gate 		nsect = number(DFLNSECT, "nsect", 0);
9967c478bd9Sstevel@tonic-gate 		nsect_flag = RC_POSITIONAL;
9977c478bd9Sstevel@tonic-gate 		/* FALLTHROUGH */
9987c478bd9Sstevel@tonic-gate 	case 1:
9997c478bd9Sstevel@tonic-gate 		string = argv[1];
10007c478bd9Sstevel@tonic-gate 		fssize_db = number(max_fssize, "size", 0);
10017c478bd9Sstevel@tonic-gate 	}
10027c478bd9Sstevel@tonic-gate 
1003d50c8f90Svsakar 	/*
1004d50c8f90Svsakar 	 * Initialize the parameters in the same way as newfs so that
1005d50c8f90Svsakar 	 * newfs and mkfs would result in the same file system layout
1006d50c8f90Svsakar 	 * for EFI labelled disks. Do this only in the absence of user
1007d50c8f90Svsakar 	 * specified values for these parameters.
1008d50c8f90Svsakar 	 */
1009d50c8f90Svsakar 	if (label_type == LABEL_TYPE_EFI) {
1010d50c8f90Svsakar 		if (apc_flag == RC_DEFAULT) apc = 0;
1011d50c8f90Svsakar 		if (nrpos_flag == RC_DEFAULT) nrpos = 1;
1012d50c8f90Svsakar 		if (ntrack_flag == RC_DEFAULT) ntrack = DEF_TRACKS_EFI;
1013d50c8f90Svsakar 		if (rps_flag == RC_DEFAULT) rps = DEFHZ;
1014d50c8f90Svsakar 		if (nsect_flag == RC_DEFAULT) nsect = DEF_SECTORS_EFI;
1015d50c8f90Svsakar 	}
10167c478bd9Sstevel@tonic-gate 
10177c478bd9Sstevel@tonic-gate 	if ((maxcontig_flag == RC_DEFAULT) || (tmpmaxcontig == -1) ||
1018d50c8f90Svsakar 	    (maxcontig == -1)) {
10197c478bd9Sstevel@tonic-gate 		long maxtrax = get_max_track_size(fsi);
10207c478bd9Sstevel@tonic-gate 		maxcontig = maxtrax / bsize;
10217c478bd9Sstevel@tonic-gate 
10227c478bd9Sstevel@tonic-gate 	} else {
10237c478bd9Sstevel@tonic-gate 		maxcontig = tmpmaxcontig;
10247c478bd9Sstevel@tonic-gate 	}
10256451fdbcSvsakar 	dprintf(("DeBuG maxcontig : %ld\n", maxcontig));
10267c478bd9Sstevel@tonic-gate 
10277c478bd9Sstevel@tonic-gate 	if (rotdelay == -1) {	/* default by newfs and mkfs */
10287c478bd9Sstevel@tonic-gate 		rotdelay = ROTDELAY;
10297c478bd9Sstevel@tonic-gate 	}
10307c478bd9Sstevel@tonic-gate 
10317c478bd9Sstevel@tonic-gate 	if (cpg_flag == RC_DEFAULT) { /* If not explicity set, use default */
10327c478bd9Sstevel@tonic-gate 		cpg = DESCPG;
10337c478bd9Sstevel@tonic-gate 	}
10346451fdbcSvsakar 	dprintf(("DeBuG cpg : %ld\n", cpg));
10357c478bd9Sstevel@tonic-gate 
10367c478bd9Sstevel@tonic-gate 	/*
10377c478bd9Sstevel@tonic-gate 	 * Now that we have the semi-sane args, either positional, via -o,
10387c478bd9Sstevel@tonic-gate 	 * or by defaulting, handle inter-dependencies and range checks.
10397c478bd9Sstevel@tonic-gate 	 */
10407c478bd9Sstevel@tonic-gate 
10417c478bd9Sstevel@tonic-gate 	/*
10427c478bd9Sstevel@tonic-gate 	 * Settle the file system block size first, since it's a fixed
10437c478bd9Sstevel@tonic-gate 	 * parameter once set and so many other parameters, including
10447c478bd9Sstevel@tonic-gate 	 * max_fssize, depend on it.
10457c478bd9Sstevel@tonic-gate 	 */
10467c478bd9Sstevel@tonic-gate 	range_check(&bsize, "bsize", MINBSIZE, MAXBSIZE, DESBLKSIZE,
10477c478bd9Sstevel@tonic-gate 	    bsize_flag);
10487c478bd9Sstevel@tonic-gate 
10497c478bd9Sstevel@tonic-gate 	if (!POWEROF2(bsize)) {
10507c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
10517c478bd9Sstevel@tonic-gate 		    gettext("block size must be a power of 2, not %ld\n"),
10527c478bd9Sstevel@tonic-gate 		    bsize);
10537c478bd9Sstevel@tonic-gate 		bsize = DESBLKSIZE;
10547c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
10557c478bd9Sstevel@tonic-gate 		    gettext("mkfs: bsize reset to default %ld\n"),
10567c478bd9Sstevel@tonic-gate 		    bsize);
10577c478bd9Sstevel@tonic-gate 	}
10587c478bd9Sstevel@tonic-gate 
10597c478bd9Sstevel@tonic-gate 	if (fssize_db > max_fssize && validate_size(fsi, fssize_db)) {
10607c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext(
10617c478bd9Sstevel@tonic-gate 		    "Warning: the requested size of this file system\n"
10627c478bd9Sstevel@tonic-gate 		    "(%lld sectors) is greater than the size of the\n"
10637c478bd9Sstevel@tonic-gate 		    "device reported by the driver (%lld sectors).\n"
10647c478bd9Sstevel@tonic-gate 		    "However, a read of the device at the requested size\n"
10657c478bd9Sstevel@tonic-gate 		    "does succeed, so the requested size will be used.\n"),
10667c478bd9Sstevel@tonic-gate 		    fssize_db, max_fssize);
10677c478bd9Sstevel@tonic-gate 		max_fssize = fssize_db;
10687c478bd9Sstevel@tonic-gate 	}
10697c478bd9Sstevel@tonic-gate 	/*
10707c478bd9Sstevel@tonic-gate 	 * Since the maximum allocatable unit (the frag) must be less than
10717c478bd9Sstevel@tonic-gate 	 * or equal to bsize, and the number of frags must be less than or
10727c478bd9Sstevel@tonic-gate 	 * equal to INT_MAX, the total size of the file system (in
10737c478bd9Sstevel@tonic-gate 	 * bytes) must be less than or equal to bsize * INT_MAX.
10747c478bd9Sstevel@tonic-gate 	 */
10757c478bd9Sstevel@tonic-gate 
10767c478bd9Sstevel@tonic-gate 	if (max_fssize > ((diskaddr_t)bsize/DEV_BSIZE) * INT_MAX)
10777c478bd9Sstevel@tonic-gate 		max_fssize = ((diskaddr_t)bsize/DEV_BSIZE) * INT_MAX;
1078d50c8f90Svsakar 
10797c478bd9Sstevel@tonic-gate 	range_check_64(&fssize_db, "size", 1024LL, max_fssize, max_fssize, 1);
10807c478bd9Sstevel@tonic-gate 
10817c478bd9Sstevel@tonic-gate 	if (fssize_db >= SECTORS_PER_TERABYTE) {
10827c478bd9Sstevel@tonic-gate 		mtb = 'y';
10837c478bd9Sstevel@tonic-gate 		if (!in_64bit_mode()) {
10847c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(
10857c478bd9Sstevel@tonic-gate "mkfs:  Warning: Creating a file system greater than 1 terabyte on a\n"
10867c478bd9Sstevel@tonic-gate "       system running a 32-bit kernel.  This file system will not be\n"
10877c478bd9Sstevel@tonic-gate "       accessible until the system is rebooted with a 64-bit kernel.\n"));
10887c478bd9Sstevel@tonic-gate 		}
10897c478bd9Sstevel@tonic-gate 	}
1090d50c8f90Svsakar 	dprintf(("DeBuG mtb : %c\n", mtb));
10917c478bd9Sstevel@tonic-gate 
10927c478bd9Sstevel@tonic-gate 	/*
1093*bbf21555SRichard Lowe 	 * With newer and much larger disks, the newfs(8) and mkfs_ufs(8)
10946451fdbcSvsakar 	 * commands had problems in correctly handling the "native" geometries
10956451fdbcSvsakar 	 * for various storage devices.
10966451fdbcSvsakar 	 *
1097*bbf21555SRichard Lowe 	 * To handle the new age disks, mkfs_ufs(8) will use the EFI style
10986451fdbcSvsakar 	 * for non-EFI disks that are larger than the CHS addressing limit
10996451fdbcSvsakar 	 * ( > 8GB approx ) and ignore the disk geometry information for
11006451fdbcSvsakar 	 * these drives. This is what is currently done for multi-terrabyte
11016451fdbcSvsakar 	 * filesystems on EFI disks.
11026451fdbcSvsakar 	 *
11036451fdbcSvsakar 	 * However if the user asked for a specific layout by supplying values
11046d24e334Svsakar 	 * for even one of the three parameters (nsect, ntrack, cpg), honour
11056d24e334Svsakar 	 * the user supplied parameters.
11066d24e334Svsakar 	 *
11076d24e334Svsakar 	 * Choosing EFI style or native geometry style can make a lot of
11086d24e334Svsakar 	 * difference, because the size of a cylinder group is dependent on
11096d24e334Svsakar 	 * this choice. This in turn means that the position of alternate
11106d24e334Svsakar 	 * superblocks varies depending on the style chosen. It is not
11116d24e334Svsakar 	 * necessary that all disks of size > CHSLIMIT have EFI style layout.
11126d24e334Svsakar 	 * There can be disks which are > CHSLIMIT size, but have native
11136d24e334Svsakar 	 * geometry style layout, thereby warranting the need for alternate
11146d24e334Svsakar 	 * logic in superblock detection.
11157c478bd9Sstevel@tonic-gate 	 */
1116d50c8f90Svsakar 	if (mtb != 'y' && (ntrack == -1 || GROW_WITH_DEFAULT_TRAK ||
1117d50c8f90Svsakar 	    DEFAULT_SECT_TRAK_CPG)) {
11186451fdbcSvsakar 		/*
11196d24e334Svsakar 		 * "-1" indicates that we were called from newfs and ntracks
11206d24e334Svsakar 		 * was not specified in newfs command line. Calculate nsect
11216451fdbcSvsakar 		 * and ntrack in the same manner as newfs.
11226451fdbcSvsakar 		 *
11236451fdbcSvsakar 		 * This is required because, the defaults for nsect and ntrack
11246451fdbcSvsakar 		 * is hardcoded in mkfs, whereas to generate the alternate
11256451fdbcSvsakar 		 * superblock locations for the -N option, there is a need for
11266451fdbcSvsakar 		 * the geometry based values that newfs would have arrived at.
11276451fdbcSvsakar 		 * Newfs would have arrived at these values as below.
11286451fdbcSvsakar 		 */
1129d50c8f90Svsakar 		if (label_type == LABEL_TYPE_EFI ||
1130d50c8f90Svsakar 		    label_type == LABEL_TYPE_OTHER) {
1131d50c8f90Svsakar 			use_efi_dflts = 1;
1132d50c8f90Svsakar 			retry = 1;
1133d50c8f90Svsakar 		} else if (ioctl(fsi, DKIOCGGEOM, &dkg)) {
1134d50c8f90Svsakar 			dprintf(("%s: Unable to read Disk geometry", fsys));
1135d50c8f90Svsakar 			perror(gettext("Unable to read Disk geometry"));
1136d50c8f90Svsakar 			lockexit(32);
11376451fdbcSvsakar 		} else {
1138d50c8f90Svsakar 			nsect = dkg.dkg_nsect;
1139d50c8f90Svsakar 			ntrack = dkg.dkg_nhead;
11406451fdbcSvsakar #ifdef i386	/* Bug 1170182 */
1141d50c8f90Svsakar 			if (ntrack > 32 && (ntrack % 16) != 0) {
1142d50c8f90Svsakar 				ntrack -= (ntrack % 16);
1143d50c8f90Svsakar 			}
11446451fdbcSvsakar #endif
1145d50c8f90Svsakar 			if (ioctl(fsi, DKIOCREMOVABLE, &isremovable)) {
11464d594c33Svsakar 				dprintf(("DeBuG Unable to determine if %s is"
11474d594c33Svsakar 				    " Removable Media. Proceeding with system"
11484d594c33Svsakar 				    " determined parameters.\n", fsys));
1149d50c8f90Svsakar 				isremovable = 0;
1150d50c8f90Svsakar 			}
11518b7c2cdfSws 			if (ioctl(fsi, DKIOCHOTPLUGGABLE, &ishotpluggable)) {
11528b7c2cdfSws 				dprintf(("DeBuG Unable to determine if %s is"
11538b7c2cdfSws 				    " Hotpluggable Media. Proceeding with "
11548b7c2cdfSws 				    "system determined parameters.\n", fsys));
11558b7c2cdfSws 				ishotpluggable = 0;
11568b7c2cdfSws 			}
1157