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