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