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