Home | History | Annotate | Download | only in mkfs
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
     27 /*	  All Rights Reserved  	*/
     28 
     29 /*
     30  * University Copyright- Copyright (c) 1982, 1986, 1988
     31  * The Regents of the University of California
     32  * All Rights Reserved
     33  *
     34  * University Acknowledgment- Portions of this document are derived from
     35  * software developed by the University of California, Berkeley, and its
     36  * contributors.
     37  */
     38 
     39 /*
     40  * The maximum supported file system size (in sectors) is the
     41  * number of frags that can be represented in an int32_t field
     42  * (INT_MAX) times the maximum number of sectors per frag.  Since
     43  * the maximum frag size is MAXBSIZE, the maximum number of sectors
     44  * per frag is MAXBSIZE/DEV_BSIZE.
     45  */
     46 #define	FS_MAX	(((diskaddr_t)INT_MAX) * (MAXBSIZE/DEV_BSIZE))
     47 
     48 /*
     49  * make file system for cylinder-group style file systems
     50  *
     51  * usage:
     52  *
     53  *    mkfs [-F FSType] [-V] [-G [-P]] [-M dirname] [-m] [options]
     54  *	[-o specific_options]  special size
     55  *	[nsect ntrack bsize fsize cpg	minfree	rps nbpi opt apc rotdelay
     56  *	  2     3      4     5     6	7	8   9	 10  11  12
     57  *	nrpos maxcontig mtb]
     58  *	13    14	15
     59  *
     60  *  where specific_options are:
     61  *	N - no create
     62  *	nsect - The number of sectors per track
     63  *	ntrack - The number of tracks per cylinder
     64  *	bsize - block size
     65  *	fragsize - fragment size
     66  *	cgsize - The number of disk cylinders per cylinder group.
     67  * 	free - minimum free space
     68  *	rps - rotational speed (rev/sec).
     69  *	nbpi - number of data bytes per allocated inode
     70  *	opt - optimization (space, time)
     71  *	apc - number of alternates
     72  *	gap - gap size
     73  *	nrpos - number of rotational positions
     74  *	maxcontig - maximum number of logical blocks that will be
     75  *		allocated contiguously before inserting rotational delay
     76  *	mtb - if "y", set up file system for eventual growth to over a
     77  *		a terabyte
     78  * -P Do not grow the file system, but print on stdout the maximal
     79  *    size in sectors to which the file system can be increased. The calculated
     80  *    size is limited by the value provided by the operand size.
     81  *
     82  * Note that -P is a project-private interface and together with -G intended
     83  * to be used only by the growfs script. It is therefore purposely not
     84  * documented in the man page.
     85  * The -P option is covered by PSARC case 2003/422.
     86  */
     87 
     88 /*
     89  * The following constants set the defaults used for the number
     90  * of sectors/track (fs_nsect), and number of tracks/cyl (fs_ntrak).
     91  *
     92  *			NSECT		NTRAK
     93  *	72MB CDC	18		9
     94  *	30MB CDC	18		5
     95  *	720KB Diskette	9		2
     96  *
     97  * However the defaults will be different for disks larger than CHSLIMIT.
     98  */
     99 
    100 #define	DFLNSECT	32
    101 #define	DFLNTRAK	16
    102 
    103 /*
    104  * The following default sectors and tracks values are used for
    105  * non-efi disks that are larger than the CHS addressing limit. The
    106  * existing default cpg of 16 (DESCPG) holds good for larger disks too.
    107  */
    108 #define	DEF_SECTORS_EFI	128
    109 #define	DEF_TRACKS_EFI	48
    110 
    111 /*
    112  * The maximum number of cylinders in a group depends upon how much
    113  * information can be stored on a single cylinder. The default is to
    114  * use 16 cylinders per group.  This is effectively tradition - it was
    115  * the largest value acceptable under SunOs 4.1
    116  */
    117 #define	DESCPG		16	/* desired fs_cpg */
    118 
    119 /*
    120  * The following two constants set the default block and fragment sizes.
    121  * Both constants must be a power of 2 and meet the following constraints:
    122  *	MINBSIZE <= DESBLKSIZE <= MAXBSIZE
    123  *	DEV_BSIZE <= DESFRAGSIZE <= DESBLKSIZE
    124  *	DESBLKSIZE / DESFRAGSIZE <= 8
    125  */
    126 #define	DESBLKSIZE	8192
    127 #define	DESFRAGSIZE	1024
    128 
    129 /*
    130  * MINFREE gives the minimum acceptable percentage of file system
    131  * blocks which may be free. If the freelist drops below this level
    132  * only the superuser may continue to allocate blocks. This may
    133  * be set to 0 if no reserve of free blocks is deemed necessary,
    134  * however throughput drops by fifty percent if the file system
    135  * is run at between 90% and 100% full; thus the default value of
    136  * fs_minfree is 10%. With 10% free space, fragmentation is not a
    137  * problem, so we choose to optimize for time.
    138  */
    139 #define	MINFREE		10
    140 #define	DEFAULTOPT	FS_OPTTIME
    141 
    142 /*
    143  * ROTDELAY gives the minimum number of milliseconds to initiate
    144  * another disk transfer on the same cylinder. It is no longer used
    145  * and will always default to 0.
    146  */
    147 #define	ROTDELAY	0
    148 
    149 /*
    150  * MAXBLKPG determines the maximum number of data blocks which are
    151  * placed in a single cylinder group. The default is one indirect
    152  * block worth of data blocks.
    153  */
    154 #define	MAXBLKPG(bsize)	((bsize) / sizeof (daddr32_t))
    155 
    156 /*
    157  * Each file system has a number of inodes statically allocated.
    158  * We allocate one inode slot per NBPI bytes, expecting this
    159  * to be far more than we will ever need.
    160  */
    161 #define	NBPI		2048	/* Number Bytes Per Inode */
    162 #define	MTB_NBPI	(MB)	/* Number Bytes Per Inode for multi-terabyte */
    163 
    164 /*
    165  * Disks are assumed to rotate at 60HZ, unless otherwise specified.
    166  */
    167 #define	DEFHZ		60
    168 
    169 /*
    170  * Cylinder group related limits.
    171  *
    172  * For each cylinder we keep track of the availability of blocks at different
    173  * rotational positions, so that we can lay out the data to be picked
    174  * up with minimum rotational latency.  NRPOS is the number of rotational
    175  * positions which we distinguish.  With NRPOS 8 the resolution of our
    176  * summary information is 2ms for a typical 3600 rpm drive.
    177  */
    178 #define	NRPOS		8	/* number distinct rotational positions */
    179 
    180 #ifdef DEBUG
    181 #define	dprintf(x)	printf x
    182 #else
    183 #define	dprintf(x)
    184 #endif
    185 
    186 /*
    187  * For the -N option, when calculating the backup superblocks, do not print
    188  * them if we are not really sure. We may have to try an alternate method of
    189  * arriving at the superblocks. So defer printing till a handful of superblocks
    190  * look good.
    191  */
    192 #define	tprintf(x)	if (Nflag && retry) \
    193 				(void) strncat(tmpbuf, x, strlen(x)); \
    194 			else \
    195 				(void) fprintf(stderr, x);
    196 
    197 #define	ALTSB		32	/* Location of first backup superblock */
    198 
    199 /*
    200  * range_check "user_supplied" flag values.
    201  */
    202 #define	RC_DEFAULT	0
    203 #define	RC_KEYWORD	1
    204 #define	RC_POSITIONAL	2
    205 
    206 /*
    207  * ufs hole
    208  */
    209 #define	UFS_HOLE	-1
    210 
    211 #ifndef	STANDALONE
    212 #include	<stdio.h>
    213 #include	<sys/mnttab.h>
    214 #endif
    215 
    216 #include	<stdlib.h>
    217 #include	<unistd.h>
    218 #include	<malloc.h>
    219 #include	<string.h>
    220 #include	<strings.h>
    221 #include	<ctype.h>
    222 #include	<errno.h>
    223 #include	<sys/param.h>
    224 #include	<time.h>
    225 #include	<sys/types.h>
    226 #include	<sys/sysmacros.h>
    227 #include	<sys/vnode.h>
    228 #include	<sys/fs/ufs_fsdir.h>
    229 #include	<sys/fs/ufs_inode.h>
    230 #include	<sys/fs/ufs_fs.h>
    231 #include	<sys/fs/ufs_log.h>
    232 #include	<sys/mntent.h>
    233 #include	<sys/filio.h>
    234 #include	<limits.h>
    235 #include	<sys/int_const.h>
    236 #include	<signal.h>
    237 #include	<sys/efi_partition.h>
    238 #include	"roll_log.h"
    239 
    240 #define	bcopy(f, t, n)    (void) memcpy(t, f, n)
    241 #define	bzero(s, n)	(void) memset(s, 0, n)
    242 #define	bcmp(s, d, n)	memcmp(s, d, n)
    243 
    244 #define	index(s, r)	strchr(s, r)
    245 #define	rindex(s, r)	strrchr(s, r)
    246 
    247 #include	<sys/stat.h>
    248 #include	<sys/statvfs.h>
    249 #include	<locale.h>
    250 #include	<fcntl.h>
    251 #include 	<sys/isa_defs.h>	/* for ENDIAN defines */
    252 #include	<sys/vtoc.h>
    253 
    254 #include	<sys/dkio.h>
    255 #include	<sys/asynch.h>
    256 
    257 extern offset_t	llseek();
    258 extern char	*getfullblkname();
    259 extern long	lrand48();
    260 
    261 extern int	optind;
    262 extern char	*optarg;
    263 
    264 
    265 /*
    266  * The size of a cylinder group is calculated by CGSIZE. The maximum size
    267  * is limited by the fact that cylinder groups are at most one block.
    268  * Its size is derived from the size of the maps maintained in the
    269  * cylinder group and the (struct cg) size.
    270  */
    271 #define	CGSIZE(fs) \
    272 	/* base cg		*/ (sizeof (struct cg) + \
    273 	/* blktot size	*/ (fs)->fs_cpg * sizeof (long) + \
    274 	/* blks size	*/ (fs)->fs_cpg * (fs)->fs_nrpos * sizeof (short) + \
    275 	/* inode map	*/ howmany((fs)->fs_ipg, NBBY) + \
    276 	/* block map */ howmany((fs)->fs_cpg * (fs)->fs_spc / NSPF(fs), NBBY))
    277 
    278 /*
    279  * We limit the size of the inode map to be no more than a
    280  * third of the cylinder group space, since we must leave at
    281  * least an equal amount of space for the block map.
    282  *
    283  * N.B.: MAXIpG must be a multiple of INOPB(fs).
    284  */
    285 #define	MAXIpG(fs)	roundup((fs)->fs_bsize * NBBY / 3, INOPB(fs))
    286 
    287 /*
    288  * Same as MAXIpG, but parameterized by the block size (b) and the
    289  * cylinder group divisor (d), which is the reciprocal of the fraction of the
    290  * cylinder group overhead block that is used for the inode map.  So for
    291  * example, if d = 5, the macro's computation assumes that 1/5 of the
    292  * cylinder group overhead block can be dedicated to the inode map.
    293  */
    294 #define	MAXIpG_B(b, d)	roundup((b) * NBBY / (d), (b) / sizeof (struct dinode))
    295 
    296 #define	UMASK		0755
    297 #define	MAXINOPB	(MAXBSIZE / sizeof (struct dinode))
    298 #define	POWEROF2(num)	(((num) & ((num) - 1)) == 0)
    299 #define	MB		(1024*1024)
    300 #define	BETWEEN(x, l, h)	((x) >= (l) && (x) <= (h))
    301 
    302 /*
    303  * Used to set the inode generation number. Since both inodes and dinodes
    304  * are dealt with, we really need a pointer to an icommon here.
    305  */
    306 #define	IRANDOMIZE(icp)	(icp)->ic_gen = lrand48();
    307 
    308 /*
    309  * Flags for number()
    310  */
    311 #define	ALLOW_PERCENT	0x01	/* allow trailing `%' on number */
    312 #define	ALLOW_MS1	0x02	/* allow trailing `ms', state 1 */
    313 #define	ALLOW_MS2	0x04	/* allow trailing `ms', state 2 */
    314 #define	ALLOW_END_ONLY	0x08	/* must be at end of number & suffixes */
    315 
    316 #define	MAXAIO	1000	/* maximum number of outstanding I/O's we'll manage */
    317 #define	BLOCK	1	/* block in aiowait */
    318 #define	NOBLOCK	0	/* don't block in aiowait */
    319 
    320 #define	RELEASE 1	/* free an aio buffer after use */
    321 #define	SAVE	0	/* don't free the buffer */
    322 
    323 typedef struct aio_trans {
    324 	aio_result_t resultbuf;
    325 	diskaddr_t bno;
    326 	char *buffer;
    327 	int size;
    328 	int release;
    329 	struct aio_trans *next;
    330 } aio_trans;
    331 
    332 typedef struct aio_results {
    333 	int max;
    334 	int outstanding;
    335 	int maxpend;
    336 	aio_trans *trans;
    337 } aio_results;
    338 
    339 int aio_inited = 0;
    340 aio_results results;
    341 
    342 /*
    343  * Allow up to MAXBUF aio requests that each have a unique buffer.
    344  * More aio's might be done, but not using memory through the getbuf()
    345  * interface.  This can be raised, but you run into the potential of
    346  * using more memory than is physically available on the machine,
    347  * and if you start swapping, you can forget about performance.
    348  * To prevent this, we also limit the total memory used for a given
    349  * type of buffer to MAXBUFMEM.
    350  *
    351  * Tests indicate a cylinder group's worth of inodes takes:
    352  *
    353  *	NBPI	Size of Inode Buffer
    354  *	 2k	1688k
    355  *	 8k	 424k
    356  *
    357  * initcg() stores all the inodes for a cylinder group in one buffer,
    358  * so allowing 20 buffers could take 32 MB if not limited by MAXBUFMEM.
    359  */
    360 #define	MAXBUF		20
    361 #define	MAXBUFMEM	(8 * 1024 * 1024)
    362 
    363 /*
    364  * header information for buffers managed by getbuf() and freebuf()
    365  */
    366 typedef struct bufhdr {
    367 	struct bufhdr *head;
    368 	struct bufhdr *next;
    369 } bufhdr;
    370 
    371 int bufhdrsize;
    372 
    373 bufhdr inodebuf = { NULL, NULL };
    374 bufhdr cgsumbuf = { NULL, NULL };
    375 
    376 #define	SECTORS_PER_TERABYTE	(1LL << 31)
    377 /*
    378  * The following constant specifies an upper limit for file system size
    379  * that is actually a lot bigger than we expect to support with UFS. (Since
    380  * it's specified in sectors, the file system size would be 2**44 * 512,
    381  * which is 2**53, which is 8192 Terabytes.)  However, it's useful
    382  * for checking the basic sanity of a size value that is input on the
    383  * command line.
    384  */
    385 #define	FS_SIZE_UPPER_LIMIT	0x100000000000LL
    386 
    387 /*
    388  * Forward declarations
    389  */
    390 static char *getbuf(bufhdr *bufhead, int size);
    391 static void freebuf(char *buf);
    392 static void freetrans(aio_trans *transp);
    393 static aio_trans *get_aiop();
    394 static aio_trans *wait_for_write(int block);
    395 static void initcg(int cylno);
    396 static void fsinit();
    397 static int makedir(struct direct *protodir, int entries);
    398 static void iput(struct inode *ip);
    399 static void rdfs(diskaddr_t bno, int size, char *bf);
    400 static void wtfs(diskaddr_t bno, int size, char *bf);
    401 static void awtfs(diskaddr_t bno, int size, char *bf, int release);
    402 static void wtfs_breakup(diskaddr_t bno, int size, char *bf);
    403 static int isblock(struct fs *fs, unsigned char *cp, int h);
    404 static void clrblock(struct fs *fs, unsigned char *cp, int h);
    405 static void setblock(struct fs *fs, unsigned char *cp, int h);
    406 static void usage();
    407 static void dump_fscmd(char *fsys, int fsi);
    408 static uint64_t number(uint64_t d_value, char *param, int flags);
    409 static int match(char *s);
    410 static char checkopt(char *optim);
    411 static char checkmtb(char *mtbarg);
    412 static void range_check(long *varp, char *name, long minimum,
    413     long maximum, long def_val, int user_supplied);
    414 static void range_check_64(uint64_t *varp, char *name, uint64_t minimum,
    415     uint64_t maximum, uint64_t def_val, int user_supplied);
    416 static daddr32_t alloc(int size, int mode);
    417 static diskaddr_t get_max_size(int fd);
    418 static long get_max_track_size(int fd);
    419 static void block_sigint(sigset_t *old_mask);
    420 static void unblock_sigint(sigset_t *old_mask);
    421 static void recover_from_sigint(int signum);
    422 static int confirm_abort(void);
    423 static int getline(FILE *fp, char *loc, int maxlen);
    424 static void flush_writes(void);
    425 static long compute_maxcpg(long, long, long, long, long);
    426 static int in_64bit_mode(void);
    427 static int validate_size(int fd, diskaddr_t size);
    428 static void dump_sblock(void);
    429 
    430 /*
    431  * Workaround for mkfs to function properly on disks attached to XMIT 2.X
    432  * controller. If the address is not aligned at 8 byte boundary, mkfs on
    433  * disks attached to XMIT 2.X controller exhibts un-predictable behaviour.
    434  */
    435 #define	XMIT_2_X_ALIGN	8
    436 #pragma	align XMIT_2_X_ALIGN(fsun, altfsun, cgun)
    437 
    438 union {
    439 	struct fs fs;
    440 	char pad[SBSIZE];
    441 } fsun, altfsun;
    442 #define	sblock	fsun.fs
    443 #define	altsblock	altfsun.fs
    444 
    445 struct	csum *fscs;
    446 
    447 union cgun {
    448 	struct cg cg;
    449 	char pad[MAXBSIZE];
    450 } cgun;
    451 
    452 #define	acg	cgun.cg
    453 /*
    454  * Size of screen in cols in which to fit output
    455  */
    456 #define	WIDTH	80
    457 
    458 struct dinode zino[MAXBSIZE / sizeof (struct dinode)];
    459 
    460 /*
    461  * file descriptors used for rdfs(fsi) and wtfs(fso).
    462  * Initialized to an illegal file descriptor number.
    463  */
    464 int	fsi = -1;
    465 int	fso = -1;
    466 
    467 /*
    468  * The BIG parameter is machine dependent.  It should be a longlong integer
    469  * constant that can be used by the number parser to check the validity
    470  * of numeric parameters.
    471  */
    472 
    473 #define	BIG		0x7fffffffffffffffLL
    474 
    475 /* Used to indicate to number() that a bogus value should cause us to exit */
    476 #define	NO_DEFAULT	LONG_MIN
    477 
    478 /*
    479  * INVALIDSBLIMIT is the number of bad backup superblocks that will be
    480  * tolerated before we decide to try arriving at a different set of them
    481  * using a different logic. This is applicable for non-EFI disks only.
    482  */
    483 #define	INVALIDSBLIMIT	10
    484 
    485 /*
    486  * The *_flag variables are used to indicate that the user specified
    487  * the values, rather than that we made them up ourselves.  We can
    488  * complain about the user giving us bogus values.
    489  */
    490 
    491 /* semi-constants */
    492 long	sectorsize = DEV_BSIZE;		/* bytes/sector from param.h */
    493 long	bbsize = BBSIZE;		/* boot block size */
    494 long	sbsize = SBSIZE;		/* superblock size */
    495 
    496 /* parameters */
    497 diskaddr_t	fssize_db;		/* file system size in disk blocks */
    498 diskaddr_t	fssize_frag;		/* file system size in frags */
    499 long	cpg;				/* cylinders/cylinder group */
    500 int	cpg_flag = RC_DEFAULT;
    501 long	rotdelay = -1;			/* rotational delay between blocks */
    502 int	rotdelay_flag = RC_DEFAULT;
    503 long	maxcontig;			/* max contiguous blocks to allocate */
    504 int	maxcontig_flag = RC_DEFAULT;
    505 long	nsect = DFLNSECT;		/* sectors per track */
    506 int	nsect_flag = RC_DEFAULT;
    507 long	ntrack = DFLNTRAK;		/* tracks per cylinder group */
    508 int	ntrack_flag = RC_DEFAULT;
    509 long	bsize = DESBLKSIZE;		/* filesystem block size */
    510 int	bsize_flag = RC_DEFAULT;
    511 long	fragsize = DESFRAGSIZE; 	/* filesystem fragment size */
    512 int	fragsize_flag = RC_DEFAULT;
    513 long	minfree = MINFREE; 		/* fs_minfree */
    514 int	minfree_flag = RC_DEFAULT;
    515 long	rps = DEFHZ;			/* revolutions/second of drive */
    516 int	rps_flag = RC_DEFAULT;
    517 long	nbpi = NBPI;			/* number of bytes per inode */
    518 int	nbpi_flag = RC_DEFAULT;
    519 long	nrpos = NRPOS;			/* number of rotational positions */
    520 int	nrpos_flag = RC_DEFAULT;
    521 long	apc = 0;			/* alternate sectors per cylinder */
    522 int	apc_flag = RC_DEFAULT;
    523 char	opt = 't';			/* optimization style, `t' or `s' */
    524 char	mtb = 'n';			/* multi-terabyte format, 'y' or 'n' */
    525 #define	DEFAULT_SECT_TRAK_CPG	(nsect_flag == RC_DEFAULT && \
    526 				ntrack_flag == RC_DEFAULT && \
    527 				cpg_flag == RC_DEFAULT)
    528 
    529 long	debug = 0;			/* enable debugging output */
    530 
    531 int	spc_flag = 0;			/* alternate sectors specified or */
    532 					/* found */
    533 
    534 /* global state */
    535 int	Nflag;		/* do not write to disk */
    536 int	mflag;		/* return the command line used to create this FS */
    537 int	rflag;		/* report the superblock in an easily-parsed form */
    538 int	Rflag;		/* dump the superblock in binary */
    539 char	*fsys;
    540 time_t	mkfstime;
    541 char	*string;
    542 int	label_type;
    543 
    544 /*
    545  * logging support
    546  */
    547 int	ismdd;			/* true if device is a SVM device */
    548 int	islog;			/* true if ufs or SVM logging is enabled */
    549 int	islogok;		/* true if ufs/SVM log state is good */
    550 
    551 static int	isufslog;	/* true if ufs logging is enabled */
    552 static int	waslog;		/* true when ufs logging disabled during grow */
    553 
    554 /*
    555  * growfs defines, globals, and forward references
    556  */
    557 #define	NOTENOUGHSPACE 33
    558 int		grow;
    559 #define	GROW_WITH_DEFAULT_TRAK	(grow && ntrack_flag == RC_DEFAULT)
    560 
    561 static int	Pflag;		/* probe to which size the fs can be grown */
    562 int		ismounted;
    563 char		*directory;
    564 diskaddr_t	grow_fssize;
    565 long		grow_fs_size;
    566 long		grow_fs_ncg;
    567 diskaddr_t		grow_fs_csaddr;
    568 long		grow_fs_cssize;
    569 int		grow_fs_clean;
    570 struct csum	*grow_fscs;
    571 diskaddr_t		grow_sifrag;
    572 int		test;
    573 int		testforce;
    574 diskaddr_t		testfrags;
    575 int		inlockexit;
    576 int		isbad;
    577 
    578 void		lockexit(int);
    579 void		randomgeneration(void);
    580 void		checksummarysize(void);
    581 int		checksblock(struct fs, int);
    582 void		growinit(char *);
    583 void		checkdev(char *, char  *);
    584 void		checkmount(struct mnttab *, char *);
    585 struct dinode	*gdinode(ino_t);
    586 int		csfraginrange(daddr32_t);
    587 struct csfrag	*findcsfrag(daddr32_t, struct csfrag **);
    588 void		checkindirect(ino_t, daddr32_t *, daddr32_t, int);
    589 void		addcsfrag(ino_t, daddr32_t, struct csfrag **);
    590 void		delcsfrag(daddr32_t, struct csfrag **);
    591 void		checkdirect(ino_t, daddr32_t *, daddr32_t *, int);
    592 void		findcsfragino(void);
    593 void		fixindirect(daddr32_t, int);
    594 void		fixdirect(caddr_t, daddr32_t, daddr32_t *, int);
    595 void		fixcsfragino(void);
    596 void		extendsummaryinfo(void);
    597 int		notenoughspace(void);
    598 void		unalloccsfragino(void);
    599 void		unalloccsfragfree(void);
    600 void		findcsfragfree(void);
    601 void		copycsfragino(void);
    602 void		rdcg(long);
    603 void		wtcg(void);
    604 void		flcg(void);
    605 void		allocfrags(long, daddr32_t *, long *);
    606 void		alloccsfragino(void);
    607 void		alloccsfragfree(void);
    608 void		freefrags(daddr32_t, long, long);
    609 int		findfreerange(long *, long *);
    610 void		resetallocinfo(void);
    611 void		extendcg(long);
    612 void		ulockfs(void);
    613 void		wlockfs(void);
    614 void		clockfs(void);
    615 void		wtsb(void);
    616 static int64_t	checkfragallocated(daddr32_t);
    617 static struct csum 	*read_summaryinfo(struct fs *);
    618 static diskaddr_t 	probe_summaryinfo();
    619 
    620 int
    621 main(int argc, char *argv[])
    622 {
    623 	long i, mincpc, mincpg, ibpcl;
    624 	long cylno, rpos, blk, j, warn = 0;
    625 	long mincpgcnt, maxcpg;
    626 	uint64_t used, bpcg, inospercg;
    627 	long mapcramped, inodecramped;
    628 	long postblsize, rotblsize, totalsbsize;
    629 	FILE *mnttab;
    630 	struct mnttab mntp;
    631 	char *special;
    632 	struct statvfs64 fs;
    633 	struct dk_geom dkg;
    634 	struct dk_cinfo dkcinfo;
    635 	struct dk_minfo dkminfo;
    636 	char pbuf[sizeof (uint64_t) * 3 + 1];
    637 	char *tmpbuf;
    638 	int width, plen;
    639 	uint64_t num;
    640 	int c, saverr;
    641 	diskaddr_t max_fssize;
    642 	long tmpmaxcontig = -1;
    643 	struct sigaction sigact;
    644 	uint64_t nbytes64;
    645 	int remaining_cg;
    646 	int do_dot = 0;
    647 	int use_efi_dflts = 0, retry = 0, isremovable = 0, ishotpluggable = 0;
    648 	int invalid_sb_cnt, ret, skip_this_sb, cg_too_small;
    649 	int geom_nsect, geom_ntrack, geom_cpg;
    650 
    651 	(void) setlocale(LC_ALL, "");
    652 
    653 #if !defined(TEXT_DOMAIN)
    654 #define	TEXT_DOMAIN "SYS_TEST"
    655 #endif
    656 	(void) textdomain(TEXT_DOMAIN);
    657 
    658 	while ((c = getopt(argc, argv, "F:bmo:VPGM:T:t:")) != EOF) {
    659 		switch (c) {
    660 
    661 		case 'F':
    662 			string = optarg;
    663 			if (strcmp(string, "ufs") != 0)
    664 				usage();
    665 			break;
    666 
    667 		case 'm':	/* return command line used to create this FS */
    668 			mflag++;
    669 			break;
    670 
    671 		case 'o':
    672 			/*
    673 			 * ufs specific options.
    674 			 */
    675 			string = optarg;
    676 			while (*string != '\0') {
    677 				if (match("nsect=")) {
    678 					nsect = number(DFLNSECT, "nsect", 0);
    679 					nsect_flag = RC_KEYWORD;
    680 				} else if (match("ntrack=")) {
    681 					ntrack = number(DFLNTRAK, "ntrack", 0);
    682 					ntrack_flag = RC_KEYWORD;
    683 				} else if (match("bsize=")) {
    684 					bsize = number(DESBLKSIZE, "bsize", 0);
    685 					bsize_flag = RC_KEYWORD;
    686 				} else if (match("fragsize=")) {
    687 					fragsize = number(DESFRAGSIZE,
    688 					    "fragsize", 0);
    689 					fragsize_flag = RC_KEYWORD;
    690 				} else if (match("cgsize=")) {
    691 					cpg = number(DESCPG, "cgsize", 0);
    692 					cpg_flag = RC_KEYWORD;
    693 				} else if (match("free=")) {
    694 					minfree = number(MINFREE, "free",
    695 					    ALLOW_PERCENT);
    696 					minfree_flag = RC_KEYWORD;
    697 				} else if (match("maxcontig=")) {
    698 					tmpmaxcontig =
    699 					    number(-1, "maxcontig", 0);
    700 					maxcontig_flag = RC_KEYWORD;
    701 				} else if (match("nrpos=")) {
    702 					nrpos = number(NRPOS, "nrpos", 0);
    703 					nrpos_flag = RC_KEYWORD;
    704 				} else if (match("rps=")) {
    705 					rps = number(DEFHZ, "rps", 0);
    706 					rps_flag = RC_KEYWORD;
    707 				} else if (match("nbpi=")) {
    708 					nbpi = number(NBPI, "nbpi", 0);
    709 					nbpi_flag = RC_KEYWORD;
    710 				} else if (match("opt=")) {
    711 					opt = checkopt(string);
    712 				} else if (match("mtb=")) {
    713 					mtb = checkmtb(string);
    714 				} else if (match("apc=")) {
    715 					apc = number(0, "apc", 0);
    716 					apc_flag = RC_KEYWORD;
    717 				} else if (match("gap=")) {
    718 					(void) number(0, "gap", ALLOW_MS1);
    719 					rotdelay = ROTDELAY;
    720 					rotdelay_flag = RC_DEFAULT;
    721 				} else if (match("debug=")) {
    722 					debug = number(0, "debug", 0);
    723 				} else if (match("N")) {
    724 					Nflag++;
    725 				} else if (match("calcsb")) {
    726 					rflag++;
    727 					Nflag++;
    728 				} else if (match("calcbinsb")) {
    729 					rflag++;
    730 					Rflag++;
    731 					Nflag++;
    732 				} else if (*string == '\0') {
    733 					break;
    734 				} else {
    735 					(void) fprintf(stderr, gettext(
    736 					    "illegal option: %s\n"), string);
    737 					usage();
    738 				}
    739 
    740 				if (*string == ',') string++;
    741 				if (*string == ' ') string++;
    742 			}
    743 			break;
    744 
    745 		case 'V':
    746 			{
    747 				char	*opt_text;
    748 				int	opt_count;
    749 
    750 				(void) fprintf(stdout, gettext("mkfs -F ufs "));
    751 				for (opt_count = 1; opt_count < argc;
    752 				    opt_count++) {
    753 					opt_text = argv[opt_count];
    754 					if (opt_text)
    755 						(void) fprintf(stdout, " %s ",
    756 						    opt_text);
    757 				}
    758 				(void) fprintf(stdout, "\n");
    759 			}
    760 			break;
    761 
    762 		case 'b':	/* do nothing for this */
    763 			break;
    764 
    765 		case 'M':	/* grow the mounted file system */
    766 			directory = optarg;
    767 
    768 			/* FALLTHROUGH */
    769 		case 'G':	/* grow the file system */
    770 			grow = 1;
    771 			break;
    772 		case 'P':	/* probe the file system growing size 	*/
    773 			Pflag = 1;
    774 			grow = 1; /* probe mode implies fs growing	*/
    775 			break;
    776 		case 'T':	/* For testing */
    777 			testforce = 1;
    778 
    779 			/* FALLTHROUGH */
    780 		case 't':
    781 			test = 1;
    782 			string = optarg;
    783 			testfrags = number(NO_DEFAULT, "testfrags", 0);
    784 			break;
    785 
    786 		case '?':
    787 			usage();
    788 			break;
    789 		}
    790 	}
    791 #ifdef MKFS_DEBUG
    792 	/*
    793 	 * Turning on MKFS_DEBUG causes mkfs to produce a filesystem
    794 	 * that can be reproduced by setting the time to 0 and seeding
    795 	 * the random number generator to a constant.
    796 	 */
    797 	mkfstime = 0;	/* reproducible results */
    798 #else
    799 	(void) time(&mkfstime);
    800 #endif
    801 
    802 	if (optind >= (argc - 1)) {
    803 		if (optind > (argc - 1)) {
    804 			(void) fprintf(stderr,
    805 			    gettext("special not specified\n"));
    806 			usage();
    807 		} else if (mflag == 0) {
    808 			(void) fprintf(stderr,
    809 			    gettext("size not specified\n"));
    810 			usage();
    811 		}
    812 	}
    813 	argc -= optind;
    814 	argv = &argv[optind];
    815 
    816 	fsys = argv[0];
    817 	fsi = open64(fsys, O_RDONLY);
    818 	if (fsi < 0) {
    819 		(void) fprintf(stderr, gettext("%s: cannot open\n"), fsys);
    820 		lockexit(32);
    821 	}
    822 
    823 	if (mflag) {
    824 		dump_fscmd(fsys, fsi);
    825 		lockexit(0);
    826 	}
    827 
    828 	/*
    829 	 * The task of setting all of the configuration parameters for a
    830 	 * UFS file system is basically a matter of solving n equations
    831 	 * in m variables.  Typically, m is greater than n, so there is
    832 	 * usually more than one valid solution.  Since this is usually
    833 	 * an under-constrained problem, it's not always obvious what the
    834 	 * "best" configuration is.
    835 	 *
    836 	 * In general, the approach is to
    837 	 * 1. Determine the values for the file system parameters
    838 	 *    that are externally contrained and therefore not adjustable
    839 	 *    by mkfs (such as the device's size and maxtransfer size).
    840 	 * 2. Acquire the user's requested setting for all configuration
    841 	 *    values that can be set on the command line.
    842 	 * 3. Determine the final value of all configuration values, by
    843 	 *    the following approach:
    844 	 *	- set the file system block size (fs_bsize).  Although
    845 	 *	  this could be regarded as an adjustable parameter, in
    846 	 *	  fact, it's pretty much a constant.  At this time, it's
    847 	 *	  generally set to 8k (with older hardware, it can
    848 	 *	  sometimes make sense to set it to 4k, but those
    849 	 *	  situations are pretty rare now).
    850 	 *	- re-adjust the maximum file system size based on the
    851 	 *	  value of the file system block size.  Since the
    852 	 *	  frag size can't be any larger than a file system
    853 	 *	  block, and the number of frags in the file system
    854 	 *	  has to fit into 31 bits, the file system block size
    855 	 *	  affects the maximum file system size.
    856 	 *	- now that the real maximum file system is known, set the
    857 	 *	  actual size of the file system to be created to
    858 	 *	  MIN(requested size, maximum file system size).
    859 	 *	- now validate, and if necessary, adjust the following
    860 	 *	  values:
    861 	 *		rotdelay
    862 	 *		nsect
    863 	 *		maxcontig
    864 	 *		apc
    865 	 *		frag_size
    866 	 *		rps
    867 	 *		minfree
    868 	 *		nrpos
    869 	 *		nrack
    870 	 *		nbpi
    871 	 *	- calculate maxcpg (the maximum value of the cylinders-per-
    872 	 *	  cylinder-group configuration parameters).  There are two
    873 	 *	  algorithms for calculating maxcpg:  an old one, which is
    874 	 *	  used for file systems of less than 1 terabyte, and a
    875 	 *	  new one, implemented in the function compute_maxcpg(),
    876 	 *	  which is used for file systems of greater than 1 TB.
    877 	 *	  The difference between them is that compute_maxcpg()
    878 	 *	  really tries to maximize the cpg value.  The old
    879 	 *	  algorithm fails to take advantage of smaller frags and
    880 	 *	  lower inode density when determining the maximum cpg,
    881 	 *	  and thus comes up with much lower numbers in some
    882 	 *	  configurations.  At some point, we might use the
    883 	 *	  new algorithm for determining maxcpg for all file
    884 	 *	  systems, but at this time, the changes implemented for
    885 	 *	  multi-terabyte UFS are NOT being automatically applied
    886 	 *	  to UFS file systems of less than a terabyte (in the
    887 	 *	  interest of not changing existing UFS policy too much
    888 	 *	  until the ramifications of the changes are well-understood
    889 	 *	  and have been evaluated for their effects on performance.)
    890 	 *	- check the current values of the configuration parameters
    891 	 *	  against the various constraints imposed by UFS.  These
    892 	 *	  include:
    893 	 *		* There must be at least one inode in each
    894 	 *		  cylinder group.
    895 	 *		* The cylinder group overhead block, which
    896 	 *		  contains the inode and frag bigmaps, must fit
    897 	 *		  within one file system block.
    898 	 *		* The space required for inode maps should
    899 	 *		  occupy no more than a third of the cylinder
    900 	 *		  group overhead block.
    901 	 *		* The rotational position tables have to fit
    902 	 *		  within the available space in the super block.
    903 	 *	  Adjust the configuration values that can be adjusted
    904 	 *	  so that these constraints are satisfied.  The
    905 	 *	  configuration values that are adjustable are:
    906 	 *		* frag size
    907 	 *		* cylinders per group
    908 	 *		* inode density (can be increased)
    909 	 *		* number of rotational positions (the rotational
    910 	 *		  position tables are eliminated altogether if
    911 	 *		  there isn't enough room for them.)
    912 	 * 4. Set the values for all the dependent configuration
    913 	 *    values (those that aren't settable on the command
    914 	 *    line and which are completely dependent on the
    915 	 *    adjustable parameters).  This include cpc (cycles
    916 	 *    per cylinder, spc (sectors-per-cylinder), and many others.
    917 	 */
    918 
    919 	/*
    920 	 * Figure out the partition size and initialize the label_type.
    921 	 */
    922 	max_fssize = get_max_size(fsi);
    923 
    924 	/*
    925 	 * Get and check positional arguments, if any.
    926 	 */
    927 	switch (argc - 1) {
    928 	default:
    929 		usage();
    930 		/*NOTREACHED*/
    931 	case 15:
    932 		mtb = checkmtb(argv[15]);
    933 		/* FALLTHROUGH */
    934 	case 14:
    935 		string = argv[14];
    936 		tmpmaxcontig = number(-1, "maxcontig", 0);
    937 		maxcontig_flag = RC_POSITIONAL;
    938 		/* FALLTHROUGH */
    939 	case 13:
    940 		string = argv[13];
    941 		nrpos = number(NRPOS, "nrpos", 0);
    942 		nrpos_flag = RC_POSITIONAL;
    943 		/* FALLTHROUGH */
    944 	case 12:
    945 		string = argv[12];
    946 		rotdelay = ROTDELAY;
    947 		rotdelay_flag = RC_DEFAULT;
    948 		/* FALLTHROUGH */
    949 	case 11:
    950 		string = argv[11];
    951 		apc = number(0, "apc", 0);
    952 		apc_flag = RC_POSITIONAL;
    953 		/* FALLTHROUGH */
    954 	case 10:
    955 		opt = checkopt(argv[10]);
    956 		/* FALLTHROUGH */
    957 	case 9:
    958 		string = argv[9];
    959 		nbpi = number(NBPI, "nbpi", 0);
    960 		nbpi_flag = RC_POSITIONAL;
    961 		/* FALLTHROUGH */
    962 	case 8:
    963 		string = argv[8];
    964 		rps = number(DEFHZ, "rps", 0);
    965 		rps_flag = RC_POSITIONAL;
    966 		/* FALLTHROUGH */
    967 	case 7:
    968 		string = argv[7];
    969 		minfree = number(MINFREE, "free", ALLOW_PERCENT);
    970 		minfree_flag = RC_POSITIONAL;
    971 		/* FALLTHROUGH */
    972 	case 6:
    973 		string = argv[6];
    974 		cpg = number(DESCPG, "cgsize", 0);
    975 		cpg_flag = RC_POSITIONAL;
    976 		/* FALLTHROUGH */
    977 	case 5:
    978 		string = argv[5];
    979 		fragsize = number(DESFRAGSIZE, "fragsize", 0);
    980 		fragsize_flag = RC_POSITIONAL;
    981 		/* FALLTHROUGH */
    982 	case 4:
    983 		string = argv[4];
    984 		bsize = number(DESBLKSIZE, "bsize", 0);
    985 		bsize_flag = RC_POSITIONAL;
    986 		/* FALLTHROUGH */
    987 	case 3:
    988 		string = argv[3];
    989 		ntrack = number(DFLNTRAK, "ntrack", 0);
    990 		ntrack_flag = RC_POSITIONAL;
    991 		/* FALLTHROUGH */
    992 	case 2:
    993 		string = argv[2];
    994 		nsect = number(DFLNSECT, "nsect", 0);
    995 		nsect_flag = RC_POSITIONAL;
    996 		/* FALLTHROUGH */
    997 	case 1:
    998 		string = argv[1];
    999 		fssize_db = number(max_fssize, "size", 0);
   1000 	}
   1001 
   1002 	/*
   1003 	 * Initialize the parameters in the same way as newfs so that
   1004 	 * newfs and mkfs would result in the same file system layout
   1005 	 * for EFI labelled disks. Do this only in the absence of user
   1006 	 * specified values for these parameters.
   1007 	 */
   1008 	if (label_type == LABEL_TYPE_EFI) {
   1009 		if (apc_flag == RC_DEFAULT) apc = 0;
   1010 		if (nrpos_flag == RC_DEFAULT) nrpos = 1;
   1011 		if (ntrack_flag == RC_DEFAULT) ntrack = DEF_TRACKS_EFI;
   1012 		if (rps_flag == RC_DEFAULT) rps = DEFHZ;
   1013 		if (nsect_flag == RC_DEFAULT) nsect = DEF_SECTORS_EFI;
   1014 	}
   1015 
   1016 	if ((maxcontig_flag == RC_DEFAULT) || (tmpmaxcontig == -1) ||
   1017 	    (maxcontig == -1)) {
   1018 		long maxtrax = get_max_track_size(fsi);
   1019 		maxcontig = maxtrax / bsize;
   1020 
   1021 	} else {
   1022 		maxcontig = tmpmaxcontig;
   1023 	}
   1024 	dprintf(("DeBuG maxcontig : %ld\n", maxcontig));
   1025 
   1026 	if (rotdelay == -1) {	/* default by newfs and mkfs */
   1027 		rotdelay = ROTDELAY;
   1028 	}
   1029 
   1030 	if (cpg_flag == RC_DEFAULT) { /* If not explicity set, use default */
   1031 		cpg = DESCPG;
   1032 	}
   1033 	dprintf(("DeBuG cpg : %ld\n", cpg));
   1034 
   1035 	/*
   1036 	 * Now that we have the semi-sane args, either positional, via -o,
   1037 	 * or by defaulting, handle inter-dependencies and range checks.
   1038 	 */
   1039 
   1040 	/*
   1041 	 * Settle the file system block size first, since it's a fixed
   1042 	 * parameter once set and so many other parameters, including
   1043 	 * max_fssize, depend on it.
   1044 	 */
   1045 	range_check(&bsize, "bsize", MINBSIZE, MAXBSIZE, DESBLKSIZE,
   1046 	    bsize_flag);
   1047 
   1048 	if (!POWEROF2(bsize)) {
   1049 		(void) fprintf(stderr,
   1050 		    gettext("block size must be a power of 2, not %ld\n"),
   1051 		    bsize);
   1052 		bsize = DESBLKSIZE;
   1053 		(void) fprintf(stderr,
   1054 		    gettext("mkfs: bsize reset to default %ld\n"),
   1055 		    bsize);
   1056 	}
   1057 
   1058 	if (fssize_db > max_fssize && validate_size(fsi, fssize_db)) {
   1059 		(void) fprintf(stderr, gettext(
   1060 		    "Warning: the requested size of this file system\n"
   1061 		    "(%lld sectors) is greater than the size of the\n"
   1062 		    "device reported by the driver (%lld sectors).\n"
   1063 		    "However, a read of the device at the requested size\n"
   1064 		    "does succeed, so the requested size will be used.\n"),
   1065 		    fssize_db, max_fssize);
   1066 		max_fssize = fssize_db;
   1067 	}
   1068 	/*
   1069 	 * Since the maximum allocatable unit (the frag) must be less than
   1070 	 * or equal to bsize, and the number of frags must be less than or
   1071 	 * equal to INT_MAX, the total size of the file system (in
   1072 	 * bytes) must be less than or equal to bsize * INT_MAX.
   1073 	 */
   1074 
   1075 	if (max_fssize > ((diskaddr_t)bsize/DEV_BSIZE) * INT_MAX)
   1076 		max_fssize = ((diskaddr_t)bsize/DEV_BSIZE) * INT_MAX;
   1077 
   1078 	range_check_64(&fssize_db, "size", 1024LL, max_fssize, max_fssize, 1);
   1079 
   1080 	if (fssize_db >= SECTORS_PER_TERABYTE) {
   1081 		mtb = 'y';
   1082 		if (!in_64bit_mode()) {
   1083 			(void) fprintf(stderr, gettext(
   1084 "mkfs:  Warning: Creating a file system greater than 1 terabyte on a\n"
   1085 "       system running a 32-bit kernel.  This file system will not be\n"
   1086 "       accessible until the system is rebooted with a 64-bit kernel.\n"));
   1087 		}
   1088 	}
   1089 	dprintf(("DeBuG mtb : %c\n", mtb));
   1090 
   1091 	/*
   1092 	 * With newer and much larger disks, the newfs(1M) and mkfs_ufs(1M)
   1093 	 * commands had problems in correctly handling the "native" geometries
   1094 	 * for various storage devices.
   1095 	 *
   1096 	 * To handle the new age disks, mkfs_ufs(1M) will use the EFI style
   1097 	 * for non-EFI disks that are larger than the CHS addressing limit
   1098 	 * ( > 8GB approx ) and ignore the disk geometry information for
   1099 	 * these drives. This is what is currently done for multi-terrabyte
   1100 	 * filesystems on EFI disks.
   1101 	 *
   1102 	 * However if the user asked for a specific layout by supplying values
   1103 	 * for even one of the three parameters (nsect, ntrack, cpg), honour
   1104 	 * the user supplied parameters.
   1105 	 *
   1106 	 * Choosing EFI style or native geometry style can make a lot of
   1107 	 * difference, because the size of a cylinder group is dependent on
   1108 	 * this choice. This in turn means that the position of alternate
   1109 	 * superblocks varies depending on the style chosen. It is not
   1110 	 * necessary that all disks of size > CHSLIMIT have EFI style layout.
   1111 	 * There can be disks which are > CHSLIMIT size, but have native
   1112 	 * geometry style layout, thereby warranting the need for alternate
   1113 	 * logic in superblock detection.
   1114 	 */
   1115 	if (mtb != 'y' && (ntrack == -1 || GROW_WITH_DEFAULT_TRAK ||
   1116 	    DEFAULT_SECT_TRAK_CPG)) {
   1117 		/*
   1118 		 * "-1" indicates that we were called from newfs and ntracks
   1119 		 * was not specified in newfs command line. Calculate nsect
   1120 		 * and ntrack in the same manner as newfs.
   1121 		 *
   1122 		 * This is required because, the defaults for nsect and ntrack
   1123 		 * is hardcoded in mkfs, whereas to generate the alternate
   1124 		 * superblock locations for the -N option, there is a need for
   1125 		 * the geometry based values that newfs would have arrived at.
   1126 		 * Newfs would have arrived at these values as below.
   1127 		 */
   1128 		if (label_type == LABEL_TYPE_EFI ||
   1129 		    label_type == LABEL_TYPE_OTHER) {
   1130 			use_efi_dflts = 1;
   1131 			retry = 1;
   1132 		} else if (ioctl(fsi, DKIOCGGEOM, &dkg)) {
   1133 			dprintf(("%s: Unable to read Disk geometry", fsys));
   1134 			perror(gettext("Unable to read Disk geometry"));
   1135 			lockexit(32);
   1136 		} else {
   1137 			nsect = dkg.dkg_nsect;
   1138 			ntrack = dkg.dkg_nhead;
   1139 #ifdef i386	/* Bug 1170182 */
   1140 			if (ntrack > 32 && (ntrack % 16) != 0) {
   1141 				ntrack -= (ntrack % 16);
   1142 			}
   1143 #endif
   1144 			if (ioctl(fsi, DKIOCREMOVABLE, &isremovable)) {
   1145 				dprintf(("DeBuG Unable to determine if %s is"
   1146 				    " Removable Media. Proceeding with system"
   1147 				    " determined parameters.\n", fsys));
   1148 				isremovable = 0;
   1149 			}
   1150 			if (ioctl(fsi, DKIOCHOTPLUGGABLE, &ishotpluggable)) {
   1151 				dprintf(("DeBuG Unable to determine if %s is"
   1152 				    " Hotpluggable Media. Proceeding with "
   1153 				    "system determined parameters.\n", fsys));
   1154 				ishotpluggable = 0;
   1155 			}
   1156 			if ((((diskaddr_t)dkg.dkg_ncyl * dkg.dkg_nhead *
   1157 			    dkg.dkg_nsect) > CHSLIMIT) || isremovable ||
   1158 			    ishotpluggable) {
   1159 				use_efi_dflts = 1;
   1160 				retry = 1;
   1161 			}
   1162 		}
   1163 	}
   1164 	dprintf(("DeBuG CHSLIMIT = %d geom = %llu\n", CHSLIMIT,
   1165 	    (diskaddr_t)dkg.dkg_ncyl * dkg.dkg_nhead * dkg.dkg_nsect));
   1166 	dprintf(("DeBuG label_type = %d isremovable = %d ishotpluggable = %d "
   1167 	    "use_efi_dflts = %d\n", label_type, isremovable, ishotpluggable,
   1168 	    use_efi_dflts));
   1169 
   1170 	/*
   1171 	 * For the newfs -N case, even if the disksize is > CHSLIMIT, do not
   1172 	 * blindly follow EFI style. If the fs_version indicates a geometry
   1173 	 * based layout, try that one first. If it fails we can always try the
   1174 	 * other logic.
   1175 	 *
   1176 	 * If we were called from growfs, we will have a problem if we mix
   1177 	 * and match the filesystem creation and growth styles. For example,
   1178 	 * if we create using EFI style, we have to also grow using EFI
   1179 	 * style. So follow the style indicated by the fs_version.
   1180 	 *
   1181 	 * Read and verify the primary superblock. If it looks sane, use the
   1182 	 * fs_version from the superblock. If the primary superblock does
   1183 	 * not look good, read and verify the first alternate superblock at
   1184 	 * ALTSB. Use the fs_version to decide whether to use the
   1185 	 * EFI style logic or the old geometry based logic to calculate
   1186 	 * the alternate superblock locations.
   1187 	 */
   1188 	if ((Nflag && use_efi_dflts) || (grow)) {
   1189 		if (grow && ntrack_flag != RC_DEFAULT)
   1190 			goto start_fs_creation;
   1191 		rdfs((diskaddr_t)(SBOFF / sectorsize), (int)sbsize,
   1192 		    (char *)&altsblock);
   1193 		ret = checksblock(altsblock, 1);
   1194 
   1195 		if (!ret) {
   1196 			if (altsblock.fs_magic == MTB_UFS_MAGIC) {
   1197 				mtb = 'y';
   1198 				goto start_fs_creation;
   1199 			}
   1200 			use_efi_dflts = (altsblock.fs_version ==
   1201 			    UFS_EFISTYLE4NONEFI_VERSION_2) ? 1 : 0;
   1202 		} else {
   1203 			/*
   1204 			 * The primary superblock didn't help in determining
   1205 			 * the fs_version. Try the first alternate superblock.
   1206 			 */
   1207 			dprintf(("DeBuG checksblock() failed - error : %d"
   1208 			    " for sb : %d\n", ret, SBOFF/sectorsize));
   1209 			rdfs((diskaddr_t)ALTSB, (int)sbsize,
   1210 			    (char *)&altsblock);
   1211 			ret = checksblock(altsblock, 1);
   1212 
   1213 			if (!ret) {
   1214 				if (altsblock.fs_magic == MTB_UFS_MAGIC) {
   1215 					mtb = 'y';
   1216 					goto start_fs_creation;
   1217 				}
   1218 				use_efi_dflts = (altsblock.fs_version ==
   1219 				    UFS_EFISTYLE4NONEFI_VERSION_2) ? 1 : 0;
   1220 			}
   1221 			dprintf(("DeBuG checksblock() returned : %d"
   1222 			    " for sb : %d\n", ret, ALTSB));
   1223 		}
   1224 	}
   1225 
   1226 	geom_nsect = nsect;
   1227 	geom_ntrack = ntrack;
   1228 	geom_cpg = cpg;
   1229 	dprintf(("DeBuG geom_nsect=%d, geom_ntrack=%d, geom_cpg=%d\n",
   1230 	    geom_nsect, geom_ntrack, geom_cpg));
   1231 
   1232 start_fs_creation:
   1233 retry_alternate_logic:
   1234 	invalid_sb_cnt = 0;
   1235 	cg_too_small = 0;
   1236 	if (use_efi_dflts) {
   1237 		nsect = DEF_SECTORS_EFI;
   1238 		ntrack = DEF_TRACKS_EFI;
   1239 		cpg = DESCPG;
   1240 		dprintf(("\nDeBuG Using EFI defaults\n"));
   1241 	} else {
   1242 		nsect = geom_nsect;
   1243 		ntrack = geom_ntrack;
   1244 		cpg = geom_cpg;
   1245 		dprintf(("\nDeBuG Using Geometry\n"));
   1246 		/*
   1247 		 * 32K based on max block size of 64K, and rotational layout
   1248 		 * test of nsect <= (256 * sectors/block).  Current block size
   1249 		 * limit is not 64K, but it's growing soon.
   1250 		 */
   1251 		range_check(&nsect, "nsect", 1, 32768, DFLNSECT, nsect_flag);
   1252 		/*
   1253 		 * ntrack is the number of tracks per cylinder.
   1254 		 * The ntrack value must be between 1 and the total number of
   1255 		 * sectors in the file system.
   1256 		 */
   1257 		range_check(&ntrack, "ntrack", 1,
   1258 		    fssize_db > INT_MAX ? INT_MAX : (uint32_t)fssize_db,
   1259 		    DFLNTRAK, ntrack_flag);
   1260 	}
   1261 
   1262 	range_check(&apc, "apc", 0, nsect - 1, 0, apc_flag);
   1263 
   1264 	if (mtb == 'y')
   1265 		fragsize = bsize;
   1266 
   1267 	range_check(&fragsize, "fragsize", sectorsize, bsize,
   1268 	    MAX(bsize / MAXFRAG, MIN(DESFRAGSIZE, bsize)), fragsize_flag);
   1269 
   1270 	if ((bsize / MAXFRAG) > fragsize) {
   1271 		(void) fprintf(stderr, gettext(
   1272 "fragment size %ld is too small, minimum with block size %ld is %ld\n"),
   1273 		    fragsize, bsize, bsize / MAXFRAG);
   1274 		(void) fprintf(stderr,
   1275 		    gettext("mkfs: fragsize reset to minimum %ld\n"),
   1276 		    bsize / MAXFRAG);
   1277 		fragsize = bsize / MAXFRAG;
   1278 	}
   1279 
   1280 	if (!POWEROF2(fragsize)) {
   1281 		(void) fprintf(stderr,
   1282 		    gettext("fragment size must be a power of 2, not %ld\n"),
   1283 		    fragsize);
   1284 		fragsize = MAX(bsize / MAXFRAG, MIN(DESFRAGSIZE, bsize));
   1285 		(void) fprintf(stderr,
   1286 		    gettext("mkfs: fragsize reset to %ld\n"),
   1287 		    fragsize);
   1288 	}
   1289 
   1290 	/* At this point, bsize must be >= fragsize, so no need to check it */
   1291 
   1292 	if (bsize < PAGESIZE) {
   1293 		(void) fprintf(stderr, gettext(
   1294 		    "WARNING: filesystem block size (%ld) is smaller than "
   1295 		    "memory page size (%ld).\nResulting filesystem can not be "
   1296 		    "mounted on this system.\n\n"),
   1297 		    bsize, (long)PAGESIZE);
   1298 	}
   1299 
   1300 	range_check(&rps, "rps", 1, 1000, DEFHZ, rps_flag);
   1301 	range_check(&minfree, "free", 0, 99, MINFREE, minfree_flag);
   1302 	range_check(&nrpos, "nrpos", 1, nsect, MIN(nsect, NRPOS), nrpos_flag);
   1303 
   1304 	/*
   1305 	 * nbpi is variable, but 2MB seems a reasonable upper limit,
   1306 	 * as 4MB tends to cause problems (using otherwise-default
   1307 	 * parameters).  The true limit is where we end up with one
   1308 	 * inode per cylinder group.  If this file system is being
   1309 	 * configured for multi-terabyte access, nbpi must be at least 1MB.
   1310 	 */
   1311 	if (mtb == 'y' && nbpi < MTB_NBPI) {
   1312 		if (nbpi_flag != RC_DEFAULT)
   1313 			(void) fprintf(stderr, gettext("mkfs: bad value for "
   1314 			    "nbpi: must be at least 1048576 for multi-terabyte,"
   1315 			    " nbpi reset to default 1048576\n"));
   1316 		nbpi = MTB_NBPI;
   1317 	}
   1318 
   1319 	if (mtb == 'y')
   1320 		range_check(&nbpi, "nbpi", MTB_NBPI, 2 * MB, MTB_NBPI,
   1321 		    nbpi_flag);
   1322 	else
   1323 		range_check(&nbpi, "nbpi", DEV_BSIZE, 2 * MB, NBPI, nbpi_flag);
   1324 
   1325 	/*
   1326 	 * maxcpg is another variably-limited parameter.  Calculate
   1327 	 * the limit based on what we've got for its dependent
   1328 	 * variables.  Effectively, it's how much space is left in the
   1329 	 * superblock after all the other bits are accounted for.  We
   1330 	 * only fill in sblock fields so we can use MAXIpG.
   1331 	 *
   1332 	 * If the calculation of maxcpg below (for the mtb == 'n'
   1333 	 * case) is changed, update newfs as well.
   1334 	 *
   1335 	 * For old-style, non-MTB format file systems, use the old
   1336 	 * algorithm for calculating the maximum cylinder group size,
   1337 	 * even though it limits the cylinder group more than necessary.
   1338 	 * Since layout can affect performance, we don't want to change
   1339 	 * the default layout for non-MTB file systems at this time.
   1340 	 * However, for MTB file systems, use the new maxcpg calculation,
   1341 	 * which really maxes out the cylinder group size.
   1342 	 */
   1343 
   1344 	sblock.fs_bsize = bsize;
   1345 	sblock.fs_inopb = sblock.fs_bsize / sizeof (struct dinode);
   1346 
   1347 	if (mtb == 'n') {
   1348 		maxcpg = (bsize - sizeof (struct cg) -
   1349 		    howmany(MAXIpG(&sblock), NBBY)) /
   1350 		    (sizeof (long) + nrpos * sizeof (short) +
   1351 		    nsect / (MAXFRAG * NBBY));
   1352 	} else {
   1353 		maxcpg = compute_maxcpg(bsize, fragsize, nbpi, nrpos,
   1354 		    nsect * ntrack);
   1355 	}
   1356 
   1357 	dprintf(("DeBuG cpg : %ld\n", cpg));
   1358 	/*
   1359 	 * Increase the cpg to maxcpg if either newfs was invoked
   1360 	 * with -T option or if mkfs wants to create a mtb file system
   1361 	 * and if the user has not specified the cpg.
   1362 	 */
   1363 	if (cpg == -1 || (mtb == 'y' && cpg_flag == RC_DEFAULT))
   1364 		cpg = maxcpg;
   1365 	dprintf(("DeBuG cpg : %ld\n", cpg));
   1366 
   1367 	/*
   1368 	 * mincpg is variable in complex ways, so we really can't
   1369 	 * do a sane lower-end limit check at this point.
   1370 	 */
   1371 	range_check(&cpg, "cgsize", 1, maxcpg, MIN(maxcpg, DESCPG), cpg_flag);
   1372 
   1373 	/*
   1374 	 * get the controller info
   1375 	 */
   1376 	ismdd = 0;
   1377 	islog = 0;
   1378 	islogok = 0;
   1379 	waslog = 0;
   1380 
   1381 	if (ioctl(fsi, DKIOCINFO, &dkcinfo) == 0)
   1382 		/*
   1383 		 * if it is an MDD (disksuite) device
   1384 		 */
   1385 		if (dkcinfo.dki_ctype == DKC_MD) {
   1386 			ismdd++;
   1387 			/*
   1388 			 * check the logging device
   1389 			 */
   1390 			if (ioctl(fsi, _FIOISLOG, NULL) == 0) {
   1391 				islog++;
   1392 				if (ioctl(fsi, _FIOISLOGOK, NULL) == 0)
   1393 					islogok++;
   1394 			}
   1395 		}
   1396 
   1397 	/*
   1398 	 * Do not grow the file system, but print on stdout the maximum
   1399 	 * size in sectors to which the file system can be increased.
   1400 	 * The calculated size is limited by fssize_db.
   1401 	 * Note that we don't lock the filesystem and therefore under rare
   1402 	 * conditions (the filesystem is mounted, the free block count is
   1403 	 * almost zero, and the superuser is still changing it) the calculated
   1404 	 * size can be imprecise.
   1405 	 */
   1406 	if (Pflag) {
   1407 		(void) printf("%llu\n", probe_summaryinfo());
   1408 		exit(0);
   1409 	}
   1410 
   1411 	/*
   1412 	 * If we're growing an existing filesystem, then we're about
   1413 	 * to start doing things that can require recovery efforts if
   1414 	 * we get interrupted, so make sure we get a chance to do so.
   1415 	 */
   1416 	if (grow) {
   1417 		sigact.sa_handler = recover_from_sigint;
   1418 		sigemptyset(&sigact.sa_mask);
   1419 		sigact.sa_flags = SA_RESTART;
   1420 
   1421 		if (sigaction(SIGINT, &sigact, (struct sigaction *)NULL) < 0) {
   1422 			perror(gettext("Could not register SIGINT handler"));
   1423 			lockexit(3);
   1424 		}
   1425 	}
   1426 
   1427 	if (!Nflag) {
   1428 		/*
   1429 		 * Check if MNTTAB is trustable
   1430 		 */
   1431 		if (statvfs64(MNTTAB, &fs) < 0) {
   1432 			(void) fprintf(stderr, gettext("can't statvfs %s\n"),
   1433 			    MNTTAB);
   1434 			exit(32);
   1435 		}
   1436 
   1437 		if (strcmp(MNTTYPE_MNTFS, fs.f_basetype) != 0) {
   1438 			(void) fprintf(stderr, gettext(
   1439 			    "%s file system type is not %s, can't mkfs\n"),
   1440 			    MNTTAB, MNTTYPE_MNTFS);
   1441 			exit(32);
   1442 		}
   1443 
   1444 		special = getfullblkname(fsys);
   1445 		checkdev(fsys, special);
   1446 
   1447 		/*
   1448 		 * If we found the block device name,
   1449 		 * then check the mount table.
   1450 		 * if mounted, and growing write lock the file system
   1451 		 *
   1452 		 */
   1453 		if ((special != NULL) && (*special != '\0')) {
   1454 			if ((mnttab = fopen(MNTTAB, "r")) == NULL) {
   1455 				(void) fprintf(stderr, gettext(
   1456 				    "can't open %s\n"), MNTTAB);
   1457 				exit(32);
   1458 			}
   1459 			while ((getmntent(mnttab, &mntp)) == NULL) {
   1460 				if (grow) {
   1461 					checkmount(&mntp, special);
   1462 					continue;
   1463 				}
   1464 				if (strcmp(special, mntp.mnt_special) == 0) {
   1465 					(void) fprintf(stderr, gettext(
   1466 					    "%s is mounted, can't mkfs\n"),
   1467 					    special);
   1468 					exit(32);
   1469 				}
   1470 			}
   1471 			(void) fclose(mnttab);
   1472 		}
   1473 
   1474 		if (directory && (ismounted == 0)) {
   1475 			(void) fprintf(stderr, gettext("%s is not mounted\n"),
   1476 			    special);
   1477 			lockexit(32);
   1478 		}
   1479 
   1480 		fso = (grow) ? open64(fsys, O_WRONLY) : creat64(fsys, 0666);
   1481 		if (fso < 0) {
   1482 			saverr = errno;
   1483 			(void) fprintf(stderr,
   1484 			    gettext("%s: cannot create: %s\n"),
   1485 			    fsys, strerror(saverr));
   1486 			lockexit(32);
   1487 		}
   1488 
   1489 	} else {
   1490 
   1491 		/*
   1492 		 * For the -N case, a file descriptor is needed for the llseek()
   1493 		 * in wtfs(). See the comment in wtfs() for more information.
   1494 		 *
   1495 		 * Get a file descriptor that's read-only so that this code
   1496 		 * doesn't accidentally write to the file.
   1497 		 */
   1498 		fso = open64(fsys, O_RDONLY);
   1499 		if (fso < 0) {
   1500 			saverr = errno;
   1501 			(void) fprintf(stderr, gettext("%s: cannot open: %s\n"),
   1502 			    fsys, strerror(saverr));
   1503 			lockexit(32);
   1504 		}
   1505 	}
   1506 
   1507 	/*
   1508 	 * Check the media sector size
   1509 	 */
   1510 	if (ioctl(fso, DKIOCGMEDIAINFO, &dkminfo) != -1) {
   1511 		if (dkminfo.dki_lbsize != 0 &&
   1512 		    POWEROF2(dkminfo.dki_lbsize / DEV_BSIZE) &&
   1513 		    dkminfo.dki_lbsize != DEV_BSIZE) {
   1514 			fprintf(stderr,
   1515 			    gettext("The device sector size %u is not "
   1516 			    "supported by ufs!\n"), dkminfo.dki_lbsize);
   1517 			(void) close(fso);
   1518 			exit(1);
   1519 		}
   1520 	}
   1521 
   1522 	/*
   1523 	 * seed random # generator (for ic_generation)
   1524 	 */
   1525 #ifdef MKFS_DEBUG
   1526 	srand48(12962);	/* reproducible results */
   1527 #else
   1528 	srand48((long)(time((time_t *)NULL) + getpid()));
   1529 #endif
   1530 
   1531 	if (grow) {
   1532 		growinit(fsys);
   1533 		goto grow00;
   1534 	}
   1535 
   1536 	/*
   1537 	 * Validate the given file system size.
   1538 	 * Verify that its last block can actually be accessed.
   1539 	 *
   1540 	 * Note: it's ok to use sblock as a buffer because it is immediately
   1541 	 * overwritten by the rdfs() of the superblock in the next line.
   1542 	 *
   1543 	 * ToDo: Because the size checking is done in rdfs()/wtfs(), the
   1544 	 * error message for specifying an illegal size is very unfriendly.
   1545 	 * In the future, one could replace the rdfs()/wtfs() calls
   1546 	 * below with in-line calls to read() or write(). This allows better
   1547 	 * error messages to be put in place.
   1548 	 */
   1549 	rdfs(fssize_db - 1, (int)sectorsize, (char *)&sblock);
   1550 
   1551 	/*
   1552 	 * make the fs unmountable
   1553 	 */
   1554 	rdfs((diskaddr_t)(SBOFF / sectorsize), (int)sbsize, (char *)&sblock);
   1555 	sblock.fs_magic = -1;
   1556 	sblock.fs_clean = FSBAD;
   1557 	sblock.fs_state = FSOKAY - sblock.fs_time;
   1558 	wtfs((diskaddr_t)(SBOFF / sectorsize), (int)sbsize, (char *)&sblock);
   1559 	bzero(&sblock, (size_t)sbsize);
   1560 
   1561 	sblock.fs_nsect = nsect;
   1562 	sblock.fs_ntrak = ntrack;
   1563 
   1564 	/*
   1565 	 * Validate specified/determined spc
   1566 	 * and calculate minimum cylinders per group.
   1567 	 */
   1568 
   1569 	/*
   1570 	 * sectors/cyl = tracks/cyl * sectors/track
   1571 	 */
   1572 	sblock.fs_spc = sblock.fs_ntrak * sblock.fs_nsect;
   1573 
   1574 grow00:
   1575 	if (apc_flag) {
   1576 		sblock.fs_spc -= apc;
   1577 	}
   1578 	/*
   1579 	 * Have to test for this separately from apc_flag, due to
   1580 	 * the growfs case....
   1581 	 */
   1582 	if (sblock.fs_spc != sblock.fs_ntrak * sblock.fs_nsect) {
   1583 		spc_flag = 1;
   1584 	}
   1585 	if (grow)
   1586 		goto grow10;
   1587 
   1588 	sblock.fs_nrpos = nrpos;
   1589 	sblock.fs_bsize = bsize;
   1590 	sblock.fs_fsize = fragsize;
   1591 	sblock.fs_minfree = minfree;
   1592 
   1593 grow10:
   1594 	if (nbpi < sblock.fs_fsize) {
   1595 		(void) fprintf(stderr, gettext(
   1596 		"warning: wasteful data byte allocation / inode (nbpi):\n"));
   1597 		(void) fprintf(stderr, gettext(
   1598 		    "%ld smaller than allocatable fragment size of %d\n"),
   1599 		    nbpi, sblock.fs_fsize);
   1600 	}
   1601 	if (grow)
   1602 		goto grow20;
   1603 
   1604 	if (opt == 's')
   1605 		sblock.fs_optim = FS_OPTSPACE;
   1606 	else
   1607 		sblock.fs_optim = FS_OPTTIME;
   1608 
   1609 	sblock.fs_bmask = ~(sblock.fs_bsize - 1);
   1610 	sblock.fs_fmask = ~(sblock.fs_fsize - 1);
   1611 	/*
   1612 	 * Planning now for future expansion.
   1613 	 */
   1614 #if defined(_BIG_ENDIAN)
   1615 		sblock.fs_qbmask.val[0] = 0;
   1616 		sblock.fs_qbmask.val[1] = ~sblock.fs_bmask;
   1617 		sblock.fs_qfmask.val[0] = 0;
   1618 		sblock.fs_qfmask.val[1] = ~sblock.fs_fmask;
   1619 #endif
   1620 #if defined(_LITTLE_ENDIAN)
   1621 		sblock.fs_qbmask.val[0] = ~sblock.fs_bmask;
   1622 		sblock.fs_qbmask.val[1] = 0;
   1623 		sblock.fs_qfmask.val[0] = ~sblock.fs_fmask;
   1624 		sblock.fs_qfmask.val[1] = 0;
   1625 #endif
   1626 	for (sblock.fs_bshift = 0, i = sblock.fs_bsize; i > 1; i >>= 1)
   1627 		sblock.fs_bshift++;
   1628 	for (sblock.fs_fshift = 0, i = sblock.fs_fsize; i > 1; i >>= 1)
   1629 		sblock.fs_fshift++;
   1630 	sblock.fs_frag = numfrags(&sblock, sblock.fs_bsize);
   1631 	for (sblock.fs_fragshift = 0, i = sblock.fs_frag; i > 1; i >>= 1)
   1632 		sblock.fs_fragshift++;
   1633 	if (sblock.fs_frag > MAXFRAG) {
   1634 		(void) fprintf(stderr, gettext(
   1635 	"fragment size %d is too small, minimum with block size %d is %d\n"),
   1636 		    sblock.fs_fsize, sblock.fs_bsize,
   1637 		    sblock.fs_bsize / MAXFRAG);
   1638 		lockexit(32);
   1639 	}
   1640 	sblock.fs_nindir = sblock.fs_bsize / sizeof (daddr32_t);
   1641 	sblock.fs_inopb = sblock.fs_bsize / sizeof (struct dinode);
   1642 	sblock.fs_nspf = sblock.fs_fsize / sectorsize;
   1643 	for (sblock.fs_fsbtodb = 0, i = NSPF(&sblock); i > 1; i >>= 1)
   1644 		sblock.fs_fsbtodb++;
   1645 
   1646 	/*
   1647 	 * Compute the super-block, cylinder group, and inode blocks.
   1648 	 * Note that these "blkno" are really fragment addresses.
   1649 	 * For example, on an 8K/1K (block/fragment) system, fs_sblkno is 16,
   1650 	 * fs_cblkno is 24, and fs_iblkno is 32. This is why CGSIZE is so
   1651 	 * important: only 1 FS block is allocated for the cg struct (fragment
   1652 	 * numbers 24 through 31).
   1653 	 */
   1654 	sblock.fs_sblkno =
   1655 	    roundup(howmany(bbsize + sbsize, sblock.fs_fsize), sblock.fs_frag);
   1656 	sblock.fs_cblkno = (daddr32_t)(sblock.fs_sblkno +
   1657 	    roundup(howmany(sbsize, sblock.fs_fsize), sblock.fs_frag));
   1658 	sblock.fs_iblkno = sblock.fs_cblkno + sblock.fs_frag;
   1659 
   1660 	sblock.fs_cgoffset = roundup(
   1661 	    howmany(sblock.fs_nsect, NSPF(&sblock)), sblock.fs_frag);
   1662 	for (sblock.fs_cgmask = -1, i = sblock.fs_ntrak; i > 1; i >>= 1)
   1663 		sblock.fs_cgmask <<= 1;
   1664 	if (!POWEROF2(sblock.fs_ntrak))
   1665 		sblock.fs_cgmask <<= 1;
   1666 	/*
   1667 	 * Validate specified/determined spc
   1668 	 * and calculate minimum cylinders per group.
   1669 	 */
   1670 
   1671 	for (sblock.fs_cpc = NSPB(&sblock), i = sblock.fs_spc;
   1672 	    sblock.fs_cpc > 1 && (i & 1) == 0;
   1673 	    sblock.fs_cpc >>= 1, i >>= 1)
   1674 		/* void */;
   1675 	mincpc = sblock.fs_cpc;
   1676 
   1677 	/* if these calculations are changed, check dump_fscmd also */
   1678 	bpcg = (uint64_t)sblock.fs_spc * sectorsize;
   1679 	inospercg = (uint64_t)roundup(bpcg / sizeof (struct dinode),
   1680 	    INOPB(&sblock));
   1681 	if (inospercg > MAXIpG(&sblock))
   1682 		inospercg = MAXIpG(&sblock);
   1683 	used = (uint64_t)(sblock.fs_iblkno + inospercg /
   1684 	    INOPF(&sblock)) * NSPF(&sblock);
   1685 	mincpgcnt = (long)howmany((uint64_t)sblock.fs_cgoffset *
   1686 	    (~sblock.fs_cgmask) + used, sblock.fs_spc);
   1687 	mincpg = roundup(mincpgcnt, mincpc);
   1688 	/*
   1689 	 * Insure that cylinder group with mincpg has enough space
   1690 	 * for block maps
   1691 	 */
   1692 	sblock.fs_cpg = mincpg;
   1693 	sblock.fs_ipg = (int32_t)inospercg;
   1694 	mapcramped = 0;
   1695 
   1696 	/*
   1697 	 * Make sure the cg struct fits within the file system block.
   1698 	 * Use larger block sizes until it fits
   1699 	 */
   1700 	while (CGSIZE(&sblock) > sblock.fs_bsize) {
   1701 		mapcramped = 1;
   1702 		if (sblock.fs_bsize < MAXBSIZE) {
   1703 			sblock.fs_bsize <<= 1;
   1704 			if ((i & 1) == 0) {
   1705 				i >>= 1;
   1706 			} else {
   1707 				sblock.fs_cpc <<= 1;
   1708 				mincpc <<= 1;
   1709 				mincpg = roundup(mincpgcnt, mincpc);
   1710 				sblock.fs_cpg = mincpg;
   1711 			}
   1712 			sblock.fs_frag <<= 1;
   1713 			sblock.fs_fragshift += 1;
   1714 			if (sblock.fs_frag <= MAXFRAG)
   1715 				continue;
   1716 		}
   1717 
   1718 		/*
   1719 		 * Looped far enough. The fragment is now as large as the
   1720 		 * filesystem block!
   1721 		 */
   1722 		if (sblock.fs_fsize == sblock.fs_bsize) {
   1723 			(void) fprintf(stderr, gettext(
   1724 		    "There is no block size that can support this disk\n"));
   1725 			lockexit(32);
   1726 		}
   1727 
   1728 		/*
   1729 		 * Try a larger fragment. Double the fragment size.
   1730 		 */
   1731 		sblock.fs_frag >>= 1;
   1732 		sblock.fs_fragshift -= 1;
   1733 		sblock.fs_fsize <<= 1;
   1734 		sblock.fs_nspf <<= 1;
   1735 	}
   1736 	/*
   1737 	 * Insure that cylinder group with mincpg has enough space for inodes
   1738 	 */
   1739 	inodecramped = 0;
   1740 	used *= sectorsize;
   1741 	nbytes64 = (uint64_t)mincpg * bpcg - used;
   1742 	inospercg = (uint64_t)roundup((nbytes64 / nbpi), INOPB(&sblock));
   1743 	sblock.fs_ipg = (int32_t)inospercg;
   1744 	while (inospercg > MAXIpG(&sblock)) {
   1745 		inodecramped = 1;
   1746 		if (mincpc == 1 || sblock.fs_frag == 1 ||
   1747 		    sblock.fs_bsize == MINBSIZE)
   1748 			break;
   1749 		nbytes64 = (uint64_t)mincpg * bpcg - used;
   1750 		(void) fprintf(stderr,
   1751 		    gettext("With a block size of %d %s %lu\n"),
   1752 		    sblock.fs_bsize, gettext("minimum bytes per inode is"),
   1753 		    (uint32_t)(nbytes64 / MAXIpG(&sblock) + 1));
   1754 		sblock.fs_bsize >>= 1;
   1755 		sblock.fs_frag >>= 1;
   1756 		sblock.fs_fragshift -= 1;
   1757 		mincpc >>= 1;
   1758 		sblock.fs_cpg = roundup(mincpgcnt, mincpc);
   1759 		if (CGSIZE(&sblock) > sblock.fs_bsize) {
   1760 			sblock.fs_bsize <<= 1;
   1761 			break;
   1762 		}
   1763 		mincpg = sblock.fs_cpg;
   1764 		nbytes64 = (uint64_t)mincpg * bpcg - used;
   1765 		inospercg = (uint64_t)roundup((nbytes64 / nbpi),
   1766 		    INOPB(&sblock));
   1767 		sblock.fs_ipg = (int32_t)inospercg;
   1768 	}
   1769 	if (inodecramped) {
   1770 		if (inospercg > MAXIpG(&sblock)) {
   1771 			nbytes64 = (uint64_t)mincpg * bpcg - used;
   1772 			(void) fprintf(stderr, gettext(
   1773 			    "Minimum bytes per inode is %d\n"),
   1774 			    (uint32_t)(nbytes64 / MAXIpG(&sblock) + 1));
   1775 		} else if (!mapcramped) {
   1776 			(void) fprintf(stderr, gettext(
   1777 	    "With %ld bytes per inode, minimum cylinders per group is %ld\n"),
   1778 			    nbpi, mincpg);
   1779 		}
   1780 	}
   1781 	if (mapcramped) {
   1782 		(void) fprintf(stderr, gettext(
   1783 		    "With %d sectors per cylinder, minimum cylinders "
   1784 		    "per group is %ld\n"),
   1785 		    sblock.fs_spc, mincpg);
   1786 	}
   1787 	if (inodecramped || mapcramped) {
   1788 		/*
   1789 		 * To make this at least somewhat comprehensible in
   1790 		 * the world of i18n, figure out what we're going to
   1791 		 * say and then say it all at one time.  The days of
   1792 		 * needing to scrimp on string space are behind us....
   1793 		 */
   1794 		if ((sblock.fs_bsize != bsize) &&
   1795 		    (sblock.fs_fsize != fragsize)) {
   1796 			(void) fprintf(stderr, gettext(
   1797 	    "This requires the block size to be changed from %ld to %d\n"
   1798 	    "and the fragment size to be changed from %ld to %d\n"),
   1799 			    bsize, sblock.fs_bsize,
   1800 			    fragsize, sblock.fs_fsize);
   1801 		} else if (sblock.fs_bsize != bsize) {
   1802 			(void) fprintf(stderr, gettext(
   1803 	    "This requires the block size to be changed from %ld to %d\n"),
   1804 			    bsize, sblock.fs_bsize);
   1805 		} else if (sblock.fs_fsize != fragsize) {
   1806 			(void) fprintf(stderr, gettext(
   1807 	    "This requires the fragment size to be changed from %ld to %d\n"),
   1808 			    fragsize, sblock.fs_fsize);
   1809 		} else {
   1810 			(void) fprintf(stderr, gettext(
   1811 	    "Unable to make filesystem fit with the given constraints\n"));
   1812 		}
   1813 		(void) fprintf(stderr, gettext(
   1814 		    "Please re-run mkfs with corrected parameters\n"));
   1815 		lockexit(32);
   1816 	}
   1817 	/*
   1818 	 * Calculate the number of cylinders per group
   1819 	 */
   1820 	sblock.fs_cpg = cpg;
   1821 	if (sblock.fs_cpg % mincpc != 0) {
   1822 		(void) fprintf(stderr, gettext(
   1823 		    "Warning: cylinder groups must have a multiple "
   1824 		    "of %ld cylinders with the given\n         parameters\n"),
   1825 		    mincpc);
   1826 		sblock.fs_cpg = roundup(sblock.fs_cpg, mincpc);
   1827 		(void) fprintf(stderr, gettext("Rounded cgsize up to %d\n"),
   1828 		    sblock.fs_cpg);
   1829 	}
   1830 	/*
   1831 	 * Must insure there is enough space for inodes
   1832 	 */
   1833 	/* if these calculations are changed, check dump_fscmd also */
   1834 	nbytes64 = (uint64_t)sblock.fs_cpg * bpcg - used;
   1835 	sblock.fs_ipg = roundup((uint32_t)(nbytes64 / nbpi), INOPB(&sblock));
   1836 
   1837 	/*
   1838 	 * Slim down cylinders per group, until the inodes can fit.
   1839 	 */
   1840 	while (sblock.fs_ipg > MAXIpG(&sblock)) {
   1841 		inodecramped = 1;
   1842 		sblock.fs_cpg -= mincpc;
   1843 		nbytes64 = (uint64_t)sblock.fs_cpg * bpcg - used;
   1844 		sblock.fs_ipg = roundup((uint32_t)(nbytes64 / nbpi),
   1845 		    INOPB(&sblock));
   1846 	}
   1847 	/*
   1848 	 * Must insure there is enough space to hold block map.
   1849 	 * Cut down on cylinders per group, until the cg struct fits in a
   1850 	 * filesystem block.
   1851 	 */
   1852 	while (CGSIZE(&sblock) > sblock.fs_bsize) {
   1853 		mapcramped = 1;
   1854 		sblock.fs_cpg -= mincpc;
   1855 		nbytes64 = (uint64_t)sblock.fs_cpg * bpcg - used;
   1856 		sblock.fs_ipg = roundup((uint32_t)(nbytes64 / nbpi),
   1857 		    INOPB(&sblock));
   1858 	}
   1859 	sblock.fs_fpg = (sblock.fs_cpg * sblock.fs_spc) / NSPF(&sblock);
   1860 	if ((sblock.fs_cpg * sblock.fs_spc) % NSPB(&sblock) != 0) {
   1861 		(void) fprintf(stderr,
   1862 		gettext("newfs: panic (fs_cpg * fs_spc) %% NSPF != 0\n"));
   1863 		lockexit(32);
   1864 	}
   1865 	if (sblock.fs_cpg < mincpg) {
   1866 		(void) fprintf(stderr, gettext(
   1867 "With the given parameters, cgsize must be at least %ld; please re-run mkfs\n"),
   1868 		    mincpg);
   1869 		lockexit(32);
   1870 	}
   1871 	sblock.fs_cgsize = fragroundup(&sblock, CGSIZE(&sblock));
   1872 grow20:
   1873 	/*
   1874 	 * Now have size for file system and nsect and ntrak.
   1875 	 * Determine number of cylinders and blocks in the file system.
   1876 	 */
   1877 	fssize_frag = (int64_t)dbtofsb(&sblock, fssize_db);
   1878 	if (fssize_frag > INT_MAX) {
   1879 		(void) fprintf(stderr, gettext(
   1880 "There are too many fragments in the system, increase fragment size\n"),
   1881 		    mincpg);
   1882 		lockexit(32);
   1883 	}
   1884 	sblock.fs_size = (int32_t)fssize_frag;
   1885 	sblock.fs_ncyl = (int32_t)(fssize_frag * NSPF(&sblock) / sblock.fs_spc);
   1886 	if (fssize_frag * NSPF(&sblock) >
   1887 	    (uint64_t)sblock.fs_ncyl * sblock.fs_spc) {
   1888 		sblock.fs_ncyl++;
   1889 		warn = 1;
   1890 	}
   1891 	if (sblock.fs_ncyl < 1) {
   1892 		(void) fprintf(stderr, gettext(
   1893 		    "file systems must have at least one cylinder\n"));
   1894 		lockexit(32);
   1895 	}
   1896 	if (grow)
   1897 		goto grow30;
   1898 	/*
   1899 	 * Determine feasability/values of rotational layout tables.
   1900 	 *
   1901 	 * The size of the rotational layout tables is limited by the size
   1902 	 * of the file system block, fs_bsize.  The amount of space
   1903 	 * available for tables is calculated as (fs_bsize - sizeof (struct
   1904 	 * fs)).  The size of these tables is inversely proportional to the
   1905 	 * block size of the file system. The size increases if sectors per
   1906 	 * track are not powers of two, because more cylinders must be
   1907 	 * described by the tables before the rotational pattern repeats
   1908 	 * (fs_cpc).
   1909 	 */
   1910 	sblock.fs_postblformat = FS_DYNAMICPOSTBLFMT;
   1911 	sblock.fs_sbsize = fragroundup(&sblock, sizeof (struct fs));
   1912 	sblock.fs_npsect = sblock.fs_nsect;
   1913 	if (sblock.fs_ntrak == 1) {
   1914 		sblock.fs_cpc = 0;
   1915 		goto next;
   1916 	}
   1917 	postblsize = sblock.fs_nrpos * sblock.fs_cpc * sizeof (short);
   1918 	rotblsize = sblock.fs_cpc * sblock.fs_spc / NSPB(&sblock);
   1919 	totalsbsize = sizeof (struct fs) + rotblsize;
   1920 
   1921 	/* do static allocation if nrpos == 8 and fs_cpc == 16  */
   1922 	if (sblock.fs_nrpos == 8 && sblock.fs_cpc <= 16) {
   1923 		/* use old static table space */
   1924 		sblock.fs_postbloff = (char *)(&sblock.fs_opostbl[0][0]) -
   1925 		    (char *)(&sblock.fs_link);
   1926 		sblock.fs_rotbloff = &sblock.fs_space[0] -
   1927 		    (uchar_t *)(&sblock.fs_link);
   1928 	} else {
   1929 		/* use 4.3 dynamic table space */
   1930 		sblock.fs_postbloff = &sblock.fs_space[0] -
   1931 		    (uchar_t *)(&sblock.fs_link);
   1932 		sblock.fs_rotbloff = sblock.fs_postbloff + postblsize;
   1933 		totalsbsize += postblsize;
   1934 	}
   1935 	if (totalsbsize > sblock.fs_bsize ||
   1936 	    sblock.fs_nsect > (1 << NBBY) * NSPB(&sblock)) {
   1937 		(void) fprintf(stderr, gettext(
   1938 		    "Warning: insufficient space in super block for\n"
   1939 		    "rotational layout tables with nsect %d, ntrack %d, "
   1940 		    "and nrpos %d.\nOmitting tables - file system "
   1941 		    "performance may be impaired.\n"),
   1942 		    sblock.fs_nsect, sblock.fs_ntrak, sblock.fs_nrpos);
   1943 
   1944 		/*
   1945 		 * Setting fs_cpc to 0 tells alloccgblk() in ufs_alloc.c to
   1946 		 * ignore the positional layout table and rotational
   1947 		 * position table.
   1948 		 */
   1949 		sblock.fs_cpc = 0;
   1950 		goto next;
   1951 	}
   1952 	sblock.fs_sbsize = fragroundup(&sblock, totalsbsize);
   1953 
   1954 
   1955 	/*
   1956 	 * calculate the available blocks for each rotational position
   1957 	 */
   1958 	for (cylno = 0; cylno < sblock.fs_cpc; cylno++)
   1959 		for (rpos = 0; rpos < sblock.fs_nrpos; rpos++)
   1960 			fs_postbl(&sblock, cylno)[rpos] = -1;
   1961 	for (i = (rotblsize - 1) * sblock.fs_frag;
   1962 	    i >= 0; i -= sblock.fs_frag) {
   1963 		cylno = cbtocylno(&sblock, i);
   1964 		rpos = cbtorpos(&sblock, i);
   1965 		blk = fragstoblks(&sblock, i);
   1966 		if (fs_postbl(&sblock, cylno)[rpos] == -1)
   1967 			fs_rotbl(&sblock)[blk] = 0;
   1968 		else
   1969 			fs_rotbl(&sblock)[blk] =
   1970 			    fs_postbl(&sblock, cylno)[rpos] - blk;
   1971 		fs_postbl(&sblock, cylno)[rpos] = blk;
   1972 	}
   1973 next:
   1974 grow30:
   1975 	/*
   1976 	 * Compute/validate number of cylinder groups.
   1977 	 * Note that if an excessively large filesystem is specified
   1978 	 * (e.g., more than 16384 cylinders for an 8K filesystem block), it
   1979 	 * does not get detected until checksummarysize()
   1980 	 */
   1981 	sblock.fs_ncg = sblock.fs_ncyl / sblock.fs_cpg;
   1982 	if (sblock.fs_ncyl % sblock.fs_cpg)
   1983 		sblock.fs_ncg++;
   1984 	sblock.fs_dblkno = sblock.fs_iblkno + sblock.fs_ipg / INOPF(&sblock);
   1985 	i = MIN(~sblock.fs_cgmask, sblock.fs_ncg - 1);
   1986 	ibpcl = cgdmin(&sblock, i) - cgbase(&sblock, i);
   1987 	if (ibpcl >= sblock.fs_fpg) {
   1988 		(void) fprintf(stderr, gettext(
   1989 		    "inode blocks/cyl group (%d) >= data blocks (%d)\n"),
   1990 		    cgdmin(&sblock, i) - cgbase(&sblock, i) / sblock.fs_frag,
   1991 		    sblock.fs_fpg / sblock.fs_frag);
   1992 		if ((ibpcl < 0) || (sblock.fs_fpg < 0)) {
   1993 			(void) fprintf(stderr, gettext(
   1994 	    "number of cylinders per cylinder group (%d) must be decreased.\n"),
   1995 			    sblock.fs_cpg);
   1996 		} else {
   1997 			(void) fprintf(stderr, gettext(
   1998 	    "number of cylinders per cylinder group (%d) must be increased.\n"),
   1999 			    sblock.fs_cpg);
   2000 		}
   2001 		(void) fprintf(stderr, gettext(
   2002 "Note that cgsize may have been adjusted to allow struct cg to fit.\n"));
   2003 		lockexit(32);
   2004 	}
   2005 	j = sblock.fs_ncg - 1;
   2006 	if ((i = fssize_frag - j * sblock.fs_fpg) < sblock.fs_fpg &&
   2007 	    cgdmin(&sblock, j) - cgbase(&sblock, j) > i) {
   2008 		(void) fprintf(stderr, gettext(
   2009 		    "Warning: inode blocks/cyl group (%d) >= data "
   2010 		    "blocks (%ld) in last\n    cylinder group. This "
   2011 		    "implies %ld sector(s) cannot be allocated.\n"),
   2012 		    (cgdmin(&sblock, j) - cgbase(&sblock, j)) / sblock.fs_frag,
   2013 		    i / sblock.fs_frag, i * NSPF(&sblock));
   2014 		/*
   2015 		 * If there is only one cylinder group and that is not even
   2016 		 * big enough to hold the inodes, exit.
   2017 		 */
   2018 		if (sblock.fs_ncg == 1)
   2019 			cg_too_small = 1;
   2020 		sblock.fs_ncg--;
   2021 		sblock.fs_ncyl = sblock.fs_ncg * sblock.fs_cpg;
   2022 		sblock.fs_size = fssize_frag =
   2023 		    (int64_t)sblock.fs_ncyl * (int64_t)sblock.fs_spc /
   2024 		    (int64_t)NSPF(&sblock);
   2025 		warn = 0;
   2026 	}
   2027 	if (warn && !spc_flag) {
   2028 		(void) fprintf(stderr, gettext(
   2029 		    "Warning: %d sector(s) in last cylinder unallocated\n"),
   2030 		    sblock.fs_spc - (uint32_t)(fssize_frag * NSPF(&sblock) -
   2031 		    (uint64_t)(sblock.fs_ncyl - 1) * sblock.fs_spc));
   2032 	}
   2033 	/*
   2034 	 * fill in remaining fields of the super block
   2035 	 */
   2036 
   2037 	/*
   2038 	 * The csum records are stored in cylinder group 0, starting at
   2039 	 * cgdmin, the first data block.
   2040 	 */
   2041 	sblock.fs_csaddr = cgdmin(&sblock, 0);
   2042 	sblock.fs_cssize =
   2043 	    fragroundup(&sblock, sblock.fs_ncg * sizeof (struct csum));
   2044 	i = sblock.fs_bsize / sizeof (struct csum);
   2045 	sblock.fs_csmask = ~(i - 1);
   2046 	for (sblock.fs_csshift = 0; i > 1; i >>= 1)
   2047 		sblock.fs_csshift++;
   2048 	fscs = (struct csum *)calloc(1, sblock.fs_cssize);
   2049 
   2050 	checksummarysize();
   2051 	if (mtb == 'y') {
   2052 		sblock.fs_magic = MTB_UFS_MAGIC;
   2053 		sblock.fs_version = MTB_UFS_VERSION_1;
   2054 	} else {
   2055 		sblock.fs_magic = FS_MAGIC;
   2056 		if (use_efi_dflts)
   2057 			sblock.fs_version = UFS_EFISTYLE4NONEFI_VERSION_2;
   2058 		else
   2059 			sblock.fs_version = UFS_VERSION_MIN;
   2060 	}
   2061 
   2062 	if (grow) {
   2063 		bcopy((caddr_t)grow_fscs, (caddr_t)fscs, (int)grow_fs_cssize);
   2064 		extendsummaryinfo();
   2065 		goto grow40;
   2066 	}
   2067 	sblock.fs_rotdelay = rotdelay;
   2068 	sblock.fs_maxcontig = maxcontig;
   2069 	sblock.fs_maxbpg = MAXBLKPG(sblock.fs_bsize);
   2070 
   2071 	sblock.fs_rps = rps;
   2072 	sblock.fs_cgrotor = 0;
   2073 	sblock.fs_cstotal.cs_ndir = 0;
   2074 	sblock.fs_cstotal.cs_nbfree = 0;
   2075 	sblock.fs_cstotal.cs_nifree = 0;
   2076 	sblock.fs_cstotal.cs_nffree = 0;
   2077 	sblock.fs_fmod = 0;
   2078 	sblock.fs_ronly = 0;
   2079 	sblock.fs_time = mkfstime;
   2080 	sblock.fs_state = FSOKAY - sblock.fs_time;
   2081 	sblock.fs_clean = FSCLEAN;
   2082 grow40:
   2083 
   2084 	/*
   2085 	 * If all that's needed is a dump of the superblock we
   2086 	 * would use by default, we've got it now.  So, splat it
   2087 	 * out and leave.
   2088 	 */
   2089 	if (rflag) {
   2090 		dump_sblock();
   2091 		lockexit(0);
   2092 	}
   2093 	/*
   2094 	 * Dump out summary information about file system.
   2095 	 */
   2096 	(void) fprintf(stderr, gettext(
   2097 	    "%s:\t%lld sectors in %d cylinders of %d tracks, %d sectors\n"),
   2098 	    fsys, (uint64_t)sblock.fs_size * NSPF(&sblock), sblock.fs_ncyl,
   2099 	    sblock.fs_ntrak, sblock.fs_nsect);
   2100 	(void) fprintf(stderr, gettext(
   2101 	    "\t%.1fMB in %d cyl groups (%d c/g, %.2fMB/g, %d i/g)\n"),
   2102 	    (float)sblock.fs_size * sblock.fs_fsize / MB, sblock.fs_ncg,
   2103 	    sblock.fs_cpg, (float)sblock.fs_fpg * sblock.fs_fsize / MB,
   2104 	    sblock.fs_ipg);
   2105 
   2106 	tmpbuf = calloc(sblock.fs_ncg / 50 + 500, 1);
   2107 	if (tmpbuf == NULL) {
   2108 		perror("calloc");
   2109 		lockexit(32);
   2110 	}
   2111 	if (cg_too_small) {
   2112 		(void) fprintf(stderr, gettext("File system creation failed. "
   2113 		    "There is only one cylinder group and\nthat is "
   2114 		    "not even big enough to hold the inodes.\n"));
   2115 		lockexit(32);
   2116 	}
   2117 	/*
   2118 	 * Now build the cylinders group blocks and
   2119 	 * then print out indices of cylinder groups.
   2120 	 */
   2121 	tprintf(gettext(
   2122 	    "super-block backups (for fsck -F ufs -o b=#) at:\n"));
   2123 	for (width = cylno = 0; cylno < sblock.fs_ncg && cylno < 10; cylno++) {
   2124 		if ((grow == 0) || (cylno >= grow_fs_ncg))
   2125 			initcg(cylno);
   2126 		num = fsbtodb(&sblock, (uint64_t)cgsblock(&sblock, cylno));
   2127 		/*
   2128 		 * If Nflag and if the disk is larger than the CHSLIMIT,
   2129 		 * then sanity test the superblocks before reporting. If there
   2130 		 * are too many superblocks which look insane, we have
   2131 		 * to retry with alternate logic. If both methods have
   2132 		 * failed, then our efforts to arrive at alternate
   2133 		 * superblocks failed, so complain and exit.
   2134 		 */
   2135 		if (Nflag && retry) {
   2136 			skip_this_sb = 0;
   2137 			rdfs((diskaddr_t)num, sbsize, (char *)&altsblock);
   2138 			ret = checksblock(altsblock, 1);
   2139 			if (ret) {
   2140 				skip_this_sb = 1;
   2141 				invalid_sb_cnt++;
   2142 				dprintf(("DeBuG checksblock() failed - error :"
   2143 				    " %d for sb : %llu invalid_sb_cnt : %d\n",
   2144 				    ret, num, invalid_sb_cnt));
   2145 			} else {
   2146 				/*
   2147 				 * Though the superblock looks sane, verify if
   2148 				 * the fs_version in the superblock and the
   2149 				 * logic that we are using to arrive at the
   2150 				 * superblocks match.
   2151 				 */
   2152 				if (use_efi_dflts && altsblock.fs_version
   2153 				    != UFS_EFISTYLE4NONEFI_VERSION_2) {
   2154 					skip_this_sb = 1;
   2155 					invalid_sb_cnt++;
   2156 				}
   2157 			}
   2158 			if (invalid_sb_cnt >= INVALIDSBLIMIT) {
   2159 				if (retry > 1) {
   2160 					(void) fprintf(stderr, gettext(
   2161 					    "Error determining alternate "
   2162 					    "superblock locations\n"));
   2163 					free(tmpbuf);
   2164 					lockexit(32);
   2165 				}
   2166 				retry++;
   2167 				use_efi_dflts = !use_efi_dflts;
   2168 				free(tmpbuf);
   2169 				goto retry_alternate_logic;
   2170 			}
   2171 			if (skip_this_sb)
   2172 				continue;
   2173 		}
   2174 		(void) sprintf(pbuf, " %llu,", num);
   2175 		plen = strlen(pbuf);
   2176 		if ((width + plen) > (WIDTH - 1)) {
   2177 			width = plen;
   2178 			tprintf("\n");
   2179 		} else {
   2180 			width += plen;
   2181 		}
   2182 		if (Nflag && retry)
   2183 			(void) strncat(tmpbuf, pbuf, strlen(pbuf));
   2184 		else
   2185 			(void) fprintf(stderr, "%s", pbuf);
   2186 	}
   2187 	tprintf("\n");
   2188 
   2189 	remaining_cg = sblock.fs_ncg - cylno;
   2190 
   2191 	/*
   2192 	 * If there are more than 300 cylinder groups still to be
   2193 	 * initialized, print a "." for every 50 cylinder groups.
   2194 	 */
   2195 	if (remaining_cg > 300) {
   2196 		tprintf(gettext("Initializing cylinder groups:\n"));
   2197 		do_dot = 1;
   2198 	}
   2199 
   2200 	/*
   2201 	 * Now initialize all cylinder groups between the first ten
   2202 	 * and the last ten.
   2203 	 *
   2204 	 * If the number of cylinder groups was less than 10, all of the
   2205 	 * cylinder group offsets would have printed in the last loop
   2206 	 * and cylno will already be equal to sblock.fs_ncg and so this
   2207 	 * loop will not be entered.  If there are less than 20 cylinder
   2208 	 * groups, cylno is already less than fs_ncg - 10, so this loop
   2209 	 * won't be entered in that case either.
   2210 	 */
   2211 
   2212 	i = 0;
   2213 	for (; cylno < sblock.fs_ncg - 10; cylno++) {
   2214 		if ((grow == 0) || (cylno >= grow_fs_ncg))
   2215 			initcg(cylno);
   2216 		if (do_dot && cylno % 50 == 0) {
   2217 			tprintf(".");
   2218 			i++;
   2219 			if (i == WIDTH - 1) {
   2220 				tprintf("\n");
   2221 				i = 0;
   2222 			}
   2223 		}
   2224 	}
   2225 
   2226 	/*
   2227 	 * Now print the cylinder group offsets for the last 10
   2228 	 * cylinder groups, if any are left.
   2229 	 */
   2230 
   2231 	if (do_dot) {
   2232 		tprintf(gettext(
   2233 	    "\nsuper-block backups for last 10 cylinder groups at:\n"));
   2234 	}
   2235 	for (width = 0; cylno < sblock.fs_ncg; cylno++) {
   2236 		if ((grow == 0) || (cylno >= grow_fs_ncg))
   2237 			initcg(cylno);
   2238 		num = fsbtodb(&sblock, (uint64_t)cgsblock(&sblock, cylno));
   2239 		if (Nflag && retry) {
   2240 			skip_this_sb = 0;
   2241 			rdfs((diskaddr_t)num, sbsize, (char *)&altsblock);
   2242 			ret = checksblock(altsblock, 1);
   2243 			if (ret) {
   2244 				skip_this_sb = 1;
   2245 				invalid_sb_cnt++;
   2246 				dprintf(("DeBuG checksblock() failed - error :"
   2247 				    " %d for sb : %llu invalid_sb_cnt : %d\n",
   2248 				    ret, num, invalid_sb_cnt));
   2249 			} else {
   2250 				/*
   2251 				 * Though the superblock looks sane, verify if
   2252 				 * the fs_version in the superblock and the
   2253 				 * logic that we are using to arrive at the
   2254 				 * superblocks match.
   2255 				 */
   2256 				if (use_efi_dflts && altsblock.fs_version
   2257 				    != UFS_EFISTYLE4NONEFI_VERSION_2) {
   2258 					skip_this_sb = 1;
   2259 					invalid_sb_cnt++;
   2260 				}
   2261 			}
   2262 			if (invalid_sb_cnt >= INVALIDSBLIMIT) {
   2263 				if (retry > 1) {
   2264 					(void) fprintf(stderr, gettext(
   2265 					    "Error determining alternate "
   2266 					    "superblock locations\n"));
   2267 					free(tmpbuf);
   2268 					lockexit(32);
   2269 				}
   2270 				retry++;
   2271 				use_efi_dflts = !use_efi_dflts;
   2272 				free(tmpbuf);
   2273 				goto retry_alternate_logic;
   2274 			}
   2275 			if (skip_this_sb)
   2276 				continue;
   2277 		}
   2278 		/* Don't print ',' for the last superblock */
   2279 		if (cylno == sblock.fs_ncg-1)
   2280 			(void) sprintf(pbuf, " %llu", num);
   2281 		else
   2282 			(void) sprintf(pbuf, " %llu,", num);
   2283 		plen = strlen(pbuf);
   2284 		if ((width + plen) > (WIDTH - 1)) {
   2285 			width = plen;
   2286 			tprintf("\n");
   2287 		} else {
   2288 			width += plen;
   2289 		}
   2290 		if (Nflag && retry)
   2291 			(void) strncat(tmpbuf, pbuf, strlen(pbuf));
   2292 		else
   2293 			(void) fprintf(stderr, "%s", pbuf);
   2294 	}
   2295 	tprintf("\n");
   2296 	if (Nflag) {
   2297 		if (retry)
   2298 			(void) fprintf(stderr, "%s", tmpbuf);
   2299 		free(tmpbuf);
   2300 		lockexit(0);
   2301 	}
   2302 
   2303 	free(tmpbuf);
   2304 	if (grow)
   2305 		goto grow50;
   2306 
   2307 	/*
   2308 	 * Now construct the initial file system,
   2309 	 * then write out the super-block.
   2310 	 */
   2311 	fsinit();
   2312 grow50:
   2313 	/*
   2314 	 * write the superblock and csum information
   2315 	 */
   2316 	wtsb();
   2317 
   2318 	/*
   2319 	 * extend the last cylinder group in the original file system
   2320 	 */
   2321 	if (grow) {
   2322 		extendcg(grow_fs_ncg-1);
   2323 		wtsb();
   2324 	}
   2325 
   2326 	/*
   2327 	 * Write out the duplicate super blocks to the first 10
   2328 	 * cylinder groups (or fewer, if there are fewer than 10
   2329 	 * cylinder groups).
   2330 	 */
   2331 	for (cylno = 0; cylno < sblock.fs_ncg && cylno < 10; cylno++)
   2332 		awtfs(fsbtodb(&sblock, (uint64_t)cgsblock(&sblock, cylno)),
   2333 		    (int)sbsize, (char *)&sblock, SAVE);
   2334 
   2335 	/*
   2336 	 * Now write out duplicate super blocks to the remaining
   2337 	 * cylinder groups.  In the case of multi-terabyte file
   2338 	 * systems, just write out the super block to the last ten
   2339 	 * cylinder groups (or however many are left).
   2340 	 */
   2341 	if (mtb == 'y') {
   2342 		if (sblock.fs_ncg <= 10)
   2343 			cylno = sblock.fs_ncg;
   2344 		else if (sblock.fs_ncg <= 20)
   2345 			cylno = 10;
   2346 		else
   2347 			cylno = sblock.fs_ncg - 10;
   2348 	}
   2349 
   2350 	for (; cylno < sblock.fs_ncg; cylno++)
   2351 		awtfs(fsbtodb(&sblock, (uint64_t)cgsblock(&sblock, cylno)),
   2352 		    (int)sbsize, (char *)&sblock, SAVE);
   2353 
   2354 	/*
   2355 	 * Flush out all the AIO writes we've done.  It's not
   2356 	 * necessary to do this explicitly, but it's the only
   2357 	 * way to report any errors from those writes.
   2358 	 */
   2359 	flush_writes();
   2360 
   2361 	/*
   2362 	 * set clean flag
   2363 	 */
   2364 	if (grow)
   2365 		sblock.fs_clean = grow_fs_clean;
   2366 	else
   2367 		sblock.fs_clean = FSCLEAN;
   2368 	sblock.fs_time = mkfstime;
   2369 	sblock.fs_state = FSOKAY - sblock.fs_time;
   2370 	wtfs((diskaddr_t)(SBOFF / sectorsize), sbsize, (char *)&sblock);
   2371 	isbad = 0;
   2372 
   2373 	if (fsync(fso) == -1) {
   2374 		saverr = errno;
   2375 		(void) fprintf(stderr,
   2376 		    gettext("mkfs: fsync failed on write disk: %s\n"),
   2377 		    strerror(saverr));
   2378 		/* we're just cleaning up, so keep going */
   2379 	}
   2380 	if (close(fsi) == -1) {
   2381 		saverr = errno;
   2382 		(void) fprintf(stderr,
   2383 		    gettext("mkfs: close failed on read disk: %s\n"),
   2384 		    strerror(saverr));
   2385 		/* we're just cleaning up, so keep going */
   2386 	}
   2387 	if (close(fso) == -1) {
   2388 		saverr = errno;
   2389 		(void) fprintf(stderr,
   2390 		    gettext("mkfs: close failed on write disk: %s\n"),
   2391 		    strerror(saverr));
   2392 		/* we're just cleaning up, so keep going */
   2393 	}
   2394 	fsi = fso = -1;
   2395 
   2396 #ifndef STANDALONE
   2397 	lockexit(0);
   2398 #endif
   2399 
   2400 	return (0);
   2401 }
   2402 
   2403 /*
   2404  * Figure out how big the partition we're dealing with is.
   2405  * The value returned is in disk blocks (sectors);
   2406  */
   2407 static diskaddr_t
   2408 get_max_size(int fd)
   2409 {
   2410 	struct extvtoc vtoc;
   2411 	dk_gpt_t *efi_vtoc;
   2412 	diskaddr_t	slicesize;
   2413 
   2414 	int index = read_extvtoc(fd, &vtoc);
   2415 
   2416 	if (index >= 0) {
   2417 		label_type = LABEL_TYPE_VTOC;
   2418 	} else {
   2419 		if (index == VT_ENOTSUP || index == VT_ERROR) {
   2420 			/* it might be an EFI label */
   2421 			index = efi_alloc_and_read(fd, &efi_vtoc);
   2422 			label_type = LABEL_TYPE_EFI;
   2423 		}
   2424 	}
   2425 
   2426 	if (index < 0) {
   2427 		switch (index) {
   2428 		case VT_ERROR:
   2429 			break;
   2430 		case VT_EIO:
   2431 			errno = EIO;
   2432 			break;
   2433 		case VT_EINVAL:
   2434 			errno = EINVAL;
   2435 		}
   2436 		perror(gettext("Can not determine partition size"));
   2437 		lockexit(32);
   2438 	}
   2439 
   2440 	if (label_type == LABEL_TYPE_EFI) {
   2441 		slicesize = efi_vtoc->efi_parts[index].p_size;
   2442 		efi_free(efi_vtoc);
   2443 	} else {
   2444 		/*
   2445 		 * In the vtoc struct, p_size is a 32-bit signed quantity.
   2446 		 * In the dk_gpt struct (efi's version of the vtoc), p_size
   2447 		 * is an unsigned 64-bit quantity.  By casting the vtoc's
   2448 		 * psize to an unsigned 32-bit quantity, it will be copied
   2449 		 * to 'slicesize' (an unsigned 64-bit diskaddr_t) without
   2450 		 * sign extension.
   2451 		 */
   2452 
   2453 		slicesize = (uint32_t)vtoc.v_part[index].p_size;
   2454 	}
   2455 
   2456 	dprintf(("DeBuG get_max_size index = %d, p_size = %lld, dolimit = %d\n",
   2457 	    index, slicesize, (slicesize > FS_MAX)));
   2458 
   2459 	/*
   2460 	 * The next line limits a UFS file system to the maximum
   2461 	 * supported size.
   2462 	 */
   2463 
   2464 	if (slicesize > FS_MAX)
   2465 		return (FS_MAX);
   2466 	return (slicesize);
   2467 }
   2468 
   2469 static long
   2470 get_max_track_size(int fd)
   2471 {
   2472 	struct dk_cinfo ci;
   2473 	long track_size = -1;
   2474 
   2475 	if (ioctl(fd, DKIOCINFO, &ci) == 0) {
   2476 		track_size = ci.dki_maxtransfer * DEV_BSIZE;
   2477 	}
   2478 
   2479 	if ((track_size < 0)) {
   2480 		int	error = 0;
   2481 		int	maxphys;
   2482 		int	gotit = 0;
   2483 
   2484 		gotit = fsgetmaxphys(&maxphys, &error);
   2485 		if (gotit) {
   2486 			track_size = MIN(MB, maxphys);
   2487 		} else {
   2488 			(void) fprintf(stderr, gettext(
   2489 "Warning: Could not get system value for maxphys. The value for\n"
   2490 "maxcontig will default to 1MB.\n"));
   2491 			track_size = MB;
   2492 		}
   2493 	}
   2494 	return (track_size);
   2495 }
   2496 
   2497 /*
   2498  * Initialize a cylinder group.
   2499  */
   2500 static void
   2501 initcg(int cylno)
   2502 {
   2503 	diskaddr_t cbase, d;
   2504 	diskaddr_t dlower;	/* last data block before cg metadata */
   2505 	diskaddr_t dupper;	/* first data block after cg metadata */
   2506 	diskaddr_t dmax;
   2507 	int64_t i;
   2508 	struct csum *cs;
   2509 	struct dinode *inode_buffer;
   2510 	int size;
   2511 
   2512 	/*
   2513 	 * Variables used to store intermediate results as a part of
   2514 	 * the internal implementation of the cbtocylno() macros.
   2515 	 */
   2516 	diskaddr_t bno;		/* UFS block number (not sector number) */
   2517 	int	cbcylno;	/* current cylinder number */
   2518 	int	cbcylno_sect;	/* sector offset within cylinder */
   2519 	int	cbsect_incr;	/* amount to increment sector offset */
   2520 
   2521 	/*
   2522 	 * Variables used to store intermediate results as a part of
   2523 	 * the internal implementation of the cbtorpos() macros.
   2524 	 */
   2525 	short	*cgblks;	/* pointer to array of free blocks in cg */
   2526 	int	trackrpos;	/* tmp variable for rotation position */
   2527 	int	trackoff;	/* offset within a track */
   2528 	int	trackoff_incr;	/* amount to increment trackoff */
   2529 	int	rpos;		/* rotation position of current block */
   2530 	int	rpos_incr;	/* amount to increment rpos per block */
   2531 
   2532 	union cgun *icgun;	/* local pointer to a cg summary block */
   2533 #define	icg	(icgun->cg)
   2534 
   2535 	icgun = (union cgun *)getbuf(&cgsumbuf, sizeof (union cgun));
   2536 
   2537 	/*
   2538 	 * Determine block bounds for cylinder group.
   2539 	 * Allow space for super block summary information in first
   2540 	 * cylinder group.
   2541 	 */
   2542 	cbase = cgbase(&sblock, cylno);
   2543 	dmax = cbase + sblock.fs_fpg;
   2544 	if (dmax > sblock.fs_size)	/* last cg may be smaller than normal */
   2545 		dmax = sblock.fs_size;
   2546 	dlower = cgsblock(&sblock, cylno) - cbase;
   2547 	dupper = cgdmin(&sblock, cylno) - cbase;
   2548 	if (cylno == 0)
   2549 		dupper += howmany(sblock.fs_cssize, sblock.fs_fsize);
   2550 	cs = fscs + cylno;
   2551 	icg.cg_time = mkfstime;
   2552 	icg.cg_magic = CG_MAGIC;
   2553 	icg.cg_cgx = cylno;
   2554 	/* last one gets whatever's left */
   2555 	if (cylno == sblock.fs_ncg - 1)
   2556 		icg.cg_ncyl = sblock.fs_ncyl - (sblock.fs_cpg * cylno);
   2557 	else
   2558 		icg.cg_ncyl = sblock.fs_cpg;
   2559 	icg.cg_niblk = sblock.fs_ipg;
   2560 	icg.cg_ndblk = dmax - cbase;
   2561 	icg.cg_cs.cs_ndir = 0;
   2562 	icg.cg_cs.cs_nffree = 0;
   2563 	icg.cg_cs.cs_nbfree = 0;
   2564 	icg.cg_cs.cs_nifree = 0;
   2565 	icg.cg_rotor = 0;
   2566 	icg.cg_frotor = 0;
   2567 	icg.cg_irotor = 0;
   2568 	icg.cg_btotoff = &icg.cg_space[0] - (uchar_t *)(&icg.cg_link);
   2569 	icg.cg_boff = icg.cg_btotoff + sblock.fs_cpg * sizeof (long);
   2570 	icg.cg_iusedoff = icg.cg_boff +
   2571 	    sblock.fs_cpg * sblock.fs_nrpos * sizeof (short);
   2572 	icg.cg_freeoff = icg.cg_iusedoff + howmany(sblock.fs_ipg, NBBY);
   2573 	icg.cg_nextfreeoff = icg.cg_freeoff +
   2574 	    howmany(sblock.fs_cpg * sblock.fs_spc / NSPF(&sblock), NBBY);
   2575 	for (i = 0; i < sblock.fs_frag; i++) {
   2576 		icg.cg_frsum[i] = 0;
   2577 	}
   2578 	bzero((caddr_t)cg_inosused(&icg), icg.cg_freeoff - icg.cg_iusedoff);
   2579 	icg.cg_cs.cs_nifree += sblock.fs_ipg;
   2580 	if (cylno == 0)
   2581 		for (i = 0; i < UFSROOTINO; i++) {
   2582 			setbit(cg_inosused(&icg), i);
   2583 			icg.cg_cs.cs_nifree--;
   2584 		}
   2585 
   2586 	/*
   2587 	 * Initialize all the inodes in the cylinder group using
   2588 	 * random numbers.
   2589 	 */
   2590 	size = sblock.fs_ipg * sizeof (struct dinode);
   2591 	inode_buffer = (struct dinode *)getbuf(&inodebuf, size);
   2592 
   2593 	for (i = 0; i < sblock.fs_ipg; i++) {
   2594 		IRANDOMIZE(&(inode_buffer[i].di_ic));
   2595 	}
   2596 
   2597 	/*
   2598 	 * Write all inodes in a single write for performance.
   2599 	 */
   2600 	awtfs(fsbtodb(&sblock, (uint64_t)cgimin(&sblock, cylno)), (int)size,
   2601 	    (char *)inode_buffer, RELEASE);
   2602 
   2603 	bzero((caddr_t)cg_blktot(&icg), icg.cg_boff - icg.cg_btotoff);
   2604 	bzero((caddr_t)cg_blks(&sblock, &icg, 0),
   2605 	    icg.cg_iusedoff - icg.cg_boff);
   2606 	bzero((caddr_t)cg_blksfree(&icg), icg.cg_nextfreeoff - icg.cg_freeoff);
   2607 
   2608 	if (cylno > 0) {
   2609 		for (d = 0; d < dlower; d += sblock.fs_frag) {
   2610 			setblock(&sblock, cg_blksfree(&icg), d/sblock.fs_frag);
   2611 			icg.cg_cs.cs_nbfree++;
   2612 			cg_blktot(&icg)[cbtocylno(&sblock, d)]++;
   2613 			cg_blks(&sblock, &icg, cbtocylno(&sblock, d))
   2614 			    [cbtorpos(&sblock, d)]++;
   2615 		}
   2616 		sblock.fs_dsize += dlower;
   2617 	}
   2618 	sblock.fs_dsize += icg.cg_ndblk - dupper;
   2619 	if ((i = dupper % sblock.fs_frag) != 0) {
   2620 		icg.cg_frsum[sblock.fs_frag - i]++;
   2621 		for (d = dupper + sblock.fs_frag - i; dupper < d; dupper++) {
   2622 			setbit(cg_blksfree(&icg), dupper);
   2623 			icg.cg_cs.cs_nffree++;
   2624 		}
   2625 	}
   2626 
   2627 	/*
   2628 	 * WARNING: The following code is somewhat confusing, but
   2629 	 * results in a substantial performance improvement in mkfs.
   2630 	 *
   2631 	 * Instead of using cbtocylno() and cbtorpos() macros, we
   2632 	 * keep track of all the intermediate state of those macros
   2633 	 * in some variables.  This allows simple addition to be
   2634 	 * done to calculate the results as we step through the
   2635 	 * blocks in an orderly fashion instead of the slower
   2636 	 * multiplication and division the macros are forced to
   2637 	 * used so they can support random input.  (Multiplication,
   2638 	 * division, and remainder operations typically take about
   2639 	 * 10x as many processor cycles as other operations.)
   2640 	 *
   2641 	 * The basic idea is to take code:
   2642 	 *
   2643 	 *	for (x = starting_x; x < max; x++)
   2644 	 *		y = (x * c) / z
   2645 	 *
   2646 	 * and rewrite it to take advantage of the fact that
   2647 	 * the variable x is incrementing in an orderly way:
   2648 	 *
   2649 	 *	intermediate = starting_x * c
   2650 	 *	yval = intermediate / z
   2651 	 *	for (x = starting_x; x < max; x++) {
   2652 	 *		y = yval;
   2653 	 *		intermediate += c
   2654 	 *		if (intermediate > z) {
   2655 	 *			yval++;
   2656 	 *			intermediate -= z
   2657 	 *		}
   2658 	 *	}
   2659 	 *
   2660 	 * Performance has improved as much as 4X using this code.
   2661 	 */
   2662 
   2663 	/*
   2664 	 * Initialize the starting points for all the cbtocylno()
   2665 	 * macro variables and figure out the increments needed each
   2666 	 * time through the loop.
   2667 	 */
   2668 	cbcylno_sect = dupper * NSPF(&sblock);
   2669 	cbsect_incr = sblock.fs_frag * NSPF(&sblock);
   2670 	cbcylno = cbcylno_sect / sblock.fs_spc;
   2671 	cbcylno_sect %= sblock.fs_spc;
   2672 	cgblks = cg_blks(&sblock, &icg, cbcylno);
   2673 	bno = dupper / sblock.fs_frag;
   2674 
   2675 	/*
   2676 	 * Initialize the starting points for all the cbtorpos()
   2677 	 * macro variables and figure out the increments needed each
   2678 	 * time through the loop.
   2679 	 *
   2680 	 * It's harder to simplify the cbtorpos() macro if there were
   2681 	 * alternate sectors specified (or if they previously existed
   2682 	 * in the growfs case).  Since this is rare, we just revert to
   2683 	 * using the macros in this case and skip the variable setup.
   2684 	 */
   2685 	if (!spc_flag) {
   2686 		trackrpos = (cbcylno_sect % sblock.fs_nsect) * sblock.fs_nrpos;
   2687 		rpos = trackrpos / sblock.fs_nsect;
   2688 		trackoff = trackrpos % sblock.fs_nsect;
   2689 		trackoff_incr = cbsect_incr * sblock.fs_nrpos;
   2690 		rpos_incr = (trackoff_incr / sblock.fs_nsect) % sblock.fs_nrpos;
   2691 		trackoff_incr = trackoff_incr % sblock.fs_nsect;
   2692 	}
   2693 
   2694 	/*
   2695 	 * Loop through all the blocks, marking them free and
   2696 	 * updating totals kept in the superblock and cg summary.
   2697 	 */
   2698 	for (d = dupper; d + sblock.fs_frag <= dmax - cbase; ) {
   2699 		setblock(&sblock, cg_blksfree(&icg),  bno);
   2700 		icg.cg_cs.cs_nbfree++;
   2701 
   2702 		cg_blktot(&icg)[cbcylno]++;
   2703 
   2704 		if (!spc_flag)
   2705 			cgblks[rpos]++;
   2706 		else
   2707 			cg_blks(&sblock, &icg, cbtocylno(&sblock, d))
   2708 			    [cbtorpos(&sblock, d)]++;
   2709 
   2710 		d += sblock.fs_frag;
   2711 		bno++;
   2712 
   2713 		/*
   2714 		 * Increment the sector offset within the cylinder
   2715 		 * for the cbtocylno() macro reimplementation.  If
   2716 		 * we're beyond the end of the cylinder, update the
   2717 		 * cylinder number, calculate the offset in the
   2718 		 * new cylinder, and update the cgblks pointer
   2719 		 * to the next rotational position.
   2720 		 */
   2721 		cbcylno_sect += cbsect_incr;
   2722 		if (cbcylno_sect >= sblock.fs_spc) {
   2723 			cbcylno++;
   2724 			cbcylno_sect -= sblock.fs_spc;
   2725 			cgblks += sblock.fs_nrpos;
   2726 		}
   2727 
   2728 		/*
   2729 		 * If there aren't alternate sectors, increment the
   2730 		 * rotational position variables for the cbtorpos()
   2731 		 * reimplementation.  Note that we potentially
   2732 		 * increment rpos twice.  Once by rpos_incr, and one
   2733 		 * more time when we wrap to a new track because
   2734 		 * trackoff >= fs_nsect.
   2735 		 */
   2736 		if (!spc_flag) {
   2737 			trackoff += trackoff_incr;
   2738 			rpos += rpos_incr;
   2739 			if (trackoff >= sblock.fs_nsect) {
   2740 				trackoff -= sblock.fs_nsect;
   2741 				rpos++;
   2742 			}
   2743 			if (rpos >= sblock.fs_nrpos)
   2744 				rpos -= sblock.fs_nrpos;
   2745 		}
   2746 	}
   2747 
   2748 	if (d < dmax - cbase) {
   2749 		icg.cg_frsum[dmax - cbase - d]++;
   2750 		for (; d < dmax - cbase; d++) {
   2751 			setbit(cg_blksfree(&icg), d);
   2752 			icg.cg_cs.cs_nffree++;
   2753 		}
   2754 	}
   2755 	sblock.fs_cstotal.cs_ndir += icg.cg_cs.cs_ndir;
   2756 	sblock.fs_cstotal.cs_nffree += icg.cg_cs.cs_nffree;
   2757 	sblock.fs_cstotal.cs_nbfree += icg.cg_cs.cs_nbfree;
   2758 	sblock.fs_cstotal.cs_nifree += icg.cg_cs.cs_nifree;
   2759 	*cs = icg.cg_cs;
   2760 	awtfs(fsbtodb(&sblock, (uint64_t)cgtod(&sblock, cylno)),
   2761 	    sblock.fs_bsize, (char *)&icg, RELEASE);
   2762 }
   2763 
   2764 /*
   2765  * initialize the file system
   2766  */
   2767 struct inode node;
   2768 
   2769 #define	LOSTDIR
   2770 #ifdef LOSTDIR
   2771 #define	PREDEFDIR 3
   2772 #else
   2773 #define	PREDEFDIR 2
   2774 #endif
   2775 
   2776 struct direct root_dir[] = {
   2777 	{ UFSROOTINO, sizeof (struct direct), 1, "." },
   2778 	{ UFSROOTINO, sizeof (struct direct), 2, ".." },
   2779 #ifdef LOSTDIR
   2780 	{ LOSTFOUNDINO, sizeof (struct direct), 10, "lost+found" },
   2781 #endif
   2782 };
   2783 #ifdef LOSTDIR
   2784 struct direct lost_found_dir[] = {
   2785 	{ LOSTFOUNDINO, sizeof (struct direct), 1, "." },
   2786 	{ UFSROOTINO, sizeof (struct direct), 2, ".." },
   2787 	{ 0, DIRBLKSIZ, 0, 0 },
   2788 };
   2789 #endif
   2790 char buf[MAXBSIZE];
   2791 
   2792 static void
   2793 fsinit()
   2794 {
   2795 	int i;
   2796 
   2797 
   2798 	/*
   2799 	 * initialize the node
   2800 	 */
   2801 	node.i_atime = mkfstime;
   2802 	node.i_mtime = mkfstime;
   2803 	node.i_ctime = mkfstime;
   2804 #ifdef LOSTDIR
   2805 	/*
   2806 	 * create the lost+found directory
   2807 	 */
   2808 	(void) makedir(lost_found_dir, 2);
   2809 	for (i = DIRBLKSIZ; i < sblock.fs_bsize; i += DIRBLKSIZ) {
   2810 		bcopy(&lost_found_dir[2], &buf[i], DIRSIZ(&lost_found_dir[2]));
   2811 	}
   2812 	node.i_number = LOSTFOUNDINO;
   2813 	node.i_smode = node.i_mode = IFDIR | 0700;
   2814 	node.i_nlink = 2;
   2815 	node.i_size = sblock.fs_bsize;
   2816 	node.i_db[0] = alloc((int)node.i_size, node.i_mode);
   2817 	node.i_blocks = btodb(fragroundup(&sblock, (int)node.i_size));
   2818 	IRANDOMIZE(&node.i_ic);
   2819 	wtfs(fsbtodb(&sblock, (uint64_t)node.i_db[0]), (int)node.i_size, buf);
   2820 	iput(&node);
   2821 #endif
   2822 	/*
   2823 	 * create the root directory
   2824 	 */
   2825 	node.i_number = UFSROOTINO;
   2826 	node.i_mode = node.i_smode = IFDIR | UMASK;
   2827 	node.i_nlink = PREDEFDIR;
   2828 	node.i_size = makedir(root_dir, PREDEFDIR);
   2829 	node.i_db[0] = alloc(sblock.fs_fsize, node.i_mode);
   2830 	/* i_size < 2GB because we are initializing the file system */
   2831 	node.i_blocks = btodb(fragroundup(&sblock, (int)node.i_size));
   2832 	IRANDOMIZE(&node.i_ic);
   2833 	wtfs(fsbtodb(&sblock, (uint64_t)node.i_db[0]), sblock.fs_fsize, buf);
   2834 	iput(&node);
   2835 }
   2836 
   2837 /*
   2838  * construct a set of directory entries in "buf".
   2839  * return size of directory.
   2840  */
   2841 static int
   2842 makedir(struct direct *protodir, int entries)
   2843 {
   2844 	char *cp;
   2845 	int i;
   2846 	ushort_t spcleft;
   2847 
   2848 	spcleft = DIRBLKSIZ;
   2849 	for (cp = buf, i = 0; i < entries - 1; i++) {
   2850 		protodir[i].d_reclen = DIRSIZ(&protodir[i]);
   2851 		bcopy(&protodir[i], cp, protodir[i].d_reclen);
   2852 		cp += protodir[i].d_reclen;
   2853 		spcleft -= protodir[i].d_reclen;
   2854 	}
   2855 	protodir[i].d_reclen = spcleft;
   2856 	bcopy(&protodir[i], cp, DIRSIZ(&protodir[i]));
   2857 	return (DIRBLKSIZ);
   2858 }
   2859 
   2860 /*
   2861  * allocate a block or frag
   2862  */
   2863 static daddr32_t
   2864 alloc(int size, int mode)
   2865 {
   2866 	int i, frag;
   2867 	daddr32_t d;
   2868 
   2869 	rdfs(fsbtodb(&sblock, (uint64_t)cgtod(&sblock, 0)), sblock.fs_cgsize,
   2870 	    (char *)&acg);
   2871 	if (acg.cg_magic != CG_MAGIC) {
   2872 		(void) fprintf(stderr, gettext("cg 0: bad magic number\n"));
   2873 		lockexit(32);
   2874 	}
   2875 	if (acg.cg_cs.cs_nbfree == 0) {
   2876 		(void) fprintf(stderr,
   2877 		    gettext("first cylinder group ran out of space\n"));
   2878 		lockexit(32);
   2879 	}
   2880 	for (d = 0; d < acg.cg_ndblk; d += sblock.fs_frag)
   2881 		if (isblock(&sblock, cg_blksfree(&acg), d / sblock.fs_frag))
   2882 			goto goth;
   2883 	(void) fprintf(stderr,
   2884 	    gettext("internal error: can't find block in cyl 0\n"));
   2885 	lockexit(32);
   2886 goth:
   2887 	clrblock(&sblock, cg_blksfree(&acg), d / sblock.fs_frag);
   2888 	acg.cg_cs.cs_nbfree--;
   2889 	sblock.fs_cstotal.cs_nbfree--;
   2890 	fscs[0].cs_nbfree--;
   2891 	if (mode & IFDIR) {
   2892 		acg.cg_cs.cs_ndir++;
   2893 		sblock.fs_cstotal.cs_ndir++;
   2894 		fscs[0].cs_ndir++;
   2895 	}
   2896 	cg_blktot(&acg)[cbtocylno(&sblock, d)]--;
   2897 	cg_blks(&sblock, &acg, cbtocylno(&sblock, d))[cbtorpos(&sblock, d)]--;
   2898 	if (size != sblock.fs_bsize) {
   2899 		frag = howmany(size, sblock.fs_fsize);
   2900 		fscs[0].cs_nffree += sblock.fs_frag - frag;
   2901 		sblock.fs_cstotal.cs_nffree += sblock.fs_frag - frag;
   2902 		acg.cg_cs.cs_nffree += sblock.fs_frag - frag;
   2903 		acg.cg_frsum[sblock.fs_frag - frag]++;
   2904 		for (i = frag; i < sblock.fs_frag; i++)
   2905 			setbit(cg_blksfree(&acg), d + i);
   2906 	}
   2907 	wtfs(fsbtodb(&sblock, (uint64_t)cgtod(&sblock, 0)), sblock.fs_cgsize,
   2908 	    (char *)&acg);
   2909 	return (d);
   2910 }
   2911 
   2912 /*
   2913  * Allocate an inode on the disk
   2914  */
   2915 static void
   2916 iput(struct inode *ip)
   2917 {
   2918 	struct dinode buf[MAXINOPB];
   2919 	diskaddr_t d;
   2920 
   2921 	rdfs(fsbtodb(&sblock, (uint64_t)cgtod(&sblock, 0)), sblock.fs_cgsize,
   2922 	    (char *)&acg);
   2923 	if (acg.cg_magic != CG_MAGIC) {
   2924 		(void) fprintf(stderr, gettext("cg 0: bad magic number\n"));
   2925 		lockexit(32);
   2926 	}
   2927 	acg.cg_cs.cs_nifree--;
   2928 	setbit(cg_inosused(&acg), ip->i_number);
   2929 	wtfs(fsbtodb(&sblock, (uint64_t)cgtod(&sblock, 0)), sblock.fs_cgsize,
   2930 	    (char *)&acg);
   2931 	sblock.fs_cstotal.cs_nifree--;
   2932 	fscs[0].cs_nifree--;
   2933 	if ((int)ip->i_number >= sblock.fs_ipg * sblock.fs_ncg) {
   2934 		(void) fprintf(stderr,
   2935 		    gettext("fsinit: inode value out of range (%d).\n"),
   2936 		    ip->i_number);
   2937 		lockexit(32);
   2938 	}
   2939 	d = fsbtodb(&sblock, (uint64_t)itod(&sblock, (int)ip->i_number));
   2940 	rdfs(d, sblock.fs_bsize, (char *)buf);
   2941 	buf[itoo(&sblock, (int)ip->i_number)].di_ic = ip->i_ic;
   2942 	wtfs(d, sblock.fs_bsize, (char *)buf);
   2943 }
   2944 
   2945 /*
   2946  * getbuf()	-- Get a buffer for use in an AIO operation.  Buffer
   2947  *		is zero'd the first time returned, left with whatever
   2948  *		was in memory after that.  This function actually gets
   2949  *		enough memory the first time it's called to support
   2950  *		MAXBUF buffers like a slab allocator.  When all the
   2951  *		buffers are in use, it waits for an aio to complete
   2952  *		and make a buffer available.
   2953  *
   2954  *		Never returns an error.  Either succeeds or exits.
   2955  */
   2956 static char *
   2957 getbuf(bufhdr *bufhead, int size)
   2958 {
   2959 	bufhdr *pbuf;
   2960 	bufhdr *prev;
   2961 	int i;
   2962 	int buf_size, max_bufs;
   2963 
   2964 	/*
   2965 	 * Initialize all the buffers
   2966 	 */
   2967 	if (bufhead->head == NULL) {
   2968 		/*
   2969 		 * round up the size of our buffer header to a
   2970 		 * 16 byte boundary so the address we return to
   2971 		 * the caller is "suitably aligned".
   2972 		 */
   2973 		bufhdrsize = (sizeof (bufhdr) + 15) & ~15;
   2974 
   2975 		/*
   2976 		 * Add in our header to the buffer and round it all up to
   2977 		 * a 16 byte boundry so each member of the slab is aligned.
   2978 		 */
   2979 		buf_size = (size + bufhdrsize + 15) & ~15;
   2980 
   2981 		/*
   2982 		 * Limit number of buffers to lesser of MAXBUFMEM's worth
   2983 		 * or MAXBUF, whichever is less.
   2984 		 */
   2985 		max_bufs = MAXBUFMEM / buf_size;
   2986 		if (max_bufs > MAXBUF)
   2987 			max_bufs = MAXBUF;
   2988 
   2989 		pbuf = (bufhdr *)calloc(max_bufs, buf_size);
   2990 		if (pbuf == NULL) {
   2991 			perror("calloc");
   2992 			lockexit(32);
   2993 		}
   2994 
   2995 		bufhead->head = bufhead;
   2996 		prev = bufhead;
   2997 		for (i = 0; i < max_bufs; i++) {
   2998 			pbuf->head = bufhead;
   2999 			prev->next = pbuf;
   3000 			prev = pbuf;
   3001 			pbuf = (bufhdr *)((char *)pbuf + buf_size);
   3002 		}
   3003 	}
   3004 
   3005 	/*
   3006 	 * Get an available buffer, waiting for I/O if necessary
   3007 	 */
   3008 	wait_for_write(NOBLOCK);
   3009 	while (bufhead->next == NULL)
   3010 		wait_for_write(BLOCK);
   3011 
   3012 	/*
   3013 	 * Take the buffer off the list
   3014 	 */
   3015 	pbuf = bufhead->next;
   3016 	bufhead->next = pbuf->next;
   3017 	pbuf->next = NULL;
   3018 
   3019 	/*
   3020 	 * return the empty buffer space just past the header
   3021 	 */
   3022 	return ((char *)pbuf + bufhdrsize);
   3023 }
   3024 
   3025 /*
   3026  * freebuf()	-- Free a buffer gotten previously through getbuf.
   3027  *		Puts the buffer back on the appropriate list for
   3028  *		later use.  Never calls free().
   3029  *
   3030  * Assumes that SIGINT is blocked.
   3031  */
   3032 static void
   3033 freebuf(char *buf)
   3034 {
   3035 	bufhdr *pbuf;
   3036 	bufhdr *bufhead;
   3037 
   3038 	/*
   3039 	 * get the header for this buffer
   3040 	 */
   3041 	pbuf = (bufhdr *)(buf - bufhdrsize);
   3042 
   3043 	/*
   3044 	 * Put it back on the list of available buffers
   3045 	 */
   3046 	bufhead = pbuf->head;
   3047 	pbuf->next = bufhead->next;
   3048 	bufhead->next = pbuf;
   3049 }
   3050 
   3051 /*
   3052  * freetrans()	-- Free a transaction gotten previously through getaiop.
   3053  *		Puts the transaction struct back on the appropriate list for
   3054  *		later use.  Never calls free().
   3055  *
   3056  * Assumes that SIGINT is blocked.
   3057  */
   3058 static void
   3059 freetrans(aio_trans *transp)
   3060 {
   3061 	/*
   3062 	 * free the buffer associated with this AIO if needed
   3063 	 */
   3064 	if (transp->release == RELEASE)
   3065 		freebuf(transp->buffer);
   3066 
   3067 	/*
   3068 	 * Put transaction on the free list
   3069 	 */
   3070 	transp->next = results.trans;
   3071 	results.trans = transp;
   3072 }
   3073 
   3074 /*
   3075  * wait_for_write()	-- Wait for an aio write to complete.  Return
   3076  *			the transaction structure for that write.
   3077  *
   3078  * Blocks SIGINT if necessary.
   3079  */
   3080 aio_trans *
   3081 wait_for_write(int block)
   3082 {
   3083 	aio_trans	*transp;
   3084 	aio_result_t	*resultp;
   3085 	static struct timeval  zero_wait = { 0, 0 };
   3086 	sigset_t	old_mask;
   3087 
   3088 	/*
   3089 	 * If we know there aren't any outstanding transactions, just return
   3090 	 */
   3091 	if (results.outstanding == 0)
   3092 		return ((aio_trans *) 0);
   3093 
   3094 	block_sigint(&old_mask);
   3095 
   3096 	resultp = aiowait(block ? NULL : &zero_wait);
   3097 	if (resultp == NULL ||
   3098 	    (resultp == (aio_result_t *)-1 && errno == EINVAL)) {
   3099 		unblock_sigint(&old_mask);
   3100 		return ((aio_trans *) 0);
   3101 	}
   3102 
   3103 	results.outstanding--;
   3104 	transp = (aio_trans *)resultp;
   3105 
   3106 	if (resultp->aio_return != transp->size) {
   3107 		if (resultp->aio_return == -1) {
   3108 			/*
   3109 			 * The aiowrite() may have failed because the
   3110 			 * kernel didn't have enough memory to do the job.
   3111 			 * Flush all pending writes and try a normal
   3112 			 * write().  wtfs_breakup() will call exit if it
   3113 			 * fails, so we don't worry about errors here.
   3114 			 */
   3115 			flush_writes();
   3116 			wtfs_breakup(transp->bno, transp->size, transp->buffer);
   3117 		} else {
   3118 			(void) fprintf(stderr, gettext(
   3119 			    "short write (%d of %d bytes) on sector %lld\n"),
   3120 			    resultp->aio_return, transp->size,
   3121 			    transp->bno);
   3122 			/*
   3123 			 * Don't unblock SIGINT, to avoid potential
   3124 			 * looping due to queued interrupts and
   3125 			 * error handling.
   3126 			 */
   3127 			lockexit(32);
   3128 		}
   3129 	}
   3130 
   3131 	resultp->aio_return = 0;
   3132 	freetrans(transp);
   3133 	unblock_sigint(&old_mask);
   3134 	return (transp);
   3135 }
   3136 
   3137 /*
   3138  * flush_writes()	-- flush all the outstanding aio writes.
   3139  */
   3140 static void
   3141 flush_writes(void)
   3142 {
   3143 	while (wait_for_write(BLOCK))
   3144 		;
   3145 }
   3146 
   3147 /*
   3148  * get_aiop()	-- find and return an aio_trans structure on which a new
   3149  *		aio can be done.  Blocks on aiowait() if needed.  Reaps
   3150  *		all outstanding completed aio's.
   3151  *
   3152  * Assumes that SIGINT is blocked.
   3153  */
   3154 aio_trans *
   3155 get_aiop()
   3156 {
   3157 	int i;
   3158 	aio_trans *transp;
   3159 	aio_trans *prev;
   3160 
   3161 	/*
   3162 	 * initialize aio stuff
   3163 	 */
   3164 	if (!aio_inited) {
   3165 		aio_inited = 1;
   3166 
   3167 		results.maxpend = 0;
   3168 		results.outstanding = 0;
   3169 		results.max = MAXAIO;
   3170 
   3171 		results.trans = (aio_trans *)calloc(results.max,
   3172 		    sizeof (aio_trans));
   3173 		if (results.trans == NULL) {
   3174 			perror("calloc");
   3175 			lockexit(32);
   3176 		}
   3177 
   3178 		/*
   3179 		 * Initialize the linked list of aio transaction
   3180 		 * structures.  Note that the final "next" pointer
   3181 		 * will be NULL since we got the buffer from calloc().
   3182 		 */
   3183 		prev = results.trans;
   3184 		for (i = 1; i < results.max; i++) {
   3185 			prev->next = &(results.trans[i]);
   3186 			prev = prev->next;
   3187 		}
   3188 	}
   3189 
   3190 	wait_for_write(NOBLOCK);
   3191 	while (results.trans == NULL)
   3192 		wait_for_write(BLOCK);
   3193 	transp = results.trans;
   3194 	results.trans = results.trans->next;
   3195 
   3196 	transp->next = 0;
   3197 	transp->resultbuf.aio_return = AIO_INPROGRESS;
   3198 	return (transp);
   3199 }
   3200 
   3201 /*
   3202  * read a block from the file system
   3203  */
   3204 static void
   3205 rdfs(diskaddr_t bno, int size, char *bf)
   3206 {
   3207 	int n, saverr;
   3208 
   3209 	/*
   3210 	 * In case we need any data that's pending in an aiowrite(),
   3211 	 * we wait for them all to complete before doing a read.
   3212 	 */
   3213 	flush_writes();
   3214 
   3215 	/*
   3216 	 * Note: the llseek() can succeed, even if the offset is out of range.
   3217 	 * It's not until the file i/o operation (the read()) that one knows
   3218 	 * for sure if the raw device can handle the offset.
   3219 	 */
   3220 	if (llseek(fsi, (offset_t)bno * sectorsize, 0) < 0) {
   3221 		saverr = errno;
   3222 		(void) fprintf(stderr,
   3223 		    gettext("seek error on sector %lld: %s\n"),
   3224 		    bno, strerror(saverr));
   3225 		lockexit(32);
   3226 	}
   3227 	n = read(fsi, bf, size);
   3228 	if (n != size) {
   3229 		saverr = errno;
   3230 		if (n == -1)
   3231 			(void) fprintf(stderr,
   3232 			    gettext("read error on sector %lld: %s\n"),
   3233 			    bno, strerror(saverr));
   3234 		else
   3235 			(void) fprintf(stderr, gettext(
   3236 			    "short read (%d of %d bytes) on sector %lld\n"),
   3237 			    n, size, bno);
   3238 		lockexit(32);
   3239 	}
   3240 }
   3241 
   3242 /*
   3243  * write a block to the file system
   3244  */
   3245 static void
   3246 wtfs(diskaddr_t bno, int size, char *bf)
   3247 {
   3248 	int n, saverr;
   3249 
   3250 	if (fso == -1)
   3251 		return;
   3252 
   3253 	/*
   3254 	 * Note: the llseek() can succeed, even if the offset is out of range.
   3255 	 * It's not until the file i/o operation (the write()) that one knows
   3256 	 * for sure if the raw device can handle the offset.
   3257 	 */
   3258 	if (llseek(fso, (offset_t)bno * sectorsize, 0) < 0) {
   3259 		saverr = errno;
   3260 		(void) fprintf(stderr,
   3261 		    gettext("seek error on sector %lld: %s\n"),
   3262 		    bno, strerror(saverr));
   3263 		lockexit(32);
   3264 	}
   3265 	if (Nflag)
   3266 		return;
   3267 	n = write(fso, bf, size);
   3268 	if (n != size) {
   3269 		saverr = errno;
   3270 		if (n == -1)
   3271 			(void) fprintf(stderr,
   3272 			    gettext("write error on sector %lld: %s\n"),
   3273 			    bno, strerror(saverr));
   3274 		else
   3275 			(void) fprintf(stderr, gettext(
   3276 			    "short write (%d of %d bytes) on sector %lld\n"),
   3277 			    n, size, bno);
   3278 		lockexit(32);
   3279 	}
   3280 }
   3281 
   3282 /*
   3283  * write a block to the file system -- buffered with aio
   3284  */
   3285 static void
   3286 awtfs(diskaddr_t bno, int size, char *bf, int release)
   3287 {
   3288 	int n;
   3289 	aio_trans 	*transp;
   3290 	sigset_t 	old_mask;
   3291 
   3292 	if (fso == -1)
   3293 		return;
   3294 
   3295 	/*
   3296 	 * We need to keep things consistent if we get interrupted,
   3297 	 * so defer any expected interrupts for the time being.
   3298 	 */
   3299 	block_sigint(&old_mask);
   3300 
   3301 	if (Nflag) {
   3302 		if (release == RELEASE)
   3303 			freebuf(bf);
   3304 	} else {
   3305 		transp = get_aiop();
   3306 		transp->bno = bno;
   3307 		transp->buffer = bf;
   3308 		transp->size = size;
   3309 		transp->release = release;
   3310 
   3311 		n = aiowrite(fso, bf, size, (off_t)bno * sectorsize,
   3312 		    SEEK_SET, &transp->resultbuf);
   3313 
   3314 		if (n < 0) {
   3315 			/*
   3316 			 * The aiowrite() may have failed because the
   3317 			 * kernel didn't have enough memory to do the job.
   3318 			 * Flush all pending writes and try a normal
   3319 			 * write().  wtfs_breakup() will call exit if it
   3320 			 * fails, so we don't worry about errors here.
   3321 			 */
   3322 			flush_writes();
   3323 			wtfs_breakup(transp->bno, transp->size, transp->buffer);
   3324 			freetrans(transp);
   3325 		} else {
   3326 			/*
   3327 			 * Keep track of our pending writes.
   3328 			 */
   3329 			results.outstanding++;
   3330 			if (results.outstanding > results.maxpend)
   3331 				results.maxpend = results.outstanding;
   3332 		}
   3333 	}
   3334 
   3335 	unblock_sigint(&old_mask);
   3336 }
   3337 
   3338 
   3339 /*
   3340  * write a block to the file system, but break it up into sbsize
   3341  * chunks to avoid forcing a large amount of memory to be locked down.
   3342  * Only used as a fallback when an aio write has failed.
   3343  */
   3344 static void
   3345 wtfs_breakup(diskaddr_t bno, int size, char *bf)
   3346 {
   3347 	int n, saverr;
   3348 	int wsize;
   3349 	int block_incr = sbsize / sectorsize;
   3350 
   3351 	if (size < sbsize)
   3352 		wsize = size;
   3353 	else
   3354 		wsize = sbsize;
   3355 
   3356 	n = 0;
   3357 	while (size) {
   3358 		/*
   3359 		 * Note: the llseek() can succeed, even if the offset is
   3360 		 * out of range.  It's not until the file i/o operation
   3361 		 * (the write()) that one knows for sure if the raw device
   3362 		 * can handle the offset.
   3363 		 */
   3364 		if (llseek(fso, (offset_t)bno * sectorsize, 0) < 0) {
   3365 			saverr = errno;
   3366 			(void) fprintf(stderr,
   3367 			    gettext("seek error on sector %lld: %s\n"),
   3368 			    bno, strerror(saverr));
   3369 			lockexit(32);
   3370 		}
   3371 
   3372 		n = write(fso, bf, wsize);
   3373 		if (n == -1) {
   3374 			saverr = errno;
   3375 			(void) fprintf(stderr,
   3376 			    gettext("write error on sector %lld: %s\n"),
   3377 			    bno, strerror(saverr));
   3378 			lockexit(32);
   3379 		}
   3380 		if (n != wsize) {
   3381 			saverr = errno;
   3382 			(void) fprintf(stderr, gettext(
   3383 			    "short write (%d of %d bytes) on sector %lld\n"),
   3384 			    n, size, bno);
   3385 			lockexit(32);
   3386 		}
   3387 
   3388 		bno += block_incr;
   3389 		bf += wsize;
   3390 		size -= wsize;
   3391 		if (size < wsize)
   3392 			wsize = size;
   3393 	}
   3394 }
   3395 
   3396 
   3397 /*
   3398  * check if a block is available
   3399  */
   3400 static int
   3401 isblock(struct fs *fs, unsigned char *cp, int h)
   3402 {
   3403 	unsigned char mask;
   3404 
   3405 	switch (fs->fs_frag) {
   3406 	case 8:
   3407 		return (cp[h] == 0xff);
   3408 	case 4:
   3409 		mask = 0x0f << ((h & 0x1) << 2);
   3410 		return ((cp[h >> 1] & mask) == mask);
   3411 	case 2:
   3412 		mask = 0x03 << ((h & 0x3) << 1);
   3413 		return ((cp[h >> 2] & mask) == mask);
   3414 	case 1:
   3415 		mask = 0x01 << (h & 0x7);
   3416 		return ((cp[h >> 3] & mask) == mask);
   3417 	default:
   3418 		(void) fprintf(stderr, "isblock bad fs_frag %d\n", fs->fs_frag);
   3419 		return (0);
   3420 	}
   3421 }
   3422 
   3423 /*
   3424  * take a block out of the map
   3425  */
   3426 static void
   3427 clrblock(struct fs *fs, unsigned char *cp, int h)
   3428 {
   3429 	switch ((fs)->fs_frag) {
   3430 	case 8:
   3431 		cp[h] = 0;
   3432 		return;
   3433 	case 4:
   3434 		cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2));
   3435 		return;
   3436 	case 2:
   3437 		cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1));
   3438 		return;
   3439 	case 1:
   3440 		cp[h >> 3] &= ~(0x01 << (h & 0x7));
   3441 		return;
   3442 	default:
   3443 		(void) fprintf(stderr,
   3444 		    gettext("clrblock: bad fs_frag value %d\n"), fs->fs_frag);
   3445 		return;
   3446 	}
   3447 }
   3448 
   3449 /*
   3450  * put a block into the map
   3451  */
   3452 static void
   3453 setblock(struct fs *fs, unsigned char *cp, int h)
   3454 {
   3455 	switch (fs->fs_frag) {
   3456 	case 8:
   3457 		cp[h] = 0xff;
   3458 		return;
   3459 	case 4:
   3460 		cp[h >> 1] |= (0x0f << ((h & 0x1) << 2));
   3461 		return;
   3462 	case 2:
   3463 		cp[h >> 2] |= (0x03 << ((h & 0x3) << 1));
   3464 		return;
   3465 	case 1:
   3466 		cp[h >> 3] |= (0x01 << (h & 0x7));
   3467 		return;
   3468 	default:
   3469 		(void) fprintf(stderr,
   3470 		    gettext("setblock: bad fs_frag value %d\n"), fs->fs_frag);
   3471 		return;
   3472 	}
   3473 }
   3474 
   3475 static void
   3476 usage()
   3477 {
   3478 	(void) fprintf(stderr,
   3479 	    gettext("ufs usage: mkfs [-F FSType] [-V] [-m] [-o options] "
   3480 	    "special "				/* param 0 */
   3481 	    "size(sectors) \\ \n"));		/* param 1 */
   3482 	(void) fprintf(stderr,
   3483 	    "[nsect "				/* param 2 */
   3484 	    "ntrack "				/* param 3 */
   3485 	    "bsize "				/* param 4 */
   3486 	    "fragsize "				/* param 5 */
   3487 	    "cpg "				/* param 6 */
   3488 	    "free "				/* param 7 */
   3489 	    "rps "				/* param 8 */
   3490 	    "nbpi "				/* param 9 */
   3491 	    "opt "				/* param 10 */
   3492 	    "apc "				/* param 11 */
   3493 	    "gap "				/* param 12 */
   3494 	    "nrpos "				/* param 13 */
   3495 	    "maxcontig "			/* param 14 */
   3496 	    "mtb]\n");				/* param 15 */
   3497 	(void) fprintf(stderr,
   3498 	    gettext(" -m : dump fs cmd line used to make this partition\n"
   3499 	    " -V :print this command line and return\n"
   3500 	    " -o :ufs options: :nsect=%d,ntrack=%d,bsize=%d,fragsize=%d\n"
   3501 	    " -o :ufs options: :cgsize=%d,free=%d,rps=%d,nbpi=%d,opt=%c\n"
   3502 	    " -o :ufs options: :apc=%d,gap=%d,nrpos=%d,maxcontig=%d\n"
   3503 	    " -o :ufs options: :mtb=%c,calcsb,calcbinsb\n"
   3504 "NOTE that all -o suboptions: must be separated only by commas so as to\n"
   3505 "be parsed as a single argument\n"),
   3506 	    nsect, ntrack, bsize, fragsize, cpg, sblock.fs_minfree, rps,
   3507 	    nbpi, opt, apc, (rotdelay == -1) ? 0 : rotdelay,
   3508 	    sblock.fs_nrpos, maxcontig, mtb);
   3509 	lockexit(32);
   3510 }
   3511 
   3512 /*ARGSUSED*/
   3513 static void
   3514 dump_fscmd(char *fsys, int fsi)
   3515 {
   3516 	int64_t used, bpcg, inospercg;
   3517 	int64_t nbpi;
   3518 	uint64_t nbytes64;
   3519 
   3520 	bzero((char *)&sblock, sizeof (sblock));
   3521 	rdfs((diskaddr_t)SBLOCK, SBSIZE, (char *)&sblock);
   3522 
   3523 	/*
   3524 	 * ensure a valid file system and if not, exit with error or else
   3525 	 * we will end up computing block numbers etc and dividing by zero
   3526 	 * which will cause floating point errors in this routine.
   3527 	 */
   3528 
   3529 	if ((sblock.fs_magic != FS_MAGIC) &&
   3530 	    (sblock.fs_magic != MTB_UFS_MAGIC)) {
   3531 		(void) fprintf(stderr, gettext(
   3532 		    "[not currently a valid file system - bad superblock]\n"));
   3533 		lockexit(32);
   3534 	}
   3535 
   3536 	if (sblock.fs_magic == FS_MAGIC &&
   3537 	    (sblock.fs_version != UFS_EFISTYLE4NONEFI_VERSION_2 &&
   3538 	    sblock.fs_version != UFS_VERSION_MIN)) {
   3539 		(void) fprintf(stderr, gettext(
   3540 		    "Unknown version of UFS format: %d\n"), sblock.fs_version);
   3541 		lockexit(32);
   3542 	}
   3543 
   3544 	if (sblock.fs_magic == MTB_UFS_MAGIC &&
   3545 	    (sblock.fs_version > MTB_UFS_VERSION_1 ||
   3546 	    sblock.fs_version < MTB_UFS_VERSION_MIN)) {
   3547 		(void) fprintf(stderr, gettext(
   3548 		    "Unknown version of UFS format: %d\n"), sblock.fs_version);
   3549 		lockexit(32);
   3550 	}
   3551 
   3552 	/*
   3553 	 * Compute a reasonable nbpi value.
   3554 	 * The algorithm for "used" is copied from code
   3555 	 * in main() verbatim.
   3556 	 * The nbpi equation is taken from main where the
   3557 	 * fs_ipg value is set for the last time.  The INOPB(...) - 1
   3558 	 * is used to account for the roundup.
   3559 	 * The problem is that a range of nbpi values map to
   3560 	 * the same file system layout.  So it is not possible
   3561 	 * to calculate the exact value specified when the file
   3562 	 * system was created.  So instead we determine the top
   3563 	 * end of the range of values.
   3564 	 */
   3565 	bpcg = sblock.fs_spc * sectorsize;
   3566 	inospercg = (int64_t)roundup(bpcg / sizeof (struct dinode),
   3567 	    INOPB(&sblock));
   3568 	if (inospercg > MAXIpG(&sblock))
   3569 		inospercg = MAXIpG(&sblock);
   3570 	used = (int64_t)
   3571 	    (sblock.fs_iblkno + inospercg / INOPF(&sblock)) * NSPF(&sblock);
   3572 	used *= sectorsize;
   3573 	nbytes64 = (uint64_t)sblock.fs_cpg * bpcg - used;
   3574 
   3575 	/*
   3576 	 * The top end of the range of values for nbpi may not be
   3577 	 * a valid command line value for mkfs. Report the bottom
   3578 	 * end instead.
   3579 	 */
   3580 	nbpi = (int64_t)(nbytes64 / (sblock.fs_ipg));
   3581 
   3582 	(void) fprintf(stdout, gettext("mkfs -F ufs -o "), fsys);
   3583 	(void) fprintf(stdout, "nsect=%d,ntrack=%d,",
   3584 	    sblock.fs_nsect, sblock.fs_ntrak);
   3585 	(void) fprintf(stdout, "bsize=%d,fragsize=%d,cgsize=%d,free=%d,",
   3586 	    sblock.fs_bsize, sblock.fs_fsize, sblock.fs_cpg, sblock.fs_minfree);
   3587 	(void) fprintf(stdout, "rps=%d,nbpi=%lld,opt=%c,apc=%d,gap=%d,",
   3588 	    sblock.fs_rps, nbpi, (sblock.fs_optim == FS_OPTSPACE) ? 's' : 't',
   3589 	    (sblock.fs_ntrak * sblock.fs_nsect) - sblock.fs_spc,
   3590 	    sblock.fs_rotdelay);
   3591 	(void) fprintf(stdout, "nrpos=%d,maxcontig=%d,mtb=%c ",
   3592 	    sblock.fs_nrpos, sblock.fs_maxcontig,
   3593 	    ((sblock.fs_magic == MTB_UFS_MAGIC) ? 'y' : 'n'));
   3594 	(void) fprintf(stdout, "%s %lld\n", fsys,
   3595 	    fsbtodb(&sblock, sblock.fs_size));
   3596 
   3597 	bzero((char *)&sblock, sizeof (sblock));
   3598 }
   3599 
   3600 /* number ************************************************************* */
   3601 /*									*/
   3602 /* Convert a numeric string arg to binary				*/
   3603 /*									*/
   3604 /* Args:	d_value - default value, if have parse error		*/
   3605 /*		param - the name of the argument, for error messages	*/
   3606 /*		flags - parser state and what's allowed in the arg	*/
   3607 /* Global arg:  string - pointer to command arg				*/
   3608 /*									*/
   3609 /* Valid forms: 123 | 123k | 123*123 | 123x123				*/
   3610 /*									*/
   3611 /* Return:	converted number					*/
   3612 /*									*/
   3613 /* ******************************************************************** */
   3614 
   3615 static uint64_t
   3616 number(uint64_t d_value, char *param, int flags)
   3617 {
   3618 	char *cs;
   3619 	uint64_t n, t;
   3620 	uint64_t cut = BIG / 10;    /* limit to avoid overflow */
   3621 	int minus = 0;
   3622 
   3623 	cs = string;
   3624 	if (*cs == '-') {
   3625 		minus = 1;
   3626 		cs += 1;
   3627 	}
   3628 	if ((*cs < '0') || (*cs > '9')) {
   3629 		goto bail_out;
   3630 	}
   3631 	n = 0;
   3632 	while ((*cs >= '0') && (*cs <= '9') && (n <= cut)) {
   3633 		n = n*10 + *cs++ - '0';
   3634 	}
   3635 	if (minus)
   3636 		n = -n;
   3637 	for (;;) {
   3638 		switch (*cs++) {
   3639 		case 'k':
   3640 			if (flags & ALLOW_END_ONLY)
   3641 				goto bail_out;
   3642 			if (n > (BIG / 1024))
   3643 				goto overflow;
   3644 			n *= 1024;
   3645 			continue;
   3646 
   3647 		case '*':
   3648 		case 'x':
   3649 			if (flags & ALLOW_END_ONLY)
   3650 				goto bail_out;
   3651 			string = cs;
   3652 			t = number(d_value, param, flags);
   3653 			if (n > (BIG / t))
   3654 				goto overflow;
   3655 			n *= t;
   3656 			cs = string + 1; /* adjust for -- below */
   3657 
   3658 			/* recursion has read rest of expression */
   3659 			/* FALLTHROUGH */
   3660 
   3661 		case ',':
   3662 		case '\0':
   3663 			cs--;
   3664 			string = cs;
   3665 			return (n);
   3666 
   3667 		case '%':
   3668 			if (flags & ALLOW_END_ONLY)
   3669 				goto bail_out;
   3670 			if (flags & ALLOW_PERCENT) {
   3671 				flags &= ~ALLOW_PERCENT;
   3672 				flags |= ALLOW_END_ONLY;
   3673 				continue;
   3674 			}
   3675 			goto bail_out;
   3676 
   3677 		case 'm':
   3678 			if (flags & ALLOW_END_ONLY)
   3679 				goto bail_out;
   3680 			if (flags & ALLOW_MS1) {
   3681 				flags &= ~ALLOW_MS1;
   3682 				flags |= ALLOW_MS2;
   3683 				continue;
   3684 			}
   3685 			goto bail_out;
   3686 
   3687 		case 's':
   3688 			if (flags & ALLOW_END_ONLY)
   3689 				goto bail_out;
   3690 			if (flags & ALLOW_MS2) {
   3691 				flags &= ~ALLOW_MS2;
   3692 				flags |= ALLOW_END_ONLY;
   3693 				continue;
   3694 			}
   3695 			goto bail_out;
   3696 
   3697 		case '0': case '1': case '2': case '3': case '4':
   3698 		case '5': case '6': case '7': case '8': case '9':
   3699 overflow:
   3700 			(void) fprintf(stderr,
   3701 			    gettext("mkfs: value for %s overflowed\n"),
   3702 			    param);
   3703 			while ((*cs != '\0') && (*cs != ','))
   3704 				cs++;
   3705 			string = cs;
   3706 			return (BIG);
   3707 
   3708 		default:
   3709 bail_out:
   3710 			(void) fprintf(stderr, gettext(
   3711 			    "mkfs: bad numeric arg for %s: \"%s\"\n"),
   3712 			    param, string);
   3713 			while ((*cs != '\0') && (*cs != ','))
   3714 				cs++;
   3715 			string = cs;
   3716 			if (d_value != NO_DEFAULT) {
   3717 				(void) fprintf(stderr,
   3718 				    gettext("mkfs: %s reset to default %lld\n"),
   3719 				    param, d_value);
   3720 				return (d_value);
   3721 			}
   3722 			lockexit(2);
   3723 
   3724 		}
   3725 	} /* never gets here */
   3726 }
   3727 
   3728 /* match ************************************************************** */
   3729 /*									*/
   3730 /* Compare two text strings for equality				*/
   3731 /*									*/
   3732 /* Arg:	 s - pointer to string to match with a command arg		*/
   3733 /* Global arg:  string - pointer to command arg				*/
   3734 /*									*/
   3735 /* Return:	1 if match, 0 if no match				*/
   3736 /*		If match, also reset `string' to point to the text	*/
   3737 /*		that follows the matching text.				*/
   3738 /*									*/
   3739 /* ******************************************************************** */
   3740 
   3741 static int
   3742 match(char *s)
   3743 {
   3744 	char *cs;
   3745 
   3746 	cs = string;
   3747 	while (*cs++ == *s) {
   3748 		if (*s++ == '\0') {
   3749 			goto true;
   3750 		}
   3751 	}
   3752 	if (*s != '\0') {
   3753 		return (0);
   3754 	}
   3755 
   3756 true:
   3757 	cs--;
   3758 	string = cs;
   3759 	return (1);
   3760 }
   3761 
   3762 /*
   3763  * GROWFS ROUTINES
   3764  */
   3765 
   3766 /* ARGSUSED */
   3767 void
   3768 lockexit(int exitstatus)
   3769 {
   3770 	if (Pflag) {
   3771 		/* the probe mode neither changes nor locks the filesystem */
   3772 		exit(exitstatus);
   3773 	}
   3774 
   3775 	/*
   3776 	 * flush the dirty cylinder group
   3777 	 */
   3778 	if (inlockexit == 0) {
   3779 		inlockexit = 1;
   3780 		flcg();
   3781 	}
   3782 
   3783 	if (aio_inited) {
   3784 		flush_writes();
   3785 	}
   3786 
   3787 	/*
   3788 	 * make sure the file system is unlocked before exiting
   3789 	 */
   3790 	if ((inlockexit == 1) && (!isbad)) {
   3791 		inlockexit = 2;
   3792 		ulockfs();
   3793 		/*
   3794 		 * if logging was enabled, then re-enable it
   3795 		 */
   3796 		if (waslog) {
   3797 			if (rl_log_control(fsys, _FIOLOGENABLE) != RL_SUCCESS) {
   3798 				(void) fprintf(stderr, gettext(
   3799 				    "failed to re-enable logging\n"));
   3800 			}
   3801 		}
   3802 	} else if (grow) {
   3803 		if (isbad) {
   3804 			(void) fprintf(stderr, gettext(
   3805 			    "Filesystem is currently inconsistent.  It "
   3806 			    "must be repaired with fsck(1M)\nbefore being "
   3807 			    "used.  Use the following command to "
   3808 			    "do this:\n\n\tfsck %s\n\n"), fsys);
   3809 
   3810 			if (ismounted) {
   3811 				(void) fprintf(stderr, gettext(
   3812 				    "You will be told that the filesystem "
   3813 				    "is already mounted, and asked if you\n"
   3814 				    "wish to continue.  Answer `yes' to "
   3815 				    "this question.\n\n"));
   3816 			}
   3817 
   3818 			(void) fprintf(stderr, gettext(
   3819 			    "One problem should be reported, that the summary "
   3820 			    "information is bad.\nYou will then be asked if it "
   3821 			    "should be salvaged.  Answer `yes' to\nthis "
   3822 			    "question.\n\n"));
   3823 		}
   3824 
   3825 		if (ismounted) {
   3826 			/*
   3827 			 * In theory, there's no way to get here without
   3828 			 * isbad also being set, but be robust in the
   3829 			 * face of future code changes.
   3830 			 */
   3831 			(void) fprintf(stderr, gettext(
   3832 			    "The filesystem is currently mounted "
   3833 			    "read-only and write-locked.  "));
   3834 			if (isbad) {
   3835 				(void) fprintf(stderr, gettext(
   3836 				    "After\nrunning fsck, unlock the "
   3837 				    "filesystem and "));
   3838 			} else {
   3839 				(void) fprintf(stderr, gettext(
   3840 				    "Unlock the filesystem\nand "));
   3841 			}
   3842 
   3843 			(void) fprintf(stderr, gettext(
   3844 			    "re-enable writing with\nthe following "
   3845 			    "command:\n\n\tlockfs -u %s\n\n"), directory);
   3846 		}
   3847 	}
   3848 
   3849 	exit(exitstatus);
   3850 }
   3851 
   3852 void
   3853 randomgeneration()
   3854 {
   3855 	int		 i;
   3856 	struct dinode	*dp;
   3857 
   3858 	/*
   3859 	 * always perform fsirand(1) function... newfs will notice that
   3860 	 * the inodes have been randomized and will not call fsirand itself
   3861 	 */
   3862 	for (i = 0, dp = zino; i < sblock.fs_inopb; ++i, ++dp)
   3863 		IRANDOMIZE(&dp->di_ic);
   3864 }
   3865 
   3866 /*
   3867  * Check the size of the summary information.
   3868  * Fields in sblock are not changed in this function.
   3869  *
   3870  * For an 8K filesystem block, the maximum number of cylinder groups is 16384.
   3871  *     MAXCSBUFS {32}  *   8K  {FS block size}
   3872  *                         divided by (sizeof csum) {16}
   3873  *
   3874  * Note that MAXCSBUFS is not used in the kernel; as of Solaris 2.6 build 32,
   3875  * this is the only place where it's referenced.
   3876  */
   3877 void
   3878 checksummarysize()
   3879 {
   3880 	diskaddr_t	dmax;
   3881 	diskaddr_t	dmin;
   3882 	int64_t	cg0frags;
   3883 	int64_t	cg0blocks;
   3884 	int64_t	maxncg;
   3885 	int64_t	maxfrags;
   3886 	uint64_t	fs_size;
   3887 	uint64_t maxfs_blocks; /* filesystem blocks for max filesystem size */
   3888 
   3889 	/*
   3890 	 * compute the maximum summary info size
   3891 	 */
   3892 	dmin = cgdmin(&sblock, 0);
   3893 	dmax = cgbase(&sblock, 0) + sblock.fs_fpg;
   3894 	fs_size = (grow) ? grow_fs_size : sblock.fs_size;
   3895 	if (dmax > fs_size)
   3896 		dmax = fs_size;
   3897 	cg0frags  = dmax - dmin;
   3898 	cg0blocks = cg0frags / sblock.fs_frag;
   3899 	cg0frags = cg0blocks * sblock.fs_frag;
   3900 	maxncg   = (longlong_t)cg0blocks *
   3901 	    (longlong_t)(sblock.fs_bsize / sizeof (struct csum));
   3902 
   3903 	maxfs_blocks = FS_MAX;
   3904 
   3905 	if (maxncg > ((longlong_t)maxfs_blocks / (longlong_t)sblock.fs_fpg) + 1)
   3906 		maxncg = ((longlong_t)maxfs_blocks /
   3907 		    (longlong_t)sblock.fs_fpg) + 1;
   3908 
   3909 	maxfrags = maxncg * (longlong_t)sblock.fs_fpg;
   3910 
   3911 	if (maxfrags > maxfs_blocks)
   3912 		maxfrags = maxfs_blocks;
   3913 
   3914 
   3915 	/*
   3916 	 * remember for later processing in extendsummaryinfo()
   3917 	 */
   3918 	if (test)
   3919 		grow_sifrag = dmin + (cg0blocks * sblock.fs_frag);
   3920 	if (testfrags == 0)
   3921 		testfrags = cg0frags;
   3922 	if (testforce)
   3923 		if (testfrags > cg0frags) {
   3924 			(void) fprintf(stderr,
   3925 			    gettext("Too many test frags (%lld); "
   3926 			    "try %lld\n"), testfrags, cg0frags);
   3927 			lockexit(32);
   3928 		}
   3929 
   3930 	/*
   3931 	 * if summary info is too large (too many cg's) tell the user and exit
   3932 	 */
   3933 	if ((longlong_t)sblock.fs_size > maxfrags) {
   3934 		(void) fprintf(stderr, gettext(
   3935 		    "Too many cylinder groups with %llu sectors;\n    try "
   3936 		    "increasing cgsize, or decreasing fssize to %llu\n"),
   3937 		    fsbtodb(&sblock, (uint64_t)sblock.fs_size),
   3938 		    fsbtodb(&sblock, (uint64_t)maxfrags));
   3939 		lockexit(32);
   3940 	}
   3941 }
   3942 
   3943 /*
   3944  * checksblock() has two uses:
   3945  *	- One is to sanity test the superblock and is used when newfs(1M)
   3946  *	  is invoked with the "-N" option. If any discrepancy was found,
   3947  *	  just return whatever error was found and do not exit.
   3948  *	- the other use of it is in places where you expect the superblock
   3949  *	  to be sane, and if it isn't, then we exit.
   3950  * Which of the above two actions to take is indicated with the second argument.
   3951  */
   3952 
   3953 int
   3954 checksblock(struct fs sb, int proceed)
   3955 {
   3956 	int err = 0;
   3957 	char *errmsg;
   3958 
   3959 	if ((sb.fs_magic != FS_MAGIC) && (sb.fs_magic != MTB_UFS_MAGIC)) {
   3960 		err = 1;
   3961 		errmsg = gettext("Bad superblock; magic number wrong\n");
   3962 	} else if ((sb.fs_magic == FS_MAGIC &&
   3963 	    (sb.fs_version != UFS_EFISTYLE4NONEFI_VERSION_2 &&
   3964 	    sb.fs_version != UFS_VERSION_MIN)) ||
   3965 	    (sb.fs_magic == MTB_UFS_MAGIC &&
   3966 	    (sb.fs_version > MTB_UFS_VERSION_1 ||
   3967 	    sb.fs_version < MTB_UFS_VERSION_MIN))) {
   3968 		err = 2;
   3969 		errmsg = gettext("Unrecognized version of UFS\n");
   3970 	} else if (sb.fs_ncg < 1) {
   3971 		err = 3;
   3972 		errmsg = gettext("Bad superblock; ncg out of range\n");
   3973 	} else if (sb.fs_cpg < 1) {
   3974 		err = 4;
   3975 		errmsg = gettext("Bad superblock; cpg out of range\n");
   3976 	} else if (sb.fs_ncg * sb.fs_cpg < sb.fs_ncyl ||
   3977 	    (sb.fs_ncg - 1) * sb.fs_cpg >= sb.fs_ncyl) {
   3978 		err = 5;
   3979 		errmsg = gettext("Bad superblock; ncyl out of range\n");
   3980 	} else if (sb.fs_sbsize <= 0 || sb.fs_sbsize > sb.fs_bsize) {
   3981 		err = 6;
   3982 		errmsg = gettext("Bad superblock; superblock size out of "
   3983 		    "range\n");
   3984 	}
   3985 
   3986 	if (proceed) {
   3987 		if (err) dprintf(("%s", errmsg));
   3988 		return (err);
   3989 	}
   3990 
   3991 	if (err) {
   3992 		fprintf(stderr, "%s", errmsg);
   3993 		lockexit(32);
   3994 	}
   3995 	return (32);
   3996 }
   3997 
   3998 /*
   3999  * Roll the embedded log, if any, and set up the global variables
   4000  * islog, islogok and isufslog.
   4001  */
   4002 static void
   4003 logsetup(char *devstr)
   4004 {
   4005 	void		*buf, *ud_buf;
   4006 	extent_block_t	*ebp;
   4007 	ml_unit_t	*ul;
   4008 	ml_odunit_t	*ud;
   4009 
   4010 	/*
   4011 	 * Does the superblock indicate that we are supposed to have a log ?
   4012 	 */
   4013 	if (sblock.fs_logbno == 0) {
   4014 		/*
   4015 		 * No log present, nothing to do.
   4016 		 */
   4017 		islogok = 0;
   4018 		islog = 0;
   4019 		isufslog = 0;
   4020 		return;
   4021 	} else {
   4022 		/*
   4023 		 * There's a log in a yet unknown state, attempt to roll it.
   4024 		 */
   4025 		islog = 1;
   4026 		islogok = 0;
   4027 		isufslog = 0;
   4028 
   4029 		/*
   4030 		 * We failed to roll the log, bail out.
   4031 		 */
   4032 		if (rl_roll_log(devstr) != RL_SUCCESS)
   4033 			return;
   4034 
   4035 		isufslog = 1;
   4036 
   4037 		/* log is not okay; check the fs */
   4038 		if ((FSOKAY != (sblock.fs_state + sblock.fs_time)) ||
   4039 		    (sblock.fs_clean != FSLOG))
   4040 			return;
   4041 
   4042 		/* get the log allocation block */
   4043 		buf = (void *)malloc(DEV_BSIZE);
   4044 		if (buf == (void *) NULL)
   4045 			return;
   4046 
   4047 		ud_buf = (void *)malloc(DEV_BSIZE);
   4048 		if (ud_buf == (void *) NULL) {
   4049 			free(buf);
   4050 			return;
   4051 		}
   4052 
   4053 		rdfs((diskaddr_t)logbtodb(&sblock, sblock.fs_logbno),
   4054 		    DEV_BSIZE, buf);
   4055 		ebp = (extent_block_t *)buf;
   4056 
   4057 		/* log allocation block is not okay; check the fs */
   4058 		if (ebp->type != LUFS_EXTENTS) {
   4059 			free(buf);
   4060 			free(ud_buf);
   4061 			return;
   4062 		}
   4063 
   4064 		/* get the log state block(s) */
   4065 		rdfs((diskaddr_t)logbtodb(&sblock, ebp->extents[0].pbno),
   4066 		    DEV_BSIZE, ud_buf);
   4067 		ud = (ml_odunit_t *)ud_buf;
   4068 		ul = (ml_unit_t *)malloc(sizeof (*ul));
   4069 		ul->un_ondisk = *ud;
   4070 
   4071 		/* log state is okay */
   4072 		if ((ul->un_chksum == ul->un_head_ident + ul->un_tail_ident) &&
   4073 		    (ul->un_version == LUFS_VERSION_LATEST) &&
   4074 		    (ul->un_badlog == 0))
   4075 			islogok = 1;
   4076 		free(ud_buf);
   4077 		free(buf);
   4078 		free(ul);
   4079 	}
   4080 }
   4081 
   4082 void
   4083 growinit(char *devstr)
   4084 {
   4085 	int	i;
   4086 	char	buf[DEV_BSIZE];
   4087 
   4088 	/*
   4089 	 * Read and verify the superblock
   4090 	 */
   4091 	rdfs((diskaddr_t)(SBOFF / sectorsize), (int)sbsize, (char *)&sblock);
   4092 	(void) checksblock(sblock, 0);
   4093 	if (sblock.fs_postblformat != FS_DYNAMICPOSTBLFMT) {
   4094 		(void) fprintf(stderr,
   4095 		    gettext("old file system format; can't growfs\n"));
   4096 		lockexit(32);
   4097 	}
   4098 
   4099 	/*
   4100 	 * can't shrink a file system
   4101 	 */
   4102 	grow_fssize = fsbtodb(&sblock, (uint64_t)sblock.fs_size);
   4103 	if (fssize_db < grow_fssize) {
   4104 		(void) fprintf(stderr,
   4105 		    gettext("%lld sectors < current size of %lld sectors\n"),
   4106 		    fssize_db, grow_fssize);
   4107 		lockexit(32);
   4108 	}
   4109 
   4110 	/*
   4111 	 * can't grow a system to over a terabyte unless it was set up
   4112 	 * as an MTB UFS file system.
   4113 	 */
   4114 	if (mtb == 'y' && sblock.fs_magic != MTB_UFS_MAGIC) {
   4115 		if (fssize_db >= SECTORS_PER_TERABYTE) {
   4116 			(void) fprintf(stderr, gettext(
   4117 "File system was not set up with the multi-terabyte format.\n"));
   4118 			(void) fprintf(stderr, gettext(
   4119 "Its size cannot be increased to a terabyte or more.\n"));
   4120 		} else {
   4121 			(void) fprintf(stderr, gettext(
   4122 "Cannot convert file system to multi-terabyte format.\n"));
   4123 		}
   4124 		lockexit(32);
   4125 	}
   4126 
   4127 	logsetup(devstr);
   4128 
   4129 	/*
   4130 	 * can't growfs when logging device has errors
   4131 	 */
   4132 	if ((islog && !islogok) ||
   4133 	    ((FSOKAY == (sblock.fs_state + sblock.fs_time)) &&
   4134 	    (sblock.fs_clean == FSLOG && !islog))) {
   4135 		(void) fprintf(stderr,
   4136 		    gettext("logging device has errors; can't growfs\n"));
   4137 		lockexit(32);
   4138 	}
   4139 
   4140 	/*
   4141 	 * disable ufs logging for growing
   4142 	 */
   4143 	if (isufslog) {
   4144 		if (rl_log_control(devstr, _FIOLOGDISABLE) != RL_SUCCESS) {
   4145 			(void) fprintf(stderr, gettext(
   4146 			    "failed to disable logging\n"));
   4147 			lockexit(32);
   4148 		}
   4149 		islog = 0;
   4150 		waslog = 1;
   4151 	}
   4152 
   4153 	/*
   4154 	 * if mounted write lock the file system to be grown
   4155 	 */
   4156 	if (ismounted)
   4157 		wlockfs();
   4158 
   4159 	/*
   4160 	 * refresh dynamic superblock state - disabling logging will have
   4161 	 * changed the amount of free space available in the file system
   4162 	 */
   4163 	rdfs((diskaddr_t)(SBOFF / sectorsize), sbsize, (char *)&sblock);
   4164 
   4165 	/*
   4166 	 * make sure device is big enough
   4167 	 */
   4168 	rdfs((diskaddr_t)fssize_db - 1, DEV_BSIZE, buf);
   4169 	wtfs((diskaddr_t)fssize_db - 1, DEV_BSIZE, buf);
   4170 
   4171 	/*
   4172 	 * read current summary information
   4173 	 */
   4174 	grow_fscs = read_summaryinfo(&sblock);
   4175 
   4176 	/*
   4177 	 * save some current size related fields from the superblock
   4178 	 * These are used in extendsummaryinfo()
   4179 	 */
   4180 	grow_fs_size	= sblock.fs_size;
   4181 	grow_fs_ncg	= sblock.fs_ncg;
   4182 	grow_fs_csaddr	= (diskaddr_t)sblock.fs_csaddr;
   4183 	grow_fs_cssize	= sblock.fs_cssize;
   4184 
   4185 	/*
   4186 	 * save and reset the clean flag
   4187 	 */
   4188 	if (FSOKAY == (sblock.fs_state + sblock.fs_time))
   4189 		grow_fs_clean = sblock.fs_clean;
   4190 	else
   4191 		grow_fs_clean = FSBAD;
   4192 	sblock.fs_clean = FSBAD;
   4193 	sblock.fs_state = FSOKAY - sblock.fs_time;
   4194 	isbad = 1;
   4195 	wtfs((diskaddr_t)(SBOFF / sectorsize), sbsize, (char *)&sblock);
   4196 }
   4197 
   4198 void
   4199 checkdev(char *rdev, char *bdev)
   4200 {
   4201 	struct stat64	statarea;
   4202 
   4203 	if (stat64(bdev, &statarea) < 0) {
   4204 		(void) fprintf(stderr, gettext("can't check mount point; "));
   4205 		(void) fprintf(stderr, gettext("can't stat %s\n"), bdev);
   4206 		lockexit(32);
   4207 	}
   4208 	if ((statarea.st_mode & S_IFMT) != S_IFBLK) {
   4209 		(void) fprintf(stderr, gettext(
   4210 		    "can't check mount point; %s is not a block device\n"),
   4211 		    bdev);
   4212 		lockexit(32);
   4213 	}
   4214 	if (stat64(rdev, &statarea) < 0) {
   4215 		(void) fprintf(stderr, gettext("can't stat %s\n"), rdev);
   4216 		lockexit(32);
   4217 	}
   4218 	if ((statarea.st_mode & S_IFMT) != S_IFCHR) {
   4219 		(void) fprintf(stderr,
   4220 		    gettext("%s is not a character device\n"), rdev);
   4221 		lockexit(32);
   4222 	}
   4223 }
   4224 
   4225 void
   4226 checkmount(struct mnttab *mntp, char *bdevname)
   4227 {
   4228 	struct stat64	statdir;
   4229 	struct stat64	statdev;
   4230 
   4231 	if (strcmp(bdevname, mntp->mnt_special) == 0) {
   4232 		if (stat64(mntp->mnt_mountp, &statdir) == -1) {
   4233 			(void) fprintf(stderr, gettext("can't stat %s\n"),
   4234 			    mntp->mnt_mountp);
   4235 			lockexit(32);
   4236 		}
   4237 		if (stat64(mntp->mnt_special, &statdev) == -1) {
   4238 			(void) fprintf(stderr, gettext("can't stat %s\n"),
   4239 			    mntp->mnt_special);
   4240 			lockexit(32);
   4241 		}
   4242 		if (statdir.st_dev != statdev.st_rdev) {
   4243 			(void) fprintf(stderr, gettext(
   4244 			    "%s is not mounted on %s; mnttab(4) wrong\n"),
   4245 			    mntp->mnt_special, mntp->mnt_mountp);
   4246 			lockexit(32);
   4247 		}
   4248 		ismounted = 1;
   4249 		if (directory) {
   4250 			if (strcmp(mntp->mnt_mountp, directory) != 0) {
   4251 				(void) fprintf(stderr,
   4252 				    gettext("%s is mounted on %s, not %s\n"),
   4253 				    bdevname, mntp->mnt_mountp, directory);
   4254 				lockexit(32);
   4255 			}
   4256 		} else {
   4257 			if (grow)
   4258 				(void) fprintf(stderr, gettext(
   4259 				    "%s is mounted on %s; can't growfs\n"),
   4260 				    bdevname, mntp->mnt_mountp);
   4261 			else
   4262 				(void) fprintf(stderr,
   4263 				    gettext("%s is mounted, can't mkfs\n"),
   4264 				    bdevname);
   4265 			lockexit(32);
   4266 		}
   4267 	}
   4268 }
   4269 
   4270 struct dinode	*dibuf	= 0;
   4271 diskaddr_t	difrag	= 0;
   4272 
   4273 struct dinode *
   4274 gdinode(ino_t ino)
   4275 {
   4276 	/*
   4277 	 * read the block of inodes containing inode number ino
   4278 	 */
   4279 	if (dibuf == 0)
   4280 		dibuf = (struct dinode *)malloc((unsigned)sblock.fs_bsize);
   4281 	if (itod(&sblock, ino) != difrag) {
   4282 		difrag = itod(&sblock, ino);
   4283 		rdfs(fsbtodb(&sblock, (uint64_t)difrag), (int)sblock.fs_bsize,
   4284 		    (char *)dibuf);
   4285 	}
   4286 	return (dibuf + (ino % INOPB(&sblock)));
   4287 }
   4288 
   4289 /*
   4290  * structure that manages the frags we need for extended summary info
   4291  *	These frags can be:
   4292  *		free
   4293  *		data  block
   4294  *		alloc block
   4295  */
   4296 struct csfrag {
   4297 	struct csfrag	*next;		/* next entry */
   4298 	daddr32_t	 ofrag;		/* old frag */
   4299 	daddr32_t	 nfrag;		/* new frag */
   4300 	long		 cylno;		/* cylno of nfrag */
   4301 	long		 frags;		/* number of frags */
   4302 	long		 size;		/* size in bytes */
   4303 	ino_t		 ino;		/* inode number */
   4304 	long		 fixed;		/* Boolean - Already fixed? */
   4305 };
   4306 struct csfrag	*csfrag;		/* state unknown */
   4307 struct csfrag	*csfragino;		/* frags belonging to an inode */
   4308 struct csfrag	*csfragfree;		/* frags that are free */
   4309 
   4310 daddr32_t maxcsfrag	= 0;		/* maximum in range */
   4311 daddr32_t mincsfrag	= 0x7fffffff;	/* minimum in range */
   4312 
   4313 int
   4314 csfraginrange(daddr32_t frag)
   4315 {
   4316 	return ((frag >= mincsfrag) && (frag <= maxcsfrag));
   4317 }
   4318 
   4319 struct csfrag *
   4320 findcsfrag(daddr32_t frag, struct csfrag **cfap)
   4321 {
   4322 	struct csfrag	*cfp;
   4323 
   4324 	if (!csfraginrange(frag))
   4325 		return (NULL);
   4326 
   4327 	for (cfp = *cfap; cfp; cfp = cfp->next)
   4328 		if (cfp->ofrag == frag)
   4329 			return (cfp);
   4330 	return (NULL);
   4331 }
   4332 
   4333 void
   4334 checkindirect(ino_t ino, daddr32_t *fragsp, daddr32_t frag, int level)
   4335 {
   4336 	int			i;
   4337 	int			ne	= sblock.fs_bsize / sizeof (daddr32_t);
   4338 	daddr32_t			fsb[MAXBSIZE / sizeof (daddr32_t)];
   4339 
   4340 	if (frag == 0)
   4341 		return;
   4342 
   4343 	rdfs(fsbtodb(&sblock, frag), (int)sblock.fs_bsize,
   4344 	    (char *)fsb);
   4345 
   4346 	checkdirect(ino, fragsp, fsb, sblock.fs_bsize / sizeof (daddr32_t));
   4347 
   4348 	if (level)
   4349 		for (i = 0; i < ne && *fragsp; ++i)
   4350 			checkindirect(ino, fragsp, fsb[i], level-1);
   4351 }
   4352 
   4353 void
   4354 addcsfrag(ino_t ino, daddr32_t frag, struct csfrag **cfap)
   4355 {
   4356 	struct csfrag	*cfp, *curr, *prev;
   4357 
   4358 	/*
   4359 	 * establish a range for faster checking in csfraginrange()
   4360 	 */
   4361 	if (frag > maxcsfrag)
   4362 		maxcsfrag = frag;
   4363 	if (frag < mincsfrag)
   4364 		mincsfrag = frag;
   4365 
   4366 	/*
   4367 	 * if this frag belongs to an inode and is not the start of a block
   4368 	 *	then see if it is part of a frag range for this inode
   4369 	 */
   4370 	if (ino && (frag % sblock.fs_frag))
   4371 		for (cfp = *cfap; cfp; cfp = cfp->next) {
   4372 			if (ino != cfp->ino)
   4373 				continue;
   4374 			if (frag != cfp->ofrag + cfp->frags)
   4375 				continue;
   4376 			cfp->frags++;
   4377 			cfp->size += sblock.fs_fsize;
   4378 			return;
   4379 		}
   4380 	/*
   4381 	 * allocate a csfrag entry and insert it in an increasing order into the
   4382 	 * specified list
   4383 	 */
   4384 	cfp = (struct csfrag *)calloc(1, sizeof (struct csfrag));
   4385 	cfp->ino	= ino;
   4386 	cfp->ofrag	= frag;
   4387 	cfp->frags	= 1;
   4388 	cfp->size	= sblock.fs_fsize;
   4389 	for (prev = NULL, curr = *cfap; curr != NULL;
   4390 	    prev = curr, curr = curr->next) {
   4391 		if (frag < curr->ofrag) {
   4392 			cfp->next = curr;
   4393 			if (prev)
   4394 				prev->next = cfp;	/* middle element */
   4395 			else
   4396 				*cfap = cfp;		/* first element */
   4397 			break;
   4398 		}
   4399 		if (curr->next == NULL) {
   4400 			curr->next = cfp;		/* last element	*/
   4401 			break;
   4402 		}
   4403 	}
   4404 	if (*cfap == NULL)	/* will happen only once */
   4405 		*cfap = cfp;
   4406 }
   4407 
   4408 void
   4409 delcsfrag(daddr32_t frag, struct csfrag **cfap)
   4410 {
   4411 	struct csfrag	*cfp;
   4412 	struct csfrag	**cfpp;
   4413 
   4414 	/*
   4415 	 * free up entry whose beginning frag matches
   4416 	 */
   4417 	for (cfpp = cfap; *cfpp; cfpp = &(*cfpp)->next) {
   4418 		if (frag == (*cfpp)->ofrag) {
   4419 			cfp = *cfpp;
   4420 			*cfpp = (*cfpp)->next;
   4421 			free((char *)cfp);
   4422 			return;
   4423 		}
   4424 	}
   4425 }
   4426 
   4427 /*
   4428  * See whether any of the direct blocks in the array pointed by "db" and of
   4429  * length "ne" are within the range of frags needed to extend the cylinder
   4430  * summary. If so, remove those frags from the "as-yet-unclassified" list
   4431  * (csfrag) and add them to the "owned-by-inode" list (csfragino).
   4432  * For each such frag found, decrement the frag count pointed to by fragsp.
   4433  * "ino" is the inode that contains (either directly or indirectly) the frags
   4434  * being checked.
   4435  */
   4436 void
   4437 checkdirect(ino_t ino, daddr32_t *fragsp, daddr32_t *db, int ne)
   4438 {
   4439 	int	 i;
   4440 	int	 j;
   4441 	int	 found;
   4442 	diskaddr_t	 frag;
   4443 
   4444 	/*
   4445 	 * scan for allocation within the new summary info range
   4446 	 */
   4447 	for (i = 0; i < ne && *fragsp; ++i) {
   4448 		if ((frag = *db++) != 0) {
   4449 			found = 0;
   4450 			for (j = 0; j < sblock.fs_frag && *fragsp; ++j) {
   4451 				if (found || (found = csfraginrange(frag))) {
   4452 					addcsfrag(ino, frag, &csfragino);
   4453 					delcsfrag(frag, &csfrag);
   4454 				}
   4455 				++frag;
   4456 				--(*fragsp);
   4457 			}
   4458 		}
   4459 	}
   4460 }
   4461 
   4462 void
   4463 findcsfragino()
   4464 {
   4465 	int		 i;
   4466 	int		 j;
   4467 	daddr32_t		 frags;
   4468 	struct dinode	*dp;
   4469 
   4470 	/*
   4471 	 * scan all old inodes looking for allocations in the new
   4472 	 * summary info range.  Move the affected frag from the
   4473 	 * generic csfrag list onto the `owned-by-inode' list csfragino.
   4474 	 */
   4475 	for (i = UFSROOTINO; i < grow_fs_ncg*sblock.fs_ipg && csfrag; ++i) {
   4476 		dp = gdinode((ino_t)i);
   4477 		switch (dp->di_mode & IFMT) {
   4478 			case IFSHAD	:
   4479 			case IFLNK 	:
   4480 			case IFDIR 	:
   4481 			case IFREG 	: break;
   4482 			default		: continue;
   4483 		}
   4484 
   4485 		frags   = dbtofsb(&sblock, dp->di_blocks);
   4486 
   4487 		checkdirect((ino_t)i, &frags, &dp->di_db[0], NDADDR+NIADDR);
   4488 		for (j = 0; j < NIADDR && frags; ++j) {
   4489 			/* Negate the block if its an fallocate'd block */
   4490 			if (dp->di_ib[j] < 0 && dp->di_ib[j] != UFS_HOLE)
   4491 				checkindirect((ino_t)i, &frags,
   4492 				    -(dp->di_ib[j]), j);
   4493 			else
   4494 				checkindirect((ino_t)i, &frags,
   4495 				    dp->di_ib[j], j);
   4496 		}
   4497 	}
   4498 }
   4499 
   4500 void
   4501 fixindirect(daddr32_t frag, int level)
   4502 {
   4503 	int			 i;
   4504 	int			 ne	= sblock.fs_bsize / sizeof (daddr32_t);
   4505 	daddr32_t			fsb[MAXBSIZE / sizeof (daddr32_t)];
   4506 
   4507 	if (frag == 0)
   4508 		return;
   4509 
   4510 	rdfs(fsbtodb(&sblock, (uint64_t)frag), (int)sblock.fs_bsize,
   4511 	    (char *)fsb);
   4512 
   4513 	fixdirect((caddr_t)fsb, frag, fsb, ne);
   4514 
   4515 	if (level)
   4516 		for (i = 0; i < ne; ++i)
   4517 			fixindirect(fsb[i], level-1);
   4518 }
   4519 
   4520 void
   4521 fixdirect(caddr_t bp, daddr32_t frag, daddr32_t *db, int ne)
   4522 {
   4523 	int	 i;
   4524 	struct csfrag	*cfp;
   4525 
   4526 	for (i = 0; i < ne; ++i, ++db) {
   4527 		if (*db == 0)
   4528 			continue;
   4529 		if ((cfp = findcsfrag(*db, &csfragino)) == NULL)
   4530 			continue;
   4531 		*db = cfp->nfrag;
   4532 		cfp->fixed = 1;
   4533 		wtfs(fsbtodb(&sblock, (uint64_t)frag), (int)sblock.fs_bsize,
   4534 		    bp);
   4535 	}
   4536 }
   4537 
   4538 void
   4539 fixcsfragino()
   4540 {
   4541 	int		 i;
   4542 	struct dinode	*dp;
   4543 	struct csfrag	*cfp;
   4544 
   4545 	for (cfp = csfragino; cfp; cfp = cfp->next) {
   4546 		if (cfp->fixed)
   4547 			continue;
   4548 		dp = gdinode((ino_t)cfp->ino);
   4549 		fixdirect((caddr_t)dibuf, difrag, dp->di_db, NDADDR+NIADDR);
   4550 		for (i = 0; i < NIADDR; ++i)
   4551 			fixindirect(dp->di_ib[i], i);
   4552 	}
   4553 }
   4554 
   4555 /*
   4556  * Read the cylinders summary information specified by settings in the
   4557  * passed 'fs' structure into a new allocated array of csum structures.
   4558  * The caller is responsible for freeing the returned array.
   4559  * Return a pointer to an array of csum structures.
   4560  */
   4561 static struct csum *
   4562 read_summaryinfo(struct	fs *fsp)
   4563 {
   4564 	struct csum 	*csp;
   4565 	int		i;
   4566 
   4567 	if ((csp = malloc((size_t)fsp->fs_cssize)) == NULL) {
   4568 		(void) fprintf(stderr, gettext("cannot create csum list,"
   4569 		    " not enough memory\n"));
   4570 		exit(32);
   4571 	}
   4572 
   4573 	for (i = 0; i < fsp->fs_cssize; i += fsp->fs_bsize) {
   4574 		rdfs(fsbtodb(fsp,
   4575 		    (uint64_t)(fsp->fs_csaddr + numfrags(fsp, i))),
   4576 		    (int)(fsp->fs_cssize - i < fsp->fs_bsize ?
   4577 		    fsp->fs_cssize - i : fsp->fs_bsize), ((caddr_t)csp) + i);
   4578 	}
   4579 
   4580 	return (csp);
   4581 }
   4582 
   4583 /*
   4584  * Check the allocation of fragments that are to be made part of a csum block.
   4585  * A fragment is allocated if it is either in the csfragfree list or, it is
   4586  * in the csfragino list and has new frags associated with it.
   4587  * Return the number of allocated fragments.
   4588  */
   4589 int64_t
   4590 checkfragallocated(daddr32_t frag)
   4591 {
   4592 	struct 	csfrag	*cfp;
   4593 	/*
   4594 	 * Since the lists are sorted we can break the search if the asked
   4595 	 * frag is smaller then the one in the list.
   4596 	 */
   4597 	for (cfp = csfragfree; cfp != NULL && frag >= cfp->ofrag;
   4598 	    cfp = cfp->next) {
   4599 		if (frag == cfp->ofrag)
   4600 			return (1);
   4601 	}
   4602 	for (cfp = csfragino; cfp != NULL && frag >= cfp->ofrag;
   4603 	    cfp = cfp->next) {
   4604 		if (frag == cfp->ofrag && cfp->nfrag != 0)
   4605 			return (cfp->frags);
   4606 	}
   4607 
   4608 	return (0);
   4609 }
   4610 
   4611 /*
   4612  * Figure out how much the filesystem can be grown. The limiting factor is
   4613  * the available free space needed to extend the cg summary info block.
   4614  * The free space is determined in three steps:
   4615  * - Try to extend the cg summary block to the required size.
   4616  * - Find free blocks in last cg.
   4617  * - Find free space in the last already allocated fragment of the summary info
   4618  *   block, and use it for additional csum structures.
   4619  * Return the maximum size of the new filesystem or 0 if it can't be grown.
   4620  * Please note that this function leaves the global list pointers csfrag,
   4621  * csfragfree, and csfragino initialized, and the caller is responsible for
   4622  * freeing the lists.
   4623  */
   4624 diskaddr_t
   4625 probe_summaryinfo()
   4626 {
   4627 	/* fragments by which the csum block can be extended. */
   4628 	int64_t 	growth_csum_frags = 0;
   4629 	/* fragments by which the filesystem can be extended. */
   4630 	int64_t		growth_fs_frags = 0;
   4631 	int64_t		new_fs_cssize;	/* size of csum blk in the new FS */
   4632 	int64_t		new_fs_ncg;	/* number of cg in the new FS */
   4633 	int64_t 	spare_csum;
   4634 	daddr32_t	oldfrag_daddr;
   4635 	daddr32_t	newfrag_daddr;
   4636 	daddr32_t	daddr;
   4637 	int		i;
   4638 
   4639 	/*
   4640 	 * read and verify the superblock
   4641 	 */
   4642 	rdfs((diskaddr_t)(SBOFF / sectorsize), (int)sbsize, (char *)&sblock);
   4643 	(void) checksblock(sblock, 0);
   4644 
   4645 	/*
   4646 	 * check how much we can extend the cg summary info block
   4647 	 */
   4648 
   4649 	/*
   4650 	 * read current summary information
   4651 	 */
   4652 	fscs = read_summaryinfo(&sblock);
   4653 
   4654 	/*
   4655 	 * build list of frags needed for cg summary info block extension
   4656 	 */
   4657 	oldfrag_daddr = howmany(sblock.fs_cssize, sblock.fs_fsize) +
   4658 	    sblock.fs_csaddr;
   4659 	new_fs_ncg = howmany(dbtofsb(&sblock, fssize_db), sblock.fs_fpg);
   4660 	new_fs_cssize = fragroundup(&sblock, new_fs_ncg * sizeof (struct csum));
   4661 	newfrag_daddr = howmany(new_fs_cssize, sblock.fs_fsize) +
   4662 	    sblock.fs_csaddr;
   4663 	/*
   4664 	 * add all of the frags that are required to grow the cyl summary to the
   4665 	 * csfrag list, which is the generic/unknown list, since at this point
   4666 	 * we don't yet know the state of those frags.
   4667 	 */
   4668 	for (daddr = oldfrag_daddr; daddr < newfrag_daddr; daddr++)
   4669 		addcsfrag((ino_t)0, daddr, &csfrag);
   4670 
   4671 	/*
   4672 	 * filter free fragments and allocate them. Note that the free frags
   4673 	 * must be allocated first otherwise they could be grabbed by
   4674 	 * alloccsfragino() for data frags.
   4675 	 */
   4676 	findcsfragfree();
   4677 	alloccsfragfree();
   4678 
   4679 	/*
   4680 	 * filter fragments owned by inodes and allocate them
   4681 	 */
   4682 	grow_fs_ncg = sblock.fs_ncg; /* findcsfragino() needs this glob. var. */
   4683 	findcsfragino();
   4684 	alloccsfragino();
   4685 
   4686 	if (notenoughspace()) {
   4687 		/*
   4688 		 * check how many consecutive fragments could be allocated
   4689 		 * in both lists.
   4690 		 */
   4691 		int64_t tmp_frags;
   4692 		for (daddr = oldfrag_daddr; daddr < newfrag_daddr;
   4693 		    daddr += tmp_frags) {
   4694 			if ((tmp_frags = checkfragallocated(daddr)) > 0)
   4695 				growth_csum_frags += tmp_frags;
   4696 			else
   4697 				break;
   4698 		}
   4699 	} else {
   4700 		/*
   4701 		 * We have all we need for the new desired size,
   4702 		 * so clean up and report back.
   4703 		 */
   4704 		return (fssize_db);
   4705 	}
   4706 
   4707 	/*
   4708 	 * given the number of fragments by which the csum block can be grown
   4709 	 * compute by how many new fragments the FS can be increased.
   4710 	 * It is the number of csum instances per fragment multiplied by
   4711 	 * `growth_csum_frags' and the number of fragments per cylinder group.
   4712 	 */
   4713 	growth_fs_frags = howmany(sblock.fs_fsize, sizeof (struct csum)) *
   4714 	    growth_csum_frags * sblock.fs_fpg;
   4715 
   4716 	/*
   4717 	 * compute free fragments in the last cylinder group
   4718 	 */
   4719 	rdcg(sblock.fs_ncg - 1);
   4720 	growth_fs_frags += sblock.fs_fpg - acg.cg_ndblk;
   4721 
   4722 	/*
   4723 	 * compute how many csum instances are unused in the old csum block.
   4724 	 * For each unused csum instance the FS can be grown by one cylinder
   4725 	 * group without extending the csum block.
   4726 	 */
   4727 	spare_csum = howmany(sblock.fs_cssize, sizeof (struct csum)) -
   4728 	    sblock.fs_ncg;
   4729 	if (spare_csum > 0)
   4730 		growth_fs_frags += spare_csum * sblock.fs_fpg;
   4731 
   4732 	/*
   4733 	 * recalculate the new filesystem size in sectors, shorten it by
   4734 	 * the requested size `fssize_db' if necessary.
   4735 	 */
   4736 	if (growth_fs_frags > 0) {
   4737 		diskaddr_t sect;
   4738 		sect = (sblock.fs_size + growth_fs_frags) * sblock.fs_nspf;
   4739 		return ((sect > fssize_db) ? fssize_db : sect);
   4740 	}
   4741 
   4742 	return (0);
   4743 }
   4744 
   4745 void
   4746 extendsummaryinfo()
   4747 {
   4748 	int64_t		i;
   4749 	int		localtest	= test;
   4750 	int64_t		frags;
   4751 	daddr32_t		oldfrag;
   4752 	daddr32_t		newfrag;
   4753 
   4754 	/*
   4755 	 * if no-write (-N), don't bother
   4756 	 */
   4757 	if (Nflag)
   4758 		return;
   4759 
   4760 again:
   4761 	flcg();
   4762 	/*
   4763 	 * summary info did not change size -- do nothing unless in test mode
   4764 	 */
   4765 	if (grow_fs_cssize == sblock.fs_cssize)
   4766 		if (!localtest)
   4767 			return;
   4768 
   4769 	/*
   4770 	 * build list of frags needed for additional summary information
   4771 	 */
   4772 	oldfrag = howmany(grow_fs_cssize, sblock.fs_fsize) + grow_fs_csaddr;
   4773 	newfrag = howmany(sblock.fs_cssize, sblock.fs_fsize) + grow_fs_csaddr;
   4774 	/*
   4775 	 * add all of the frags that are required to grow the cyl summary to the
   4776 	 * csfrag list, which is the generic/unknown list, since at this point
   4777 	 * we don't yet know the state of those frags.
   4778 	 */
   4779 	for (i = oldfrag, frags = 0; i < newfrag; ++i, ++frags)
   4780 		addcsfrag((ino_t)0, (diskaddr_t)i, &csfrag);
   4781 	/*
   4782 	 * reduce the number of data blocks in the file system (fs_dsize) by
   4783 	 * the number of frags that need to be added to the cyl summary
   4784 	 */
   4785 	sblock.fs_dsize -= (newfrag - oldfrag);
   4786 
   4787 	/*
   4788 	 * In test mode, we move more data than necessary from
   4789 	 * cylinder group 0.  The lookup/allocate/move code can be
   4790 	 * better stressed without having to create HUGE file systems.
   4791 	 */
   4792 	if (localtest)
   4793 		for (i = newfrag; i < grow_sifrag; ++i) {
   4794 			if (frags >= testfrags)
   4795 				break;
   4796 			frags++;
   4797 			addcsfrag((ino_t)0, (diskaddr_t)i, &csfrag);
   4798 		}
   4799 
   4800 	/*
   4801 	 * move frags to free or inode lists, depending on owner
   4802 	 */
   4803 	findcsfragfree();
   4804 	findcsfragino();
   4805 
   4806 	/*
   4807 	 * if not all frags can be located, file system must be inconsistent
   4808 	 */
   4809 	if (csfrag) {
   4810 		isbad = 1;	/* should already be set, but make sure */
   4811 		lockexit(32);
   4812 	}
   4813 
   4814 	/*
   4815 	 * allocate the free frags. Note that the free frags must be allocated
   4816 	 * first otherwise they could be grabbed by alloccsfragino() for data
   4817 	 * frags.
   4818 	 */
   4819 	alloccsfragfree();
   4820 	/*
   4821 	 * allocate extra space for inode frags
   4822 	 */
   4823 	alloccsfragino();
   4824 
   4825 	/*
   4826 	 * not enough space
   4827 	 */
   4828 	if (notenoughspace()) {
   4829 		unalloccsfragfree();
   4830 		unalloccsfragino();
   4831 		if (localtest && !testforce) {
   4832 			localtest = 0;
   4833 			goto again;
   4834 		}
   4835 		(void) fprintf(stderr, gettext("Not enough free space\n"));
   4836 		lockexit(NOTENOUGHSPACE);
   4837 	}
   4838 
   4839 	/*
   4840 	 * copy the data from old frags to new frags
   4841 	 */
   4842 	copycsfragino();
   4843 
   4844 	/*
   4845 	 * fix the inodes to point to the new frags
   4846 	 */
   4847 	fixcsfragino();
   4848 
   4849 	/*
   4850 	 * We may have moved more frags than we needed.  Free them.
   4851 	 */
   4852 	rdcg((long)0);
   4853 	for (i = newfrag; i <= maxcsfrag; ++i)
   4854 		setbit(cg_blksfree(&acg), i-cgbase(&sblock, 0));
   4855 	wtcg();
   4856 
   4857 	flcg();
   4858 }
   4859 
   4860 /*
   4861  * Check if all fragments in the `csfragino' list were reallocated.
   4862  */
   4863 int
   4864 notenoughspace()
   4865 {
   4866 	struct csfrag	*cfp;
   4867 
   4868 	/*
   4869 	 * If any element in the csfragino array has a "new frag location"
   4870 	 * of 0, the allocfrags() function was unsuccessful in allocating
   4871 	 * space for moving the frag represented by this array element.
   4872 	 */
   4873 	for (cfp = csfragino; cfp; cfp = cfp->next)
   4874 		if (cfp->nfrag == 0)
   4875 			return (1);
   4876 	return (0);
   4877 }
   4878 
   4879 void
   4880 unalloccsfragino()
   4881 {
   4882 	struct csfrag	*cfp;
   4883 
   4884 	while ((cfp = csfragino) != NULL) {
   4885 		if (cfp->nfrag)
   4886 			freefrags(cfp->nfrag, cfp->frags, cfp->cylno);
   4887 		delcsfrag(cfp->ofrag, &csfragino);
   4888 	}
   4889 }
   4890 
   4891 void
   4892 unalloccsfragfree()
   4893 {
   4894 	struct csfrag	*cfp;
   4895 
   4896 	while ((cfp = csfragfree) != NULL) {
   4897 		freefrags(cfp->ofrag, cfp->frags, cfp->cylno);
   4898 		delcsfrag(cfp->ofrag, &csfragfree);
   4899 	}
   4900 }
   4901 
   4902 /*
   4903  * For each frag in the "as-yet-unclassified" list (csfrag), see if
   4904  * it's free (i.e., its bit is set in the free frag bit map).  If so,
   4905  * move it from the "as-yet-unclassified" list to the csfragfree list.
   4906  */
   4907 void
   4908 findcsfragfree()
   4909 {
   4910 	struct csfrag	*cfp;
   4911 	struct csfrag	*cfpnext;
   4912 
   4913 	/*
   4914 	 * move free frags onto the free-frag list
   4915 	 */
   4916 	rdcg((long)0);
   4917 	for (cfp = csfrag; cfp; cfp = cfpnext) {
   4918 		cfpnext = cfp->next;
   4919 		if (isset(cg_blksfree(&acg), cfp->ofrag - cgbase(&sblock, 0))) {
   4920 			addcsfrag(cfp->ino, cfp->ofrag, &csfragfree);
   4921 			delcsfrag(cfp->ofrag, &csfrag);
   4922 		}
   4923 	}
   4924 }
   4925 
   4926 void
   4927 copycsfragino()
   4928 {
   4929 	struct csfrag	*cfp;
   4930 	char		buf[MAXBSIZE];
   4931 
   4932 	/*
   4933 	 * copy data from old frags to newly allocated frags
   4934 	 */
   4935 	for (cfp = csfragino; cfp; cfp = cfp->next) {
   4936 		rdfs(fsbtodb(&sblock, (uint64_t)cfp->ofrag), (int)cfp->size,
   4937 		    buf);
   4938 		wtfs(fsbtodb(&sblock, (uint64_t)cfp->nfrag), (int)cfp->size,
   4939 		    buf);
   4940 	}
   4941 }
   4942 
   4943 long	curcylno	= -1;
   4944 int	cylnodirty	= 0;
   4945 
   4946 void
   4947 rdcg(long cylno)
   4948 {
   4949 	if (cylno != curcylno) {
   4950 		flcg();
   4951 		curcylno = cylno;
   4952 		rdfs(fsbtodb(&sblock, (uint64_t)cgtod(&sblock, curcylno)),
   4953 		    (int)sblock.fs_cgsize, (char *)&acg);
   4954 	}
   4955 }
   4956 
   4957 void
   4958 flcg()
   4959 {
   4960 	if (cylnodirty) {
   4961 		if (debug && Pflag) {
   4962 			(void) fprintf(stderr,
   4963 			    "Assert: cylnodirty set in probe mode\n");
   4964 			return;
   4965 		}
   4966 		resetallocinfo();
   4967 		wtfs(fsbtodb(&sblock, (uint64_t)cgtod(&sblock, curcylno)),
   4968 		    (int)sblock.fs_cgsize, (char *)&acg);
   4969 		cylnodirty = 0;
   4970 	}
   4971 	curcylno = -1;
   4972 }
   4973 
   4974 void
   4975 wtcg()
   4976 {
   4977 	if (!Pflag) {
   4978 		/* probe mode should never write to disk */
   4979 		cylnodirty = 1;
   4980 	}
   4981 }
   4982 
   4983 void
   4984 allocfrags(long frags, daddr32_t *fragp, long *cylnop)
   4985 {
   4986 	int	 i;
   4987 	int	 j;
   4988 	long	 bits;
   4989 	long	 bit;
   4990 
   4991 	/*
   4992 	 * Allocate a free-frag range in an old cylinder group
   4993 	 */
   4994 	for (i = 0, *fragp = 0; i < grow_fs_ncg; ++i) {
   4995 		if (((fscs+i)->cs_nffree < frags) && ((fscs+i)->cs_nbfree == 0))
   4996 			continue;
   4997 		rdcg((long)i);
   4998 		bit = bits = 0;
   4999 		while (findfreerange(&bit, &bits)) {
   5000 			if (frags <= bits)  {
   5001 				for (j = 0; j < frags; ++j)
   5002 					clrbit(cg_blksfree(&acg), bit+j);
   5003 				wtcg();
   5004 				*cylnop = i;
   5005 				*fragp  = bit + cgbase(&sblock, i);
   5006 				return;
   5007 			}
   5008 			bit += bits;
   5009 		}
   5010 	}
   5011 }
   5012 
   5013 /*
   5014  * Allocate space for frags that need to be moved in order to free up space for
   5015  * expanding the cylinder summary info.
   5016  * For each frag that needs to be moved (each frag or range of frags in
   5017  * the csfragino list), allocate a new location and store the frag number
   5018  * of that new location in the nfrag field of the csfrag struct.
   5019  * If a new frag can't be allocated for any element in the csfragino list,
   5020  * set the new frag number for that element to 0 and return immediately.
   5021  * The notenoughspace() function will detect this condition.
   5022  */
   5023 void
   5024 alloccsfragino()
   5025 {
   5026 	struct csfrag	*cfp;
   5027 
   5028 	/*
   5029 	 * allocate space for inode frag ranges
   5030 	 */
   5031 	for (cfp = csfragino; cfp; cfp = cfp->next) {
   5032 		allocfrags(cfp->frags, &cfp->nfrag, &cfp->cylno);
   5033 		if (cfp->nfrag == 0)
   5034 			break;
   5035 	}
   5036 }
   5037 
   5038 void
   5039 alloccsfragfree()
   5040 {
   5041 	struct csfrag	*cfp;
   5042 
   5043 	/*
   5044 	 * allocate the free frags needed for extended summary info
   5045 	 */
   5046 	rdcg((long)0);
   5047 
   5048 	for (cfp = csfragfree; cfp; cfp = cfp->next)
   5049 		clrbit(cg_blksfree(&acg), cfp->ofrag - cgbase(&sblock, 0));
   5050 
   5051 	wtcg();
   5052 }
   5053 
   5054 void
   5055 freefrags(daddr32_t frag, long frags, long cylno)
   5056 {
   5057 	int	i;
   5058 
   5059 	/*
   5060 	 * free frags
   5061 	 */
   5062 	rdcg(cylno);
   5063 	for (i = 0; i < frags; ++i) {
   5064 		setbit(cg_blksfree(&acg), (frag+i) - cgbase(&sblock, cylno));
   5065 	}
   5066 	wtcg();
   5067 }
   5068 
   5069 int
   5070 findfreerange(long *bitp, long *bitsp)
   5071 {
   5072 	long	 bit;
   5073 
   5074 	/*
   5075 	 * find a range of free bits in a cylinder group bit map
   5076 	 */
   5077 	for (bit = *bitp, *bitsp = 0; bit < acg.cg_ndblk; ++bit)
   5078 		if (isset(cg_blksfree(&acg), bit))
   5079 			break;
   5080 
   5081 	if (bit >= acg.cg_ndblk)
   5082 		return (0);
   5083 
   5084 	*bitp  = bit;
   5085 	*bitsp = 1;
   5086 	for (++bit; bit < acg.cg_ndblk; ++bit, ++(*bitsp)) {
   5087 		if ((bit % sblock.fs_frag) == 0)
   5088 			break;
   5089 		if (isclr(cg_blksfree(&acg), bit))
   5090 			break;
   5091 	}
   5092 	return (1);
   5093 }
   5094 
   5095 void
   5096 resetallocinfo()
   5097 {
   5098 	long	cno;
   5099 	long	bit;
   5100 	long	bits;
   5101 
   5102 	/*
   5103 	 * Compute the free blocks/frags info and update the appropriate
   5104 	 * inmemory superblock, summary info, and cylinder group fields
   5105 	 */
   5106 	sblock.fs_cstotal.cs_nffree -= acg.cg_cs.cs_nffree;
   5107 	sblock.fs_cstotal.cs_nbfree -= acg.cg_cs.cs_nbfree;
   5108 
   5109 	acg.cg_cs.cs_nffree = 0;
   5110 	acg.cg_cs.cs_nbfree = 0;
   5111 
   5112 	bzero((caddr_t)acg.cg_frsum, sizeof (acg.cg_frsum));
   5113 	bzero((caddr_t)cg_blktot(&acg), (int)(acg.cg_iusedoff-acg.cg_btotoff));
   5114 
   5115 	bit = bits = 0;
   5116 	while (findfreerange(&bit, &bits)) {
   5117 		if (bits == sblock.fs_frag) {
   5118 			acg.cg_cs.cs_nbfree++;
   5119 			cno = cbtocylno(&sblock, bit);
   5120 			cg_blktot(&acg)[cno]++;
   5121 			cg_blks(&sblock, &acg, cno)[cbtorpos(&sblock, bit)]++;
   5122 		} else {
   5123 			acg.cg_cs.cs_nffree += bits;
   5124 			acg.cg_frsum[bits]++;
   5125 		}
   5126 		bit += bits;
   5127 	}
   5128 
   5129 	*(fscs + acg.cg_cgx) = acg.cg_cs;
   5130 
   5131 	sblock.fs_cstotal.cs_nffree += acg.cg_cs.cs_nffree;
   5132 	sblock.fs_cstotal.cs_nbfree += acg.cg_cs.cs_nbfree;
   5133 }
   5134 
   5135 void
   5136 extendcg(long cylno)
   5137 {
   5138 	int	i;
   5139 	diskaddr_t	dupper;
   5140 	diskaddr_t	cbase;
   5141 	diskaddr_t	dmax;
   5142 
   5143 	/*
   5144 	 * extend the cylinder group at the end of the old file system
   5145 	 * if it was partially allocated becase of lack of space
   5146 	 */
   5147 	flcg();
   5148 	rdcg(cylno);
   5149 
   5150 	dupper = acg.cg_ndblk;
   5151 	if (cylno == sblock.fs_ncg - 1)
   5152 		acg.cg_ncyl = sblock.fs_ncyl - (sblock.fs_cpg * cylno);
   5153 	else
   5154 		acg.cg_ncyl = sblock.fs_cpg;
   5155 	cbase = cgbase(&sblock, cylno);
   5156 	dmax = cbase + sblock.fs_fpg;
   5157 	if (dmax > sblock.fs_size)
   5158 		dmax = sblock.fs_size;
   5159 	acg.cg_ndblk = dmax - cbase;
   5160 
   5161 	for (i = dupper; i < acg.cg_ndblk; ++i)
   5162 		setbit(cg_blksfree(&acg), i);
   5163 
   5164 	sblock.fs_dsize += (acg.cg_ndblk - dupper);
   5165 
   5166 	wtcg();
   5167 	flcg();
   5168 }
   5169 
   5170 struct lockfs	lockfs;
   5171 int		lockfd;
   5172 int		islocked;
   5173 int		lockfskey;
   5174 char		lockfscomment[128];
   5175 
   5176 void
   5177 ulockfs()
   5178 {
   5179 	/*
   5180 	 * if the file system was locked, unlock it before exiting
   5181 	 */
   5182 	if (islocked == 0)
   5183 		return;
   5184 
   5185 	/*
   5186 	 * first, check if the lock held
   5187 	 */
   5188 	lockfs.lf_flags = LOCKFS_MOD;
   5189 	if (ioctl(lockfd, _FIOLFSS, &lockfs) == -1) {
   5190 		perror(directory);
   5191 		lockexit(32);
   5192 	}
   5193 
   5194 	if (LOCKFS_IS_MOD(&lockfs)) {
   5195 		(void) fprintf(stderr,
   5196 		    gettext("FILE SYSTEM CHANGED DURING GROWFS!\n"));
   5197 		(void) fprintf(stderr,
   5198 		    gettext("   See lockfs(1), umount(1), and fsck(1)\n"));
   5199 		lockexit(32);
   5200 	}
   5201 	/*
   5202 	 * unlock the file system
   5203 	 */
   5204 	lockfs.lf_lock  = LOCKFS_ULOCK;
   5205 	lockfs.lf_flags = 0;
   5206 	lockfs.lf_key   = lockfskey;
   5207 	clockfs();
   5208 	if (ioctl(lockfd, _FIOLFS, &lockfs) == -1) {
   5209 		perror(directory);
   5210 		lockexit(32);
   5211 	}
   5212 }
   5213 
   5214 void
   5215 wlockfs()
   5216 {
   5217 
   5218 	/*
   5219 	 * if no-write (-N), don't bother
   5220 	 */
   5221 	if (Nflag)
   5222 		return;
   5223 	/*
   5224 	 * open the mountpoint, and write lock the file system
   5225 	 */
   5226 	if ((lockfd = open64(directory, O_RDONLY)) == -1) {
   5227 		perror(directory);
   5228 		lockexit(32);
   5229 	}
   5230 
   5231 	/*
   5232 	 * check if it is already locked
   5233 	 */
   5234 	if (ioctl(lockfd, _FIOLFSS, &lockfs) == -1) {
   5235 		perror(directory);
   5236 		lockexit(32);
   5237 	}
   5238 
   5239 	if (lockfs.lf_lock != LOCKFS_WLOCK) {
   5240 		lockfs.lf_lock  = LOCKFS_WLOCK;
   5241 		lockfs.lf_flags = 0;
   5242 		lockfs.lf_key   = 0;
   5243 		clockfs();
   5244 		if (ioctl(lockfd, _FIOLFS, &lockfs) == -1) {
   5245 			perror(directory);
   5246 			lockexit(32);
   5247 		}
   5248 	}
   5249 	islocked = 1;
   5250 	lockfskey = lockfs.lf_key;
   5251 }
   5252 
   5253 void
   5254 clockfs()
   5255 {
   5256 	time_t	t;
   5257 	char	*ct;
   5258 
   5259 	(void) time(&t);
   5260 	ct = ctime(&t);
   5261 	ct[strlen(ct)-1] = '\0';
   5262 
   5263 	(void) sprintf(lockfscomment, "%s -- mkfs pid %d", ct, getpid());
   5264 	lockfs.lf_comlen  = strlen(lockfscomment)+1;
   5265 	lockfs.lf_comment = lockfscomment;
   5266 }
   5267 
   5268 /*
   5269  * Write the csum records and the superblock
   5270  */
   5271 void
   5272 wtsb()
   5273 {
   5274 	long	i;
   5275 
   5276 	/*
   5277 	 * write summary information
   5278 	 */
   5279 	for (i = 0; i < sblock.fs_cssize; i += sblock.fs_bsize)
   5280 		wtfs(fsbtodb(&sblock, (uint64_t)(sblock.fs_csaddr +
   5281 		    numfrags(&sblock, i))),
   5282 		    (int)(sblock.fs_cssize - i < sblock.fs_bsize ?
   5283 		    sblock.fs_cssize - i : sblock.fs_bsize),
   5284 		    ((char *)fscs) + i);
   5285 
   5286 	/*
   5287 	 * write superblock
   5288 	 */
   5289 	sblock.fs_time = mkfstime;
   5290 	wtfs((diskaddr_t)(SBOFF / sectorsize), sbsize, (char *)&sblock);
   5291 }
   5292 
   5293 /*
   5294  * Verify that the optimization selection is reasonable, and advance
   5295  * the global "string" appropriately.
   5296  */
   5297 static char
   5298 checkopt(char *optim)
   5299 {
   5300 	char	opt;
   5301 	int	limit = strcspn(optim, ",");
   5302 
   5303 	switch (limit) {
   5304 	case 0:	/* missing indicator (have comma or nul) */
   5305 		(void) fprintf(stderr, gettext(
   5306 		    "mkfs: missing optimization flag reset to `t' (time)\n"));
   5307 		opt = 't';
   5308 		break;
   5309 
   5310 	case 1: /* single-character indicator */
   5311 		opt = *optim;
   5312 		if ((opt != 's') && (opt != 't')) {
   5313 			(void) fprintf(stderr, gettext(
   5314 		    "mkfs: bad optimization value `%c' reset to `t' (time)\n"),
   5315 			    opt);
   5316 			opt = 't';
   5317 		}
   5318 		break;
   5319 
   5320 	default: /* multi-character indicator */
   5321 		(void) fprintf(stderr, gettext(
   5322 	    "mkfs: bad optimization value `%*.*s' reset to `t' (time)\n"),
   5323 		    limit, limit, optim);
   5324 		opt = 't';
   5325 		break;
   5326 	}
   5327 
   5328 	string += limit;
   5329 
   5330 	return (opt);
   5331 }
   5332 
   5333 /*
   5334  * Verify that the mtb selection is reasonable, and advance
   5335  * the global "string" appropriately.
   5336  */
   5337 static char
   5338 checkmtb(char *mtbarg)
   5339 {
   5340 	char	mtbc;
   5341 	int	limit = strcspn(mtbarg, ",");
   5342 
   5343 	switch (limit) {
   5344 	case 0:	/* missing indicator (have comma or nul) */
   5345 		(void) fprintf(stderr, gettext(
   5346 		    "mkfs: missing mtb flag reset to `n' (no mtb support)\n"));
   5347 		mtbc = 'n';
   5348 		break;
   5349 
   5350 	case 1: /* single-character indicator */
   5351 		mtbc = tolower(*mtbarg);
   5352 		if ((mtbc != 'y') && (mtbc != 'n')) {
   5353 			(void) fprintf(stderr, gettext(
   5354 		    "mkfs: bad mtb value `%c' reset to `n' (no mtb support)\n"),
   5355 			    mtbc);
   5356 			mtbc = 'n';
   5357 		}
   5358 		break;
   5359 
   5360 	default: /* multi-character indicator */
   5361 		(void) fprintf(stderr, gettext(
   5362 	    "mkfs: bad mtb value `%*.*s' reset to `n' (no mtb support)\n"),
   5363 		    limit, limit, mtbarg);
   5364 		opt = 'n';
   5365 		break;
   5366 	}
   5367 
   5368 	string += limit;
   5369 
   5370 	return (mtbc);
   5371 }
   5372 
   5373 /*
   5374  * Verify that a value is in a range.  If it is not, resets it to
   5375  * its default value if one is supplied, exits otherwise.
   5376  *
   5377  * When testing, can compare user_supplied to RC_KEYWORD or RC_POSITIONAL.
   5378  */
   5379 static void
   5380 range_check(long *varp, char *name, long minimum, long maximum,
   5381     long def_val, int user_supplied)
   5382 {
   5383 	dprintf(("DeBuG %s : %ld (%ld %ld %ld)\n",
   5384 	    name, *varp, minimum, maximum, def_val));
   5385 
   5386 	if ((*varp < minimum) || (*varp > maximum)) {
   5387 		if (user_supplied != RC_DEFAULT) {
   5388 			(void) fprintf(stderr, gettext(
   5389 	    "mkfs: bad value for %s: %ld must be between %ld and %ld\n"),
   5390 			    name, *varp, minimum, maximum);
   5391 		}
   5392 		if (def_val != NO_DEFAULT) {
   5393 			if (user_supplied) {
   5394 				(void) fprintf(stderr,
   5395 				    gettext("mkfs: %s reset to default %ld\n"),
   5396 				    name, def_val);
   5397 			}
   5398 			*varp = def_val;
   5399 			dprintf(("DeBuG %s : %ld\n", name, *varp));
   5400 			return;
   5401 		}
   5402 		lockexit(2);
   5403 		/*NOTREACHED*/
   5404 	}
   5405 }
   5406 
   5407 /*
   5408  * Verify that a value is in a range.  If it is not, resets it to
   5409  * its default value if one is supplied, exits otherwise.
   5410  *
   5411  * When testing, can compare user_supplied to RC_KEYWORD or RC_POSITIONAL.
   5412  */
   5413 static void
   5414 range_check_64(uint64_t *varp, char *name, uint64_t minimum, uint64_t maximum,
   5415     uint64_t def_val, int user_supplied)
   5416 {
   5417 	if ((*varp < minimum) || (*varp > maximum)) {
   5418 		if (user_supplied != RC_DEFAULT) {
   5419 			(void) fprintf(stderr, gettext(
   5420 	    "mkfs: bad value for %s: %lld must be between %lld and %lld\n"),
   5421 			    name, *varp, minimum, maximum);
   5422 		}
   5423 		if (def_val != NO_DEFAULT) {
   5424 			if (user_supplied) {
   5425 				(void) fprintf(stderr,
   5426 				    gettext("mkfs: %s reset to default %lld\n"),
   5427 				    name, def_val);
   5428 			}
   5429 			*varp = def_val;
   5430 			return;
   5431 		}
   5432 		lockexit(2);
   5433 		/*NOTREACHED*/
   5434 	}
   5435 }
   5436 
   5437 /*
   5438  * Blocks SIGINT from delivery.  Returns the previous mask in the
   5439  * buffer provided, so that mask may be later restored.
   5440  */
   5441 static void
   5442 block_sigint(sigset_t *old_mask)
   5443 {
   5444 	sigset_t block_mask;
   5445 
   5446 	if (sigemptyset(&block_mask) < 0) {
   5447 		fprintf(stderr, gettext("Could not clear signal mask\n"));
   5448 		lockexit(3);
   5449 	}
   5450 	if (sigaddset(&block_mask, SIGINT) < 0) {
   5451 		fprintf(stderr, gettext("Could not set signal mask\n"));
   5452 		lockexit(3);
   5453 	}
   5454 	if (sigprocmask(SIG_BLOCK, &block_mask, old_mask) < 0) {
   5455 		fprintf(stderr, gettext("Could not block SIGINT\n"));
   5456 		lockexit(3);
   5457 	}
   5458 }
   5459 
   5460 /*
   5461  * Restores the signal mask that was in force before a call
   5462  * to block_sigint().  This may actually still have SIGINT blocked,
   5463  * if we've been recursively invoked.
   5464  */
   5465 static void
   5466 unblock_sigint(sigset_t *old_mask)
   5467 {
   5468 	if (sigprocmask(SIG_UNBLOCK, old_mask, (sigset_t *)NULL) < 0) {
   5469 		fprintf(stderr, gettext("Could not restore signal mask\n"));
   5470 		lockexit(3);
   5471 	}
   5472 }
   5473 
   5474 /*
   5475  * Attempt to be somewhat graceful about being interrupted, rather than
   5476  * just silently leaving the filesystem in an unusable state.
   5477  *
   5478  * The kernel has blocked SIGINT upon entry, so we don't have to worry
   5479  * about recursion if the user starts pounding on the keyboard.
   5480  */
   5481 static void
   5482 recover_from_sigint(int signum)
   5483 {
   5484 	if (fso > -1) {
   5485 		if ((Nflag != 0) || confirm_abort()) {
   5486 			lockexit(4);
   5487 		}
   5488 	}
   5489 }
   5490 
   5491 static int
   5492 confirm_abort(void)
   5493 {
   5494 	char line[80];
   5495 
   5496 	printf(gettext("\n\nAborting at this point will leave the filesystem "
   5497 	    "in an inconsistent\nstate.  If you do choose to stop, "
   5498 	    "you will be given instructions on how to\nrecover "
   5499 	    "the filesystem.  Do you wish to cancel the filesystem "
   5500 	    "grow\noperation (y/n)?"));
   5501 	if (getline(stdin, line, sizeof (line)) == EOF)
   5502 		line[0] = 'y';
   5503 
   5504 	printf("\n");
   5505 	if (line[0] == 'y' || line[0] == 'Y')
   5506 		return (1);
   5507 	else {
   5508 		return (0);
   5509 	}
   5510 }
   5511 
   5512 static int
   5513 getline(FILE *fp, char *loc, int maxlen)
   5514 {
   5515 	int n;
   5516 	char *p, *lastloc;
   5517 
   5518 	p = loc;
   5519 	lastloc = &p[maxlen-1];
   5520 	while ((n = getc(fp)) != '\n') {
   5521 		if (n == EOF)
   5522 			return (EOF);
   5523 		if (!isspace(n) && p < lastloc)
   5524 			*p++ = n;
   5525 	}
   5526 	*p = 0;
   5527 	return (p - loc);
   5528 }
   5529 
   5530 /*
   5531  * Calculate the maximum value of cylinders-per-group for a file
   5532  * system with the characteristics:
   5533  *
   5534  *	bsize - file system block size
   5535  *	fragsize - frag size
   5536  *	nbpi - number of bytes of disk space per inode
   5537  *	nrpos - number of rotational positions
   5538  *	spc - sectors per cylinder
   5539  *
   5540  * These five characteristic are not adjustable (by this function).
   5541  * The only attribute of the file system which IS adjusted by this
   5542  * function in order to maximize cylinders-per-group is the proportion
   5543  * of the cylinder group overhead block used for the inode map.  The
   5544  * inode map cannot occupy more than one-third of the cylinder group
   5545  * overhead block, but it's OK for it to occupy less than one-third
   5546  * of the overhead block.
   5547  *
   5548  * The setting of nbpi determines one possible value for the maximum
   5549  * size of a cylinder group.  It does so because it determines the total
   5550  * number of inodes in the file system (file system size is fixed, and
   5551  * nbpi is fixed, so the total number of inodes is fixed too).  The
   5552  * cylinder group has to be small enough so that the number of inodes
   5553  * in the cylinder group is less than or equal to the number of bits
   5554  * in one-third (or whatever proportion is assumed) of a file system
   5555  * block.  The details of the calculation are:
   5556  *
   5557  *     The macro MAXIpG_B(bsize, inode_divisor) determines the maximum
   5558  *     number of inodes that can be in a cylinder group, given the
   5559  *     proportion of the cylinder group overhead block used for the
   5560  *     inode bitmaps (an inode_divisor of 3 means that 1/3 of the
   5561  *     block is used for inode bitmaps; an inode_divisor of 12 means
   5562  *     that 1/12 of the block is used for inode bitmaps.)
   5563  *
   5564  *     Once the number of inodes per cylinder group is known, the
   5565  *     maximum value of cylinders-per-group (determined by nbpi)
   5566  *     is calculated by the formula
   5567  *
   5568  *     maxcpg_given_nbpi = (size of a cylinder group)/(size of a cylinder)
   5569  *
   5570  *			 = (inodes-per-cg * nbpi)/(spc * DEV_BSIZE)
   5571  *
   5572  *     (Interestingly, the size of the file system never enters
   5573  *     into this calculation.)
   5574  *
   5575  * Another possible value for the maximum cylinder group size is determined
   5576  * by frag_size and nrpos.  The frags in the cylinder group must be
   5577  * representable in the frag bitmaps in the cylinder overhead block and the
   5578  * rotational positions for each cylinder must be represented in the
   5579  * rotational position tables.  The calculation of the maximum cpg
   5580  * value, given the frag and nrpos vales, is:
   5581  *
   5582  *     maxcpg_given_fragsize =
   5583  *	  (available space in the overhead block) / (size of per-cylinder data)
   5584  *
   5585  *     The available space in the overhead block =
   5586  *	  bsize - sizeof (struct cg) - space_used_for_inode_bitmaps
   5587  *
   5588  *     The size of the per-cylinder data is:
   5589  *	    sizeof(long)            # for the "blocks avail per cylinder" field
   5590  *	    + nrpos * sizeof(short)   # for the rotational position table entry
   5591  *	    + frags-per-cylinder/NBBY # number of bytes to represent this
   5592  *				      # cylinder in the frag bitmap
   5593  *
   5594  * The two calculated maximum values of cylinder-per-group will typically
   5595  * turn out to be different, since they are derived from two different
   5596  * constraints.  Usually, maxcpg_given_nbpi is much bigger than
   5597  * maxcpg_given_fragsize.  But they can be brought together by
   5598  * adjusting the proportion of the overhead block dedicated to
   5599  * the inode bitmaps.  Decreasing the proportion of the cylinder
   5600  * group overhead block used for inode maps will decrease
   5601  * maxcpg_given_nbpi and increase maxcpg_given_fragsize.
   5602  *
   5603  * This function calculates the initial values of maxcpg_given_nbpi
   5604  * and maxcpg_given_fragsize assuming that 1/3 of the cg overhead
   5605  * block is used for inode bitmaps.  Then it decreases the proportion
   5606  * of the cg overhead block used for inode bitmaps (by increasing
   5607  * the value of inode_divisor) until maxcpg_given_nbpi and
   5608  * maxcpg_given_fragsize are the same, or stop changing, or
   5609  * maxcpg_given_nbpi is less than maxcpg_given_fragsize.
   5610  *
   5611  * The loop terminates when any of the following occur:
   5612  *	* maxcpg_given_fragsize is greater than or equal to
   5613  *	  maxcpg_given_nbpi
   5614  *	* neither maxcpg_given_fragsize nor maxcpg_given_nbpi
   5615  *	  change in the expected direction
   5616  *
   5617  * The loop is guaranteed to terminate because it only continues
   5618  * while maxcpg_given_fragsize and maxcpg_given_nbpi are approaching
   5619  * each other.  As soon they cross each other, or neither one changes
   5620  * in the direction of the other, or one of them moves in the wrong
   5621  * direction, the loop completes.
   5622  */
   5623 
   5624 static long
   5625 compute_maxcpg(long bsize, long fragsize, long nbpi, long nrpos, long spc)
   5626 {
   5627 	int	maxcpg_given_nbpi;	/* in cylinders */
   5628 	int	maxcpg_given_fragsize;	/* in cylinders */
   5629 	int	spf;			/* sectors per frag */
   5630 	int	inode_divisor;
   5631 	int	old_max_given_frag = 0;
   5632 	int	old_max_given_nbpi = INT_MAX;
   5633 
   5634 	spf = fragsize / DEV_BSIZE;
   5635 	inode_divisor = 3;
   5636 
   5637 	while (1) {
   5638 		maxcpg_given_nbpi =
   5639 		    (((int64_t)(MAXIpG_B(bsize, inode_divisor))) * nbpi) /
   5640 		    (DEV_BSIZE * ((int64_t)spc));
   5641 		maxcpg_given_fragsize =
   5642 		    (bsize - (sizeof (struct cg)) - (bsize / inode_divisor)) /
   5643 		    (sizeof (long) + nrpos * sizeof (short) +
   5644 		    (spc / spf) / NBBY);
   5645 
   5646 		if (maxcpg_given_fragsize >= maxcpg_given_nbpi)
   5647 			return (maxcpg_given_nbpi);
   5648 
   5649 		/*
   5650 		 * If neither value moves toward the other, return the
   5651 		 * least of the old values (we use the old instead of the
   5652 		 * new because: if the old is the same as the new, it
   5653 		 * doesn't matter which ones we use.  If one of the
   5654 		 * values changed, but in the wrong direction, the
   5655 		 * new values are suspect.  Better use the old.  This
   5656 		 * shouldn't happen, but it's best to check.
   5657 		 */
   5658 
   5659 		if (!(maxcpg_given_nbpi < old_max_given_nbpi) &&
   5660 		    !(maxcpg_given_fragsize > old_max_given_frag))
   5661 			return (MIN(old_max_given_nbpi, old_max_given_frag));
   5662 
   5663 		/*
   5664 		 * This is probably impossible, but if one of the maxcpg
   5665 		 * values moved in the "right" direction and one moved
   5666 		 * in the "wrong" direction (that is, the two values moved
   5667 		 * in the same direction), the previous conditional won't
   5668 		 * recognize that the values aren't converging (since at
   5669 		 * least one value moved in the "right" direction, the
   5670 		 * last conditional says "keep going").
   5671 		 *
   5672 		 * Just to make absolutely certain that the loop terminates,
   5673 		 * check for one of the values moving in the "wrong" direction
   5674 		 * and terminate the loop if it happens.
   5675 		 */
   5676 
   5677 		if (maxcpg_given_nbpi > old_max_given_nbpi ||
   5678 		    maxcpg_given_fragsize < old_max_given_frag)
   5679 			return (MIN(old_max_given_nbpi, old_max_given_frag));
   5680 
   5681 		old_max_given_nbpi = maxcpg_given_nbpi;
   5682 		old_max_given_frag = maxcpg_given_fragsize;
   5683 
   5684 		inode_divisor++;
   5685 	}
   5686 }
   5687 
   5688 static int
   5689 in_64bit_mode(void)
   5690 {
   5691 	/*  cmd must be an absolute path, for security */
   5692 	char *cmd = "/usr/bin/isainfo -b";
   5693 	char buf[BUFSIZ];
   5694 	FILE *ptr;
   5695 	int retval = 0;
   5696 
   5697 	putenv("IFS= \t");
   5698 	if ((ptr = popen(cmd, "r")) != NULL) {
   5699 		if (fgets(buf, BUFSIZ, ptr) != NULL &&
   5700 		    strncmp(buf, "64", 2) == 0)
   5701 			retval = 1;
   5702 		(void) pclose(ptr);
   5703 	}
   5704 	return (retval);
   5705 }
   5706 
   5707 /*
   5708  * validate_size
   5709  *
   5710  * Return 1 if the device appears to be at least "size" sectors long.
   5711  * Return 0 if it's shorter or we can't read it.
   5712  */
   5713 
   5714 static int
   5715 validate_size(int fd, diskaddr_t size)
   5716 {
   5717 	char 		buf[DEV_BSIZE];
   5718 	int rc;
   5719 
   5720 	if ((llseek(fd, (offset_t)((size - 1) * DEV_BSIZE), SEEK_SET) == -1) ||
   5721 	    (read(fd, buf, DEV_BSIZE)) != DEV_BSIZE)
   5722 		rc = 0;
   5723 	else
   5724 		rc = 1;
   5725 	return (rc);
   5726 }
   5727 
   5728 /*
   5729  * Print every field of the calculated superblock, along with
   5730  * its value.  To make parsing easier on the caller, the value
   5731  * is printed first, then the name.  Additionally, there's only
   5732  * one name/value pair per line.  All values are reported in
   5733  * hexadecimal (with the traditional 0x prefix), as that's slightly
   5734  * easier for humans to read.  Not that they're expected to, but
   5735  * debugging happens.
   5736  */
   5737 static void
   5738 dump_sblock(void)
   5739 {
   5740 	int row, column, pending, written;
   5741 	caddr_t source;
   5742 
   5743 	if (Rflag) {
   5744 		pending = sizeof (sblock);
   5745 		source = (caddr_t)&sblock;
   5746 		do {
   5747 			written = write(fileno(stdout), source, pending);
   5748 			pending -= written;
   5749 			source += written;
   5750 		} while ((pending > 0) && (written > 0));
   5751 
   5752 		if (written < 0) {
   5753 			perror(gettext("Binary dump of superblock failed"));
   5754 			lockexit(1);
   5755 		}
   5756 		return;
   5757 	} else {
   5758 		printf("0x%x sblock.fs_link\n", sblock.fs_link);
   5759 		printf("0x%x sblock.fs_rolled\n", sblock.fs_rolled);
   5760 		printf("0x%x sblock.fs_sblkno\n", sblock.fs_sblkno);
   5761 		printf("0x%x sblock.fs_cblkno\n", sblock.fs_cblkno);
   5762 		printf("0x%x sblock.fs_iblkno\n", sblock.fs_iblkno);
   5763 		printf("0x%x sblock.fs_dblkno\n", sblock.fs_dblkno);
   5764 		printf("0x%x sblock.fs_cgoffset\n", sblock.fs_cgoffset);
   5765 		printf("0x%x sblock.fs_cgmask\n", sblock.fs_cgmask);
   5766 		printf("0x%x sblock.fs_time\n", sblock.fs_time);
   5767 		printf("0x%x sblock.fs_size\n", sblock.fs_size);
   5768 		printf("0x%x sblock.fs_dsize\n", sblock.fs_dsize);
   5769 		printf("0x%x sblock.fs_ncg\n", sblock.fs_ncg);
   5770 		printf("0x%x sblock.fs_bsize\n", sblock.fs_bsize);
   5771 		printf("0x%x sblock.fs_fsize\n", sblock.fs_fsize);
   5772 		printf("0x%x sblock.fs_frag\n", sblock.fs_frag);
   5773 		printf("0x%x sblock.fs_minfree\n", sblock.fs_minfree);
   5774 		printf("0x%x sblock.fs_rotdelay\n", sblock.fs_rotdelay);
   5775 		printf("0x%x sblock.fs_rps\n", sblock.fs_rps);
   5776 		printf("0x%x sblock.fs_bmask\n", sblock.fs_bmask);
   5777 		printf("0x%x sblock.fs_fmask\n", sblock.fs_fmask);
   5778 		printf("0x%x sblock.fs_bshift\n", sblock.fs_bshift);
   5779 		printf("0x%x sblock.fs_fshift\n", sblock.fs_fshift);
   5780 		printf("0x%x sblock.fs_maxcontig\n", sblock.fs_maxcontig);
   5781 		printf("0x%x sblock.fs_maxbpg\n", sblock.fs_maxbpg);
   5782 		printf("0x%x sblock.fs_fragshift\n", sblock.fs_fragshift);
   5783 		printf("0x%x sblock.fs_fsbtodb\n", sblock.fs_fsbtodb);
   5784 		printf("0x%x sblock.fs_sbsize\n", sblock.fs_sbsize);
   5785 		printf("0x%x sblock.fs_csmask\n", sblock.fs_csmask);
   5786 		printf("0x%x sblock.fs_csshift\n", sblock.fs_csshift);
   5787 		printf("0x%x sblock.fs_nindir\n", sblock.fs_nindir);
   5788 		printf("0x%x sblock.fs_inopb\n", sblock.fs_inopb);
   5789 		printf("0x%x sblock.fs_nspf\n", sblock.fs_nspf);
   5790 		printf("0x%x sblock.fs_optim\n", sblock.fs_optim);
   5791 #ifdef _LITTLE_ENDIAN
   5792 		printf("0x%x sblock.fs_state\n", sblock.fs_state);
   5793 #else
   5794 		printf("0x%x sblock.fs_npsect\n", sblock.fs_npsect);
   5795 #endif
   5796 		printf("0x%x sblock.fs_si\n", sblock.fs_si);
   5797 		printf("0x%x sblock.fs_trackskew\n", sblock.fs_trackskew);
   5798 		printf("0x%x sblock.fs_id[0]\n", sblock.fs_id[0]);
   5799 		printf("0x%x sblock.fs_id[1]\n", sblock.fs_id[1]);
   5800 		printf("0x%x sblock.fs_csaddr\n", sblock.fs_csaddr);
   5801 		printf("0x%x sblock.fs_cssize\n", sblock.fs_cssize);
   5802 		printf("0x%x sblock.fs_cgsize\n", sblock.fs_cgsize);
   5803 		printf("0x%x sblock.fs_ntrak\n", sblock.fs_ntrak);
   5804 		printf("0x%x sblock.fs_nsect\n", sblock.fs_nsect);
   5805 		printf("0x%x sblock.fs_spc\n", sblock.fs_spc);
   5806 		printf("0x%x sblock.fs_ncyl\n", sblock.fs_ncyl);
   5807 		printf("0x%x sblock.fs_cpg\n", sblock.fs_cpg);
   5808 		printf("0x%x sblock.fs_ipg\n", sblock.fs_ipg);
   5809 		printf("0x%x sblock.fs_fpg\n", sblock.fs_fpg);
   5810 		printf("0x%x sblock.fs_cstotal\n", sblock.fs_cstotal);
   5811 		printf("0x%x sblock.fs_fmod\n", sblock.fs_fmod);
   5812 		printf("0x%x sblock.fs_clean\n", sblock.fs_clean);
   5813 		printf("0x%x sblock.fs_ronly\n", sblock.fs_ronly);
   5814 		printf("0x%x sblock.fs_flags\n", sblock.fs_flags);
   5815 		printf("0x%x sblock.fs_fsmnt\n", sblock.fs_fsmnt);
   5816 		printf("0x%x sblock.fs_cgrotor\n", sblock.fs_cgrotor);
   5817 		printf("0x%x sblock.fs_u.fs_csp\n", sblock.fs_u.fs_csp);
   5818 		printf("0x%x sblock.fs_cpc\n", sblock.fs_cpc);
   5819 
   5820 		/*
   5821 		 * No macros are defined for the dimensions of the
   5822 		 * opostbl array.
   5823 		 */
   5824 		for (row = 0; row < 16; row++) {
   5825 			for (column = 0; column < 8; column++) {
   5826 				printf("0x%x sblock.fs_opostbl[%d][%d]\n",
   5827 				    sblock.fs_opostbl[row][column],
   5828 				    row, column);
   5829 			}
   5830 		}
   5831 
   5832 		/*
   5833 		 * Ditto the size of sparecon.
   5834 		 */
   5835 		for (row = 0; row < 51; row++) {
   5836 			printf("0x%x sblock.fs_sparecon[%d]\n",
   5837 			    sblock.fs_sparecon[row], row);
   5838 		}
   5839 
   5840 		printf("0x%x sblock.fs_version\n", sblock.fs_version);
   5841 		printf("0x%x sblock.fs_logbno\n", sblock.fs_logbno);
   5842 		printf("0x%x sblock.fs_reclaim\n", sblock.fs_reclaim);
   5843 		printf("0x%x sblock.fs_sparecon2\n", sblock.fs_sparecon2);
   5844 #ifdef _LITTLE_ENDIAN
   5845 		printf("0x%x sblock.fs_npsect\n", sblock.fs_npsect);
   5846 #else
   5847 		printf("0x%x sblock.fs_state\n", sblock.fs_state);
   5848 #endif
   5849 		printf("0x%llx sblock.fs_qbmask\n", sblock.fs_qbmask);
   5850 		printf("0x%llx sblock.fs_qfmask\n", sblock.fs_qfmask);
   5851 		printf("0x%x sblock.fs_postblformat\n", sblock.fs_postblformat);
   5852 		printf("0x%x sblock.fs_nrpos\n", sblock.fs_nrpos);
   5853 		printf("0x%x sblock.fs_postbloff\n", sblock.fs_postbloff);
   5854 		printf("0x%x sblock.fs_rotbloff\n", sblock.fs_rotbloff);
   5855 		printf("0x%x sblock.fs_magic\n", sblock.fs_magic);
   5856 
   5857 		/*
   5858 		 * fs_space isn't of much use in this context, so we'll
   5859 		 * just ignore it for now.
   5860 		 */
   5861 	}
   5862 }
   5863