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