xref: /illumos-gate/usr/src/cmd/fs.d/ufs/mkfs/mkfs.c (revision e77c795bcbe51aebd7579fe13cbf2a6d56eca47f)
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 /*
23  * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
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 getaline(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 (getaline(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 getaline(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