xref: /illumos-gate/usr/src/cmd/fs.d/ufs/mkfs/mkfs.c (revision 8509e9ca)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
24  */
25 
26 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
27 /*	All Rights Reserved	*/
28 
29 /*
30  * University Copyright- Copyright (c) 1982, 1986, 1988
31  * The Regents of the University of California
32  * All Rights Reserved
33  *
34  * University Acknowledgment- Portions of this document are derived from
35  * software developed by the University of California, Berkeley, and its
36  * contributors.
37  */
38 
39 /*
40  * Copyright (c) 2018, Joyent, Inc.
41  */
42 
43 /*
44  * The maximum supported file system size (in sectors) is the
45  * number of frags that can be represented in an int32_t field
46  * (INT_MAX) times the maximum number of sectors per frag.  Since
47  * the maximum frag size is MAXBSIZE, the maximum number of sectors
48  * per frag is MAXBSIZE/DEV_BSIZE.
49  */
50 #define	FS_MAX	(((diskaddr_t)INT_MAX) * (MAXBSIZE/DEV_BSIZE))
51 
52 /*
53  * make file system for cylinder-group style file systems
54  *
55  * usage:
56  *
57  *    mkfs [-F FSType] [-V] [-G [-P]] [-M dirname] [-m] [options]
58  *	[-o specific_options]  special size
59  *	[nsect ntrack bsize fsize cpg	minfree	rps nbpi opt apc rotdelay
60  *	  2     3      4     5     6	7	8   9	 10  11  12
61  *	nrpos maxcontig mtb]
62  *	13    14	15
63  *
64  *  where specific_options are:
65  *	N - no create
66  *	nsect - The number of sectors per track
67  *	ntrack - The number of tracks per cylinder
68  *	bsize - block size
69  *	fragsize - fragment size
70  *	cgsize - The number of disk cylinders per cylinder group.
71  *	free - minimum free space
72  *	rps - rotational speed (rev/sec).
73  *	nbpi - number of data bytes per allocated inode
74  *	opt - optimization (space, time)
75  *	apc - number of alternates
76  *	gap - gap size
77  *	nrpos - number of rotational positions
78  *	maxcontig - maximum number of logical blocks that will be
79  *		allocated contiguously before inserting rotational delay
80  *	mtb - if "y", set up file system for eventual growth to over a
81  *		a terabyte
82  * -P Do not grow the file system, but print on stdout the maximal
83  *    size in sectors to which the file system can be increased. The calculated
84  *    size is limited by the value provided by the operand size.
85  *
86  * Note that -P is a project-private interface and together with -G intended
87  * to be used only by the growfs script. It is therefore purposely not
88  * documented in the man page.
89  * The -P option is covered by PSARC case 2003/422.
90  */
91 
92 /*
93  * The following constants set the defaults used for the number
94  * of sectors/track (fs_nsect), and number of tracks/cyl (fs_ntrak).
95  *
96  *			NSECT		NTRAK
97  *	72MB CDC	18		9
98  *	30MB CDC	18		5
99  *	720KB Diskette	9		2
100  *
101  * However the defaults will be different for disks larger than CHSLIMIT.
102  */
103 
104 #define	DFLNSECT	32
105 #define	DFLNTRAK	16
106 
107 /*
108  * The following default sectors and tracks values are used for
109  * non-efi disks that are larger than the CHS addressing limit. The
110  * existing default cpg of 16 (DESCPG) holds good for larger disks too.
111  */
112 #define	DEF_SECTORS_EFI	128
113 #define	DEF_TRACKS_EFI	48
114 
115 /*
116  * The maximum number of cylinders in a group depends upon how much
117  * information can be stored on a single cylinder. The default is to
118  * use 16 cylinders per group.  This is effectively tradition - it was
119  * the largest value acceptable under SunOs 4.1
120  */
121 #define	DESCPG		16	/* desired fs_cpg */
122 
123 /*
124  * The following two constants set the default block and fragment sizes.
125  * Both constants must be a power of 2 and meet the following constraints:
126  *	MINBSIZE <= DESBLKSIZE <= MAXBSIZE
127  *	DEV_BSIZE <= DESFRAGSIZE <= DESBLKSIZE
128  *	DESBLKSIZE / DESFRAGSIZE <= 8
129  */
130 #define	DESBLKSIZE	8192
131 #define	DESFRAGSIZE	1024
132 
133 /*
134  * MINFREE gives the minimum acceptable percentage of file system
135  * blocks which may be free. If the freelist drops below this level
136  * only the superuser may continue to allocate blocks. This may
137  * be set to 0 if no reserve of free blocks is deemed necessary,
138  * however throughput drops by fifty percent if the file system
139  * is run at between 90% and 100% full; thus the default value of
140  * fs_minfree is 10%. With 10% free space, fragmentation is not a
141  * problem, so we choose to optimize for time.
142  */
143 #define	MINFREE		10
144 #define	DEFAULTOPT	FS_OPTTIME
145 
146 /*
147  * ROTDELAY gives the minimum number of milliseconds to initiate
148  * another disk transfer on the same cylinder. It is no longer used
149  * and will always default to 0.
150  */
151 #define	ROTDELAY	0
152 
153 /*
154  * MAXBLKPG determines the maximum number of data blocks which are
155  * placed in a single cylinder group. The default is one indirect
156  * block worth of data blocks.
157  */
158 #define	MAXBLKPG(bsize)	((bsize) / sizeof (daddr32_t))
159 
160 /*
161  * Each file system has a number of inodes statically allocated.
162  * We allocate one inode slot per NBPI bytes, expecting this
163  * to be far more than we will ever need.
164  */
165 #define	NBPI		2048	/* Number Bytes Per Inode */
166 #define	MTB_NBPI	(MB)	/* Number Bytes Per Inode for multi-terabyte */
167 
168 /*
169  * Disks are assumed to rotate at 60HZ, unless otherwise specified.
170  */
171 #define	DEFHZ		60
172 
173 /*
174  * Cylinder group related limits.
175  *
176  * For each cylinder we keep track of the availability of blocks at different
177  * rotational positions, so that we can lay out the data to be picked
178  * up with minimum rotational latency.  NRPOS is the number of rotational
179  * positions which we distinguish.  With NRPOS 8 the resolution of our
180  * summary information is 2ms for a typical 3600 rpm drive.
181  */
182 #define	NRPOS		8	/* number distinct rotational positions */
183 
184 #ifdef DEBUG
185 #define	dprintf(x)	printf x
186 #else
187 #define	dprintf(x)
188 #endif
189 
190 /*
191  * For the -N option, when calculating the backup superblocks, do not print
192  * them if we are not really sure. We may have to try an alternate method of
193  * arriving at the superblocks. So defer printing till a handful of superblocks
194  * look good.
195  */
196 #define	tprintf(x)	if (Nflag && retry) \
197 				(void) strncat(tmpbuf, x, strlen(x)); \
198 			else \
199 				(void) fprintf(stderr, x);
200 
201 #define	ALTSB		32	/* Location of first backup superblock */
202 
203 /*
204  * range_check "user_supplied" flag values.
205  */
206 #define	RC_DEFAULT	0
207 #define	RC_KEYWORD	1
208 #define	RC_POSITIONAL	2
209 
210 /*
211  * ufs hole
212  */
213 #define	UFS_HOLE	-1
214 
215 #ifndef	STANDALONE
216 #include	<stdio.h>
217 #include	<sys/mnttab.h>
218 #endif
219 
220 #include	<stdlib.h>
221 #include	<unistd.h>
222 #include	<malloc.h>
223 #include	<string.h>
224 #include	<strings.h>
225 #include	<ctype.h>
226 #include	<errno.h>
227 #include	<sys/param.h>
228 #include	<time.h>
229 #include	<sys/types.h>
230 #include	<sys/sysmacros.h>
231 #include	<sys/vnode.h>
232 #include	<sys/fs/ufs_fsdir.h>
233 #include	<sys/fs/ufs_inode.h>
234 #include	<sys/fs/ufs_fs.h>
235 #include	<sys/fs/ufs_log.h>
236 #include	<sys/mntent.h>
237 #include	<sys/filio.h>
238 #include	<limits.h>
239 #include	<sys/int_const.h>
240 #include	<signal.h>
241 #include	<sys/efi_partition.h>
242 #include	<fslib.h>
243 #include	"roll_log.h"
244 
245 #define	bcopy(f, t, n)    (void) memcpy(t, f, n)
246 #define	bzero(s, n)	(void) memset(s, 0, n)
247 #define	bcmp(s, d, n)	memcmp(s, d, n)
248 
249 #define	index(s, r)	strchr(s, r)
250 #define	rindex(s, r)	strrchr(s, r)
251 
252 #include	<sys/stat.h>
253 #include	<sys/statvfs.h>
254 #include	<locale.h>
255 #include	<fcntl.h>
256 #include	<sys/isa_defs.h>	/* for ENDIAN defines */
257 #include	<sys/vtoc.h>
258 
259 #include	<sys/dkio.h>
260 #include	<sys/asynch.h>
261 
262 extern offset_t	llseek();
263 extern char	*getfullblkname();
264 extern long	lrand48();
265 
266 extern int	optind;
267 extern char	*optarg;
268 
269 
270 /*
271  * The size of a cylinder group is calculated by CGSIZE. The maximum size
272  * is limited by the fact that cylinder groups are at most one block.
273  * Its size is derived from the size of the maps maintained in the
274  * cylinder group and the (struct cg) size.
275  */
276 #define	CGSIZE(fs) \
277 	/* base cg		*/ (sizeof (struct cg) + \
278 	/* blktot size	*/ (fs)->fs_cpg * sizeof (long) + \
279 	/* blks size	*/ (fs)->fs_cpg * (fs)->fs_nrpos * sizeof (short) + \
280 	/* inode map	*/ howmany((fs)->fs_ipg, NBBY) + \
281 	/* block map */ howmany((fs)->fs_cpg * (fs)->fs_spc / NSPF(fs), NBBY))
282 
283 /*
284  * We limit the size of the inode map to be no more than a
285  * third of the cylinder group space, since we must leave at
286  * least an equal amount of space for the block map.
287  *
288  * N.B.: MAXIpG must be a multiple of INOPB(fs).
289  */
290 #define	MAXIpG(fs)	roundup((fs)->fs_bsize * NBBY / 3, INOPB(fs))
291 
292 /*
293  * Same as MAXIpG, but parameterized by the block size (b) and the
294  * cylinder group divisor (d), which is the reciprocal of the fraction of the
295  * cylinder group overhead block that is used for the inode map.  So for
296  * example, if d = 5, the macro's computation assumes that 1/5 of the
297  * cylinder group overhead block can be dedicated to the inode map.
298  */
299 #define	MAXIpG_B(b, d)	roundup((b) * NBBY / (d), (b) / sizeof (struct dinode))
300 
301 #define	UMASK		0755
302 #define	MAXINOPB	(MAXBSIZE / sizeof (struct dinode))
303 #define	POWEROF2(num)	(((num) & ((num) - 1)) == 0)
304 #define	MB		(1024*1024)
305 #define	BETWEEN(x, l, h)	((x) >= (l) && (x) <= (h))
306 
307 /*
308  * Used to set the inode generation number. Since both inodes and dinodes
309  * are dealt with, we really need a pointer to an icommon here.
310  */
311 #define	IRANDOMIZE(icp)	(icp)->ic_gen = lrand48();
312 
313 /*
314  * Flags for number()
315  */
316 #define	ALLOW_PERCENT	0x01	/* allow trailing `%' on number */
317 #define	ALLOW_MS1	0x02	/* allow trailing `ms', state 1 */
318 #define	ALLOW_MS2	0x04	/* allow trailing `ms', state 2 */
319 #define	ALLOW_END_ONLY	0x08	/* must be at end of number & suffixes */
320 
321 #define	MAXAIO	1000	/* maximum number of outstanding I/O's we'll manage */
322 #define	BLOCK	1	/* block in aiowait */
323 #define	NOBLOCK	0	/* don't block in aiowait */
324 
325 #define	RELEASE 1	/* free an aio buffer after use */
326 #define	SAVE	0	/* don't free the buffer */
327 
328 typedef struct aio_trans {
329 	aio_result_t resultbuf;
330 	diskaddr_t bno;
331 	char *buffer;
332 	int size;
333 	int release;
334 	struct aio_trans *next;
335 } aio_trans;
336 
337 typedef struct aio_results {
338 	int max;
339 	int outstanding;
340 	int maxpend;
341 	aio_trans *trans;
342 } aio_results;
343 
344 int aio_inited = 0;
345 aio_results results;
346 
347 /*
348  * Allow up to MAXBUF aio requests that each have a unique buffer.
349  * More aio's might be done, but not using memory through the getbuf()
350  * interface.  This can be raised, but you run into the potential of
351  * using more memory than is physically available on the machine,
352  * and if you start swapping, you can forget about performance.
353  * To prevent this, we also limit the total memory used for a given
354  * type of buffer to MAXBUFMEM.
355  *
356  * Tests indicate a cylinder group's worth of inodes takes:
357  *
358  *	NBPI	Size of Inode Buffer
359  *	 2k	1688k
360  *	 8k	 424k
361  *
362  * initcg() stores all the inodes for a cylinder group in one buffer,
363  * so allowing 20 buffers could take 32 MB if not limited by MAXBUFMEM.
364  */
365 #define	MAXBUF		20
366 #define	MAXBUFMEM	(8 * 1024 * 1024)
367 
368 /*
369  * header information for buffers managed by getbuf() and freebuf()
370  */
371 typedef struct bufhdr {
372 	struct bufhdr *head;
373 	struct bufhdr *next;
374 } bufhdr;
375 
376 int bufhdrsize;
377 
378 bufhdr inodebuf = { NULL, NULL };
379 bufhdr cgsumbuf = { NULL, NULL };
380 
381 #define	SECTORS_PER_TERABYTE	(1LL << 31)
382 /*
383  * The following constant specifies an upper limit for file system size
384  * that is actually a lot bigger than we expect to support with UFS. (Since
385  * it's specified in sectors, the file system size would be 2**44 * 512,
386  * which is 2**53, which is 8192 Terabytes.)  However, it's useful
387  * for checking the basic sanity of a size value that is input on the
388  * command line.
389  */
390 #define	FS_SIZE_UPPER_LIMIT	0x100000000000LL
391 
392 /*
393  * Forward declarations
394  */
395 static char *getbuf(bufhdr *bufhead, int size);
396 static void freebuf(char *buf);
397 static void freetrans(aio_trans *transp);
398 static aio_trans *get_aiop();
399 static aio_trans *wait_for_write(int block);
400 static void initcg(int cylno);
401 static void fsinit();
402 static int makedir(struct direct *protodir, int entries);
403 static void iput(struct inode *ip);
404 static void rdfs(diskaddr_t bno, int size, char *bf);
405 static void wtfs(diskaddr_t bno, int size, char *bf);
406 static void awtfs(diskaddr_t bno, int size, char *bf, int release);
407 static void wtfs_breakup(diskaddr_t bno, int size, char *bf);
408 static int isblock(struct fs *fs, unsigned char *cp, int h);
409 static void clrblock(struct fs *fs, unsigned char *cp, int h);
410 static void setblock(struct fs *fs, unsigned char *cp, int h);
411 static void usage(void) __NORETURN;
412 static void dump_fscmd(char *fsys, int fsi);
413 static uint64_t number(uint64_t d_value, char *param, int flags);
414 static int match(char *s);
415 static char checkopt(char *optim);
416 static char checkmtb(char *mtbarg);
417 static void range_check(long *varp, char *name, long minimum,
418     long maximum, long def_val, int user_supplied);
419 static void range_check_64(uint64_t *varp, char *name, uint64_t minimum,
420     uint64_t maximum, uint64_t def_val, int user_supplied);
421 static daddr32_t alloc(int size, int mode);
422 static diskaddr_t get_max_size(int fd);
423 static long get_max_track_size(int fd);
424 static void block_sigint(sigset_t *old_mask);
425 static void unblock_sigint(sigset_t *old_mask);
426 static void recover_from_sigint(int signum);
427 static int confirm_abort(void);
428 static int getaline(FILE *fp, char *loc, int maxlen);
429 static void flush_writes(void);
430 static long compute_maxcpg(long, long, long, long, long);
431 static int in_64bit_mode(void);
432 static int validate_size(int fd, diskaddr_t size);
433 static void dump_sblock(void);
434 
435 /*
436  * Workaround for mkfs to function properly on disks attached to XMIT 2.X
437  * controller. If the address is not aligned at 8 byte boundary, mkfs on
438  * disks attached to XMIT 2.X controller exhibts un-predictable behaviour.
439  */
440 #define	XMIT_2_X_ALIGN	8
441 #pragma	align XMIT_2_X_ALIGN(fsun, altfsun, cgun)
442 
443 union {
444 	struct fs fs;
445 	char pad[SBSIZE];
446 } fsun, altfsun;
447 #define	sblock	fsun.fs
448 #define	altsblock	altfsun.fs
449 
450 struct	csum *fscs;
451 
452 union cgun {
453 	struct cg cg;
454 	char pad[MAXBSIZE];
455 } cgun;
456 
457 #define	acg	cgun.cg
458 /*
459  * Size of screen in cols in which to fit output
460  */
461 #define	WIDTH	80
462 
463 struct dinode zino[MAXBSIZE / sizeof (struct dinode)];
464 
465 /*
466  * file descriptors used for rdfs(fsi) and wtfs(fso).
467  * Initialized to an illegal file descriptor number.
468  */
469 int	fsi = -1;
470 int	fso = -1;
471 
472 /*
473  * The BIG parameter is machine dependent.  It should be a longlong integer
474  * constant that can be used by the number parser to check the validity
475  * of numeric parameters.
476  */
477 
478 #define	BIG		0x7fffffffffffffffLL
479 
480 /* Used to indicate to number() that a bogus value should cause us to exit */
481 #define	NO_DEFAULT	LONG_MIN
482 
483 /*
484  * INVALIDSBLIMIT is the number of bad backup superblocks that will be
485  * tolerated before we decide to try arriving at a different set of them
486  * using a different logic. This is applicable for non-EFI disks only.
487  */
488 #define	INVALIDSBLIMIT	10
489 
490 /*
491  * The *_flag variables are used to indicate that the user specified
492  * the values, rather than that we made them up ourselves.  We can
493  * complain about the user giving us bogus values.
494  */
495 
496 /* semi-constants */
497 long	sectorsize = DEV_BSIZE;		/* bytes/sector from param.h */
498 long	bbsize = BBSIZE;		/* boot block size */
499 long	sbsize = SBSIZE;		/* superblock size */
500 
501 /* parameters */
502 diskaddr_t	fssize_db;		/* file system size in disk blocks */
503 diskaddr_t	fssize_frag;		/* file system size in frags */
504 long	cpg;				/* cylinders/cylinder group */
505 int	cpg_flag = RC_DEFAULT;
506 long	rotdelay = -1;			/* rotational delay between blocks */
507 int	rotdelay_flag = RC_DEFAULT;
508 long	maxcontig;			/* max contiguous blocks to allocate */
509 int	maxcontig_flag = RC_DEFAULT;
510 long	nsect = DFLNSECT;		/* sectors per track */
511 int	nsect_flag = RC_DEFAULT;
512 long	ntrack = DFLNTRAK;		/* tracks per cylinder group */
513 int	ntrack_flag = RC_DEFAULT;
514 long	bsize = DESBLKSIZE;		/* filesystem block size */
515 int	bsize_flag = RC_DEFAULT;
516 long	fragsize = DESFRAGSIZE;		/* filesystem fragment size */
517 int	fragsize_flag = RC_DEFAULT;
518 long	minfree = MINFREE;		/* fs_minfree */
519 int	minfree_flag = RC_DEFAULT;
520 long	rps = DEFHZ;			/* revolutions/second of drive */
521 int	rps_flag = RC_DEFAULT;
522 long	nbpi = NBPI;			/* number of bytes per inode */
523 int	nbpi_flag = RC_DEFAULT;
524 long	nrpos = NRPOS;			/* number of rotational positions */
525 int	nrpos_flag = RC_DEFAULT;
526 long	apc = 0;			/* alternate sectors per cylinder */
527 int	apc_flag = RC_DEFAULT;
528 char	opt = 't';			/* optimization style, `t' or `s' */
529 char	mtb = 'n';			/* multi-terabyte format, 'y' or 'n' */
530 #define	DEFAULT_SECT_TRAK_CPG	(nsect_flag == RC_DEFAULT && \
531 				ntrack_flag == RC_DEFAULT && \
532 				cpg_flag == RC_DEFAULT)
533 
534 long	debug = 0;			/* enable debugging output */
535 
536 int	spc_flag = 0;			/* alternate sectors specified or */
537 					/* found */
538 
539 /* global state */
540 int	Nflag;		/* do not write to disk */
541 int	mflag;		/* return the command line used to create this FS */
542 int	rflag;		/* report the superblock in an easily-parsed form */
543 int	Rflag;		/* dump the superblock in binary */
544 char	*fsys;
545 time_t	mkfstime;
546 char	*string;
547 int	label_type;
548 
549 /*
550  * logging support
551  */
552 int	islog;			/* true if ufs logging is enabled */
553 int	islogok;		/* true if ufs log state is good */
554 int	waslog;			/* true when ufs logging disabled during grow */
555 
556 /*
557  * growfs defines, globals, and forward references
558  */
559 #define	NOTENOUGHSPACE 33
560 int		grow;
561 #define	GROW_WITH_DEFAULT_TRAK	(grow && ntrack_flag == RC_DEFAULT)
562 
563 static int	Pflag;		/* probe to which size the fs can be grown */
564 int		ismounted;
565 char		*directory;
566 diskaddr_t	grow_fssize;
567 long		grow_fs_size;
568 long		grow_fs_ncg;
569 diskaddr_t		grow_fs_csaddr;
570 long		grow_fs_cssize;
571 int		grow_fs_clean;
572 struct csum	*grow_fscs;
573 diskaddr_t		grow_sifrag;
574 int		test;
575 int		testforce;
576 diskaddr_t		testfrags;
577 int		inlockexit;
578 int		isbad;
579 
580 void		lockexit(int) __NORETURN;
581 void		randomgeneration(void);
582 void		checksummarysize(void);
583 int		checksblock(struct fs, int);
584 void		growinit(char *);
585 void		checkdev(char *, char  *);
586 void		checkmount(struct mnttab *, char *);
587 struct dinode	*gdinode(ino_t);
588 int		csfraginrange(daddr32_t);
589 struct csfrag	*findcsfrag(daddr32_t, struct csfrag **);
590 void		checkindirect(ino_t, daddr32_t *, daddr32_t, int);
591 void		addcsfrag(ino_t, daddr32_t, struct csfrag **);
592 void		delcsfrag(daddr32_t, struct csfrag **);
593 void		checkdirect(ino_t, daddr32_t *, daddr32_t *, int);
594 void		findcsfragino(void);
595 void		fixindirect(daddr32_t, int);
596 void		fixdirect(caddr_t, daddr32_t, daddr32_t *, int);
597 void		fixcsfragino(void);
598 void		extendsummaryinfo(void);
599 int		notenoughspace(void);
600 void		unalloccsfragino(void);
601 void		unalloccsfragfree(void);
602 void		findcsfragfree(void);
603 void		copycsfragino(void);
604 void		rdcg(long);
605 void		wtcg(void);
606 void		flcg(void);
607 void		allocfrags(long, daddr32_t *, long *);
608 void		alloccsfragino(void);
609 void		alloccsfragfree(void);
610 void		freefrags(daddr32_t, long, long);
611 int		findfreerange(long *, long *);
612 void		resetallocinfo(void);
613 void		extendcg(long);
614 void		ulockfs(void);
615 void		wlockfs(void);
616 void		clockfs(void);
617 void		wtsb(void);
618 static int64_t	checkfragallocated(daddr32_t);
619 static struct csum	*read_summaryinfo(struct fs *);
620 static diskaddr_t	probe_summaryinfo();
621 
622 int
main(int argc,char * argv[])623 main(int argc, char *argv[])
624 {
625 	long i, mincpc, mincpg, ibpcl;
626 	long cylno, rpos, blk, j, warn = 0;
627 	long mincpgcnt, maxcpg;
628 	uint64_t used, bpcg, inospercg;
629 	long mapcramped, inodecramped;
630 	long postblsize, rotblsize, totalsbsize;
631 	FILE *mnttab;
632 	struct mnttab mntp;
633 	char *special;
634 	struct statvfs64 fs;
635 	struct dk_geom dkg;
636 	struct dk_minfo dkminfo;
637 	char pbuf[sizeof (uint64_t) * 3 + 1];
638 	char *tmpbuf;
639 	int width, plen;
640 	uint64_t num;
641 	int c, saverr;
642 	diskaddr_t max_fssize;
643 	long tmpmaxcontig = -1;
644 	struct sigaction sigact;
645 	uint64_t nbytes64;
646 	int remaining_cg;
647 	int do_dot = 0;
648 	int use_efi_dflts = 0, retry = 0, isremovable = 0, ishotpluggable = 0;
649 	int invalid_sb_cnt, ret, skip_this_sb, cg_too_small;
650 	int geom_nsect, geom_ntrack, geom_cpg;
651 
652 	(void) setlocale(LC_ALL, "");
653 
654 #if !defined(TEXT_DOMAIN)
655 #define	TEXT_DOMAIN "SYS_TEST"
656 #endif
657 	(void) textdomain(TEXT_DOMAIN);
658 
659 	while ((c = getopt(argc, argv, "F:bmo:VPGM:T:t:")) != EOF) {
660 		switch (c) {
661 
662 		case 'F':
663 			string = optarg;
664 			if (strcmp(string, "ufs") != 0)
665 				usage();
666 			break;
667 
668 		case 'm':	/* return command line used to create this FS */
669 			mflag++;
670 			break;
671 
672 		case 'o':
673 			/*
674 			 * ufs specific options.
675 			 */
676 			string = optarg;
677 			while (*string != '\0') {
678 				if (match("nsect=")) {
679 					nsect = number(DFLNSECT, "nsect", 0);
680 					nsect_flag = RC_KEYWORD;
681 				} else if (match("ntrack=")) {
682 					ntrack = number(DFLNTRAK, "ntrack", 0);
683 					ntrack_flag = RC_KEYWORD;
684 				} else if (match("bsize=")) {
685 					bsize = number(DESBLKSIZE, "bsize", 0);
686 					bsize_flag = RC_KEYWORD;
687 				} else if (match("fragsize=")) {
688 					fragsize = number(DESFRAGSIZE,
689 					    "fragsize", 0);
690 					fragsize_flag = RC_KEYWORD;
691 				} else if (match("cgsize=")) {
692 					cpg = number(DESCPG, "cgsize", 0);
693 					cpg_flag = RC_KEYWORD;
694 				} else if (match("free=")) {
695 					minfree = number(MINFREE, "free",
696 					    ALLOW_PERCENT);
697 					minfree_flag = RC_KEYWORD;
698 				} else if (match("maxcontig=")) {
699 					tmpmaxcontig =
700 					    number(-1, "maxcontig", 0);
701 					maxcontig_flag = RC_KEYWORD;
702 				} else if (match("nrpos=")) {
703 					nrpos = number(NRPOS, "nrpos", 0);
704 					nrpos_flag = RC_KEYWORD;
705 				} else if (match("rps=")) {
706 					rps = number(DEFHZ, "rps", 0);
707 					rps_flag = RC_KEYWORD;
708 				} else if (match("nbpi=")) {
709 					nbpi = number(NBPI, "nbpi", 0);
710 					nbpi_flag = RC_KEYWORD;
711 				} else if (match("opt=")) {
712 					opt = checkopt(string);
713 				} else if (match("mtb=")) {
714 					mtb = checkmtb(string);
715 				} else if (match("apc=")) {
716 					apc = number(0, "apc", 0);
717 					apc_flag = RC_KEYWORD;
718 				} else if (match("gap=")) {
719 					(void) number(0, "gap", ALLOW_MS1);
720 					rotdelay = ROTDELAY;
721 					rotdelay_flag = RC_DEFAULT;
722 				} else if (match("debug=")) {
723 					debug = number(0, "debug", 0);
724 				} else if (match("N")) {
725 					Nflag++;
726 				} else if (match("calcsb")) {
727 					rflag++;
728 					Nflag++;
729 				} else if (match("calcbinsb")) {
730 					rflag++;
731 					Rflag++;
732 					Nflag++;
733 				} else if (*string == '\0') {
734 					break;
735 				} else {
736 					(void) fprintf(stderr, gettext(
737 					    "illegal option: %s\n"), string);
738 					usage();
739 				}
740 
741 				if (*string == ',') string++;
742 				if (*string == ' ') string++;
743 			}
744 			break;
745 
746 		case 'V':
747 			{
748 				char	*opt_text;
749 				int	opt_count;
750 
751 				(void) fprintf(stdout, gettext("mkfs -F ufs "));
752 				for (opt_count = 1; opt_count < argc;
753 				    opt_count++) {
754 					opt_text = argv[opt_count];
755 					if (opt_text)
756 						(void) fprintf(stdout, " %s ",
757 						    opt_text);
758 				}
759 				(void) fprintf(stdout, "\n");
760 			}
761 			break;
762 
763 		case 'b':	/* do nothing for this */
764 			break;
765 
766 		case 'M':	/* grow the mounted file system */
767 			directory = optarg;
768 
769 			/* FALLTHROUGH */
770 		case 'G':	/* grow the file system */
771 			grow = 1;
772 			break;
773 		case 'P':	/* probe the file system growing size	*/
774 			Pflag = 1;
775 			grow = 1; /* probe mode implies fs growing	*/
776 			break;
777 		case 'T':	/* For testing */
778 			testforce = 1;
779 
780 			/* FALLTHROUGH */
781 		case 't':
782 			test = 1;
783 			string = optarg;
784 			testfrags = number(NO_DEFAULT, "testfrags", 0);
785 			break;
786 
787 		case '?':
788 			usage();
789 			break;
790 		}
791 	}
792 #ifdef MKFS_DEBUG
793 	/*
794 	 * Turning on MKFS_DEBUG causes mkfs to produce a filesystem
795 	 * that can be reproduced by setting the time to 0 and seeding
796 	 * the random number generator to a constant.
797 	 */
798 	mkfstime = 0;	/* reproducible results */
799 #else
800 	(void) time(&mkfstime);
801 #endif
802 
803 	if (optind >= (argc - 1)) {
804 		if (optind > (argc - 1)) {
805 			(void) fprintf(stderr,
806 			    gettext("special not specified\n"));
807 			usage();
808 		} else if (mflag == 0) {
809 			(void) fprintf(stderr,
810 			    gettext("size not specified\n"));
811 			usage();
812 		}
813 	}
814 	argc -= optind;
815 	argv = &argv[optind];
816 
817 	fsys = argv[0];
818 	fsi = open64(fsys, O_RDONLY);
819 	if (fsi < 0) {
820 		(void) fprintf(stderr, gettext("%s: cannot open\n"), fsys);
821 		lockexit(32);
822 	}
823 
824 	if (mflag) {
825 		dump_fscmd(fsys, fsi);
826 		lockexit(0);
827 	}
828 
829 	/*
830 	 * The task of setting all of the configuration parameters for a
831 	 * UFS file system is basically a matter of solving n equations
832 	 * in m variables.  Typically, m is greater than n, so there is
833 	 * usually more than one valid solution.  Since this is usually
834 	 * an under-constrained problem, it's not always obvious what the
835 	 * "best" configuration is.
836 	 *
837 	 * In general, the approach is to
838 	 * 1. Determine the values for the file system parameters
839 	 *    that are externally contrained and therefore not adjustable
840 	 *    by mkfs (such as the device's size and maxtransfer size).
841 	 * 2. Acquire the user's requested setting for all configuration
842 	 *    values that can be set on the command line.
843 	 * 3. Determine the final value of all configuration values, by
844 	 *    the following approach:
845 	 *	- set the file system block size (fs_bsize).  Although
846 	 *	  this could be regarded as an adjustable parameter, in
847 	 *	  fact, it's pretty much a constant.  At this time, it's
848 	 *	  generally set to 8k (with older hardware, it can
849 	 *	  sometimes make sense to set it to 4k, but those
850 	 *	  situations are pretty rare now).
851 	 *	- re-adjust the maximum file system size based on the
852 	 *	  value of the file system block size.  Since the
853 	 *	  frag size can't be any larger than a file system
854 	 *	  block, and the number of frags in the file system
855 	 *	  has to fit into 31 bits, the file system block size
856 	 *	  affects the maximum file system size.
857 	 *	- now that the real maximum file system is known, set the
858 	 *	  actual size of the file system to be created to
859 	 *	  MIN(requested size, maximum file system size).
860 	 *	- now validate, and if necessary, adjust the following
861 	 *	  values:
862 	 *		rotdelay
863 	 *		nsect
864 	 *		maxcontig
865 	 *		apc
866 	 *		frag_size
867 	 *		rps
868 	 *		minfree
869 	 *		nrpos
870 	 *		nrack
871 	 *		nbpi
872 	 *	- calculate maxcpg (the maximum value of the cylinders-per-
873 	 *	  cylinder-group configuration parameters).  There are two
874 	 *	  algorithms for calculating maxcpg:  an old one, which is
875 	 *	  used for file systems of less than 1 terabyte, and a
876 	 *	  new one, implemented in the function compute_maxcpg(),
877 	 *	  which is used for file systems of greater than 1 TB.
878 	 *	  The difference between them is that compute_maxcpg()
879 	 *	  really tries to maximize the cpg value.  The old
880 	 *	  algorithm fails to take advantage of smaller frags and
881 	 *	  lower inode density when determining the maximum cpg,
882 	 *	  and thus comes up with much lower numbers in some
883 	 *	  configurations.  At some point, we might use the
884 	 *	  new algorithm for determining maxcpg for all file
885 	 *	  systems, but at this time, the changes implemented for
886 	 *	  multi-terabyte UFS are NOT being automatically applied
887 	 *	  to UFS file systems of less than a terabyte (in the
888 	 *	  interest of not changing existing UFS policy too much
889 	 *	  until the ramifications of the changes are well-understood
890 	 *	  and have been evaluated for their effects on performance.)
891 	 *	- check the current values of the configuration parameters
892 	 *	  against the various constraints imposed by UFS.  These
893 	 *	  include:
894 	 *		* There must be at least one inode in each
895 	 *		  cylinder group.
896 	 *		* The cylinder group overhead block, which
897 	 *		  contains the inode and frag bigmaps, must fit
898 	 *		  within one file system block.
899 	 *		* The space required for inode maps should
900 	 *		  occupy no more than a third of the cylinder
901 	 *		  group overhead block.
902 	 *		* The rotational position tables have to fit
903 	 *		  within the available space in the super block.
904 	 *	  Adjust the configuration values that can be adjusted
905 	 *	  so that these constraints are satisfied.  The
906 	 *	  configuration values that are adjustable are:
907 	 *		* frag size
908 	 *		* cylinders per group
909 	 *		* inode density (can be increased)
910 	 *		* number of rotational positions (the rotational
911 	 *		  position tables are eliminated altogether if
912 	 *		  there isn't enough room for them.)
913 	 * 4. Set the values for all the dependent configuration
914 	 *    values (those that aren't settable on the command
915 	 *    line and which are completely dependent on the
916 	 *    adjustable parameters).  This include cpc (cycles
917 	 *    per cylinder, spc (sectors-per-cylinder), and many others.
918 	 */
919 
920 	/*
921 	 * Figure out the partition size and initialize the label_type.
922 	 */
923 	max_fssize = get_max_size(fsi);
924 
925 	/*
926 	 * Get and check positional arguments, if any.
927 	 */
928 	switch (argc - 1) {
929 	default:
930 		usage();
931 		/*NOTREACHED*/
932 	case 15:
933 		mtb = checkmtb(argv[15]);
934 		/* FALLTHROUGH */
935 	case 14:
936 		string = argv[14];
937 		tmpmaxcontig = number(-1, "maxcontig", 0);
938 		maxcontig_flag = RC_POSITIONAL;
939 		/* FALLTHROUGH */
940 	case 13:
941 		string = argv[13];
942 		nrpos = number(NRPOS, "nrpos", 0);
943 		nrpos_flag = RC_POSITIONAL;
944 		/* FALLTHROUGH */
945 	case 12:
946 		string = argv[12];
947 		rotdelay = ROTDELAY;
948 		rotdelay_flag = RC_DEFAULT;
949 		/* FALLTHROUGH */
950 	case 11:
951 		string = argv[11];
952 		apc = number(0, "apc", 0);
953 		apc_flag = RC_POSITIONAL;
954 		/* FALLTHROUGH */
955 	case 10:
956 		opt = checkopt(argv[10]);
957 		/* FALLTHROUGH */
958 	case 9:
959 		string = argv[9];
960 		nbpi = number(NBPI, "nbpi", 0);
961 		nbpi_flag = RC_POSITIONAL;
962 		/* FALLTHROUGH */
963 	case 8:
964 		string = argv[8];
965 		rps = number(DEFHZ, "rps", 0);
966 		rps_flag = RC_POSITIONAL;
967 		/* FALLTHROUGH */
968 	case 7:
969 		string = argv[7];
970 		minfree = number(MINFREE, "free", ALLOW_PERCENT);
971 		minfree_flag = RC_POSITIONAL;
972 		/* FALLTHROUGH */
973 	case 6:
974 		string = argv[6];
975 		cpg = number(DESCPG, "cgsize", 0);
976 		cpg_flag = RC_POSITIONAL;
977 		/* FALLTHROUGH */
978 	case 5:
979 		string = argv[5];
980 		fragsize = number(DESFRAGSIZE, "fragsize", 0);
981 		fragsize_flag = RC_POSITIONAL;
982 		/* FALLTHROUGH */
983 	case 4:
984 		string = argv[4];
985 		bsize = number(DESBLKSIZE, "bsize", 0);
986 		bsize_flag = RC_POSITIONAL;
987 		/* FALLTHROUGH */
988 	case 3:
989 		string = argv[3];
990 		ntrack = number(DFLNTRAK, "ntrack", 0);
991 		ntrack_flag = RC_POSITIONAL;
992 		/* FALLTHROUGH */
993 	case 2:
994 		string = argv[2];
995 		nsect = number(DFLNSECT, "nsect", 0);
996 		nsect_flag = RC_POSITIONAL;
997 		/* FALLTHROUGH */
998 	case 1:
999 		string = argv[1];
1000 		fssize_db = number(max_fssize, "size", 0);
1001 	}
1002 
1003 	/*
1004 	 * Initialize the parameters in the same way as newfs so that
1005 	 * newfs and mkfs would result in the same file system layout
1006 	 * for EFI labelled disks. Do this only in the absence of user
1007 	 * specified values for these parameters.
1008 	 */
1009 	if (label_type == LABEL_TYPE_EFI) {
1010 		if (apc_flag == RC_DEFAULT) apc = 0;
1011 		if (nrpos_flag == RC_DEFAULT) nrpos = 1;
1012 		if (ntrack_flag == RC_DEFAULT) ntrack = DEF_TRACKS_EFI;
1013 		if (rps_flag == RC_DEFAULT) rps = DEFHZ;
1014 		if (nsect_flag == RC_DEFAULT) nsect = DEF_SECTORS_EFI;
1015 	}
1016 
1017 	if ((maxcontig_flag == RC_DEFAULT) || (tmpmaxcontig == -1) ||
1018 	    (maxcontig == -1)) {
1019 		long maxtrax = get_max_track_size(fsi);
1020 		maxcontig = maxtrax / bsize;
1021 
1022 	} else {
1023 		maxcontig = tmpmaxcontig;
1024 	}
1025 	dprintf(("DeBuG maxcontig : %ld\n", maxcontig));
1026 
1027 	if (rotdelay == -1) {	/* default by newfs and mkfs */
1028 		rotdelay = ROTDELAY;
1029 	}
1030 
1031 	if (cpg_flag == RC_DEFAULT) { /* If not explicity set, use default */
1032 		cpg = DESCPG;
1033 	}
1034 	dprintf(("DeBuG cpg : %ld\n", cpg));
1035 
1036 	/*
1037 	 * Now that we have the semi-sane args, either positional, via -o,
1038 	 * or by defaulting, handle inter-dependencies and range checks.
1039 	 */
1040 
1041 	/*
1042 	 * Settle the file system block size first, since it's a fixed
1043 	 * parameter once set and so many other parameters, including
1044 	 * max_fssize, depend on it.
1045 	 */
1046 	range_check(&bsize, "bsize", MINBSIZE, MAXBSIZE, DESBLKSIZE,
1047 	    bsize_flag);
1048 
1049 	if (!POWEROF2(bsize)) {
1050 		(void) fprintf(stderr,
1051 		    gettext("block size must be a power of 2, not %ld\n"),
1052 		    bsize);
1053 		bsize = DESBLKSIZE;
1054 		(void) fprintf(stderr,
1055 		    gettext("mkfs: bsize reset to default %ld\n"),
1056 		    bsize);
1057 	}
1058 
1059 	if (fssize_db > max_fssize && validate_size(fsi, fssize_db)) {
1060 		(void) fprintf(stderr, gettext(
1061 		    "Warning: the requested size of this file system\n"
1062 		    "(%lld sectors) is greater than the size of the\n"
1063 		    "device reported by the driver (%lld sectors).\n"
1064 		    "However, a read of the device at the requested size\n"
1065 		    "does succeed, so the requested size will be used.\n"),
1066 		    fssize_db, max_fssize);
1067 		max_fssize = fssize_db;
1068 	}
1069 	/*
1070 	 * Since the maximum allocatable unit (the frag) must be less than
1071 	 * or equal to bsize, and the number of frags must be less than or
1072 	 * equal to INT_MAX, the total size of the file system (in
1073 	 * bytes) must be less than or equal to bsize * INT_MAX.
1074 	 */
1075 
1076 	if (max_fssize > ((diskaddr_t)bsize/DEV_BSIZE) * INT_MAX)
1077 		max_fssize = ((diskaddr_t)bsize/DEV_BSIZE) * INT_MAX;
1078 
1079 	range_check_64(&fssize_db, "size", 1024LL, max_fssize, max_fssize, 1);
1080 
1081 	if (fssize_db >= SECTORS_PER_TERABYTE) {
1082 		mtb = 'y';
1083 		if (!in_64bit_mode()) {
1084 			(void) fprintf(stderr, gettext(
1085 "mkfs:  Warning: Creating a file system greater than 1 terabyte on a\n"
1086 "       system running a 32-bit kernel.  This file system will not be\n"
1087 "       accessible until the system is rebooted with a 64-bit kernel.\n"));
1088 		}
1089 	}
1090 	dprintf(("DeBuG mtb : %c\n", mtb));
1091 
1092 	/*
1093 	 * With newer and much larger disks, the newfs(1M) and mkfs_ufs(1M)
1094 	 * commands had problems in correctly handling the "native" geometries
1095 	 * for various storage devices.
1096 	 *
1097 	 * To handle the new age disks, mkfs_ufs(1M) will use the EFI style
1098 	 * for non-EFI disks that are larger than the CHS addressing limit
1099 	 * ( > 8GB approx ) and ignore the disk geometry information for
1100 	 * these drives. This is what is currently done for multi-terrabyte
1101 	 * filesystems on EFI disks.
1102 	 *
1103 	 * However if the user asked for a specific layout by supplying values
1104 	 * for even one of the three parameters (nsect, ntrack, cpg), honour
1105 	 * the user supplied parameters.
1106 	 *
1107 	 * Choosing EFI style or native geometry style can make a lot of
1108 	 * difference, because the size of a cylinder group is dependent on
1109 	 * this choice. This in turn means that the position of alternate
1110 	 * superblocks varies depending on the style chosen. It is not
1111 	 * necessary that all disks of size > CHSLIMIT have EFI style layout.
1112 	 * There can be disks which are > CHSLIMIT size, but have native
1113 	 * geometry style layout, thereby warranting the need for alternate
1114 	 * logic in superblock detection.
1115 	 */
1116 	if (mtb != 'y' && (ntrack == -1 || GROW_WITH_DEFAULT_TRAK ||
1117 	    DEFAULT_SECT_TRAK_CPG)) {
1118 		/*
1119 		 * "-1" indicates that we were called from newfs and ntracks
1120 		 * was not specified in newfs command line. Calculate nsect
1121 		 * and ntrack in the same manner as newfs.
1122 		 *
1123 		 * This is required because, the defaults for nsect and ntrack
1124 		 * is hardcoded in mkfs, whereas to generate the alternate
1125 		 * superblock locations for the -N option, there is a need for
1126 		 * the geometry based values that newfs would have arrived at.
1127 		 * Newfs would have arrived at these values as below.
1128 		 */
1129 		if (label_type == LABEL_TYPE_EFI ||
1130 		    label_type == LABEL_TYPE_OTHER) {
1131 			use_efi_dflts = 1;
1132 			retry = 1;
1133 		} else if (ioctl(fsi, DKIOCGGEOM, &dkg)) {
1134 			dprintf(("%s: Unable to read Disk geometry", fsys));
1135 			perror(gettext("Unable to read Disk geometry"));
1136 			lockexit(32);
1137 		} else {
1138 			nsect = dkg.dkg_nsect;
1139 			ntrack = dkg.dkg_nhead;
1140 #ifdef i386	/* Bug 1170182 */
1141 			if (ntrack > 32 && (ntrack % 16) != 0) {
1142 				ntrack -= (ntrack % 16);
1143 			}
1144 #endif
1145 			if (ioctl(fsi, DKIOCREMOVABLE, &isremovable)) {
1146 				dprintf(("DeBuG Unable to determine if %s is"
1147 				    " Removable Media. Proceeding with system"
1148 				    " determined parameters.\n", fsys));
1149 				isremovable = 0;
1150 			}
1151 			if (ioctl(fsi, DKIOCHOTPLUGGABLE, &ishotpluggable)) {
1152 				dprintf(("DeBuG Unable to determine if %s is"
1153 				    " Hotpluggable Media. Proceeding with "
1154 				    "system determined parameters.\n", fsys));
1155 				ishotpluggable = 0;
1156 			}
1157 			if ((((diskaddr_t)dkg.dkg_ncyl * dkg.dkg_nhead *
1158 			    dkg.dkg_nsect) > CHSLIMIT) || isremovable ||
1159 			    ishotpluggable) {
1160 				use_efi_dflts = 1;
1161 				retry = 1;
1162 			}
1163 		}
1164 	}
1165 	dprintf(("DeBuG CHSLIMIT = %d geom = %llu\n", CHSLIMIT,
1166 	    (diskaddr_t)dkg.dkg_ncyl * dkg.dkg_nhead * dkg.dkg_nsect));
1167 	dprintf(("DeBuG label_type = %d isremovable = %d ishotpluggable = %d "
1168 	    "use_efi_dflts = %d\n", label_type, isremovable, ishotpluggable,
1169 	    use_efi_dflts));
1170 
1171 	/*
1172 	 * For the newfs -N case, even if the disksize is > CHSLIMIT, do not
1173 	 * blindly follow EFI style. If the fs_version indicates a geometry
1174 	 * based layout, try that one first. If it fails we can always try the
1175 	 * other logic.
1176 	 *
1177 	 * If we were called from growfs, we will have a problem if we mix
1178 	 * and match the filesystem creation and growth styles. For example,
1179 	 * if we create using EFI style, we have to also grow using EFI
1180 	 * style. So follow the style indicated by the fs_version.
1181 	 *
1182 	 * Read and verify the primary superblock. If it looks sane, use the
1183 	 * fs_version from the superblock. If the primary superblock does
1184 	 * not look good, read and verify the first alternate superblock at
1185 	 * ALTSB. Use the fs_version to decide whether to use the
1186 	 * EFI style logic or the old geometry based logic to calculate
1187 	 * the alternate superblock locations.
1188 	 */
1189 	if ((Nflag && use_efi_dflts) || (grow)) {
1190 		if (grow && ntrack_flag != RC_DEFAULT)
1191 			goto start_fs_creation;
1192 		rdfs((diskaddr_t)(SBOFF / sectorsize), (int)sbsize,
1193 		    (char *)&altsblock);
1194 		ret = checksblock(altsblock, 1);
1195 
1196 		if (!ret) {
1197 			if (altsblock.fs_magic == MTB_UFS_MAGIC) {
1198 				mtb = 'y';
1199 				goto start_fs_creation;
1200 			}
1201 			use_efi_dflts = (altsblock.fs_version ==
1202 			    UFS_EFISTYLE4NONEFI_VERSION_2) ? 1 : 0;
1203 		} else {
1204 			/*
1205 			 * The primary superblock didn't help in determining
1206 			 * the fs_version. Try the first alternate superblock.
1207 			 */
1208 			dprintf(("DeBuG checksblock() failed - error : %d"
1209 			    " for sb : %d\n", ret, SBOFF/sectorsize));
1210 			rdfs((diskaddr_t)ALTSB, (int)sbsize,
1211 			    (char *)&altsblock);
1212 			ret = checksblock(altsblock, 1);
1213 
1214 			if (!ret) {
1215 				if (altsblock.fs_magic == MTB_UFS_MAGIC) {
1216 					mtb = 'y';
1217 					goto start_fs_creation;
1218 				}
1219 				use_efi_dflts = (altsblock.fs_version ==
1220 				    UFS_EFISTYLE4NONEFI_VERSION_2) ? 1 : 0;
1221 			}
1222 			dprintf(("DeBuG checksblock() returned : %d"
1223 			    " for sb : %d\n", ret, ALTSB));
1224 		}
1225 	}
1226 
1227 	geom_nsect = nsect;
1228 	geom_ntrack = ntrack;
1229 	geom_cpg = cpg;
1230 	dprintf(("DeBuG geom_nsect=%d, geom_ntrack=%d, geom_cpg=%d\n",
1231 	    geom_nsect, geom_ntrack, geom_cpg));
1232 
1233 start_fs_creation:
1234 retry_alternate_logic:
1235 	invalid_sb_cnt = 0;
1236 	cg_too_small = 0;
1237 	if (use_efi_dflts) {
1238 		nsect = DEF_SECTORS_EFI;
1239 		ntrack = DEF_TRACKS_EFI;
1240 		cpg = DESCPG;
1241 		dprintf(("\nDeBuG Using EFI defaults\n"));
1242 	} else {
1243 		nsect = geom_nsect;
1244 		ntrack = geom_ntrack;
1245 		cpg = geom_cpg;
1246 		dprintf(("\nDeBuG Using Geometry\n"));
1247 		/*
1248 		 * 32K based on max block size of 64K, and rotational layout
1249 		 * test of nsect <= (256 * sectors/block).  Current block size
1250 		 * limit is not 64K, but it's growing soon.
1251 		 */
1252 		range_check(&nsect, "nsect", 1, 32768, DFLNSECT, nsect_flag);
1253 		/*
1254 		 * ntrack is the number of tracks per cylinder.
1255 		 * The ntrack value must be between 1 and the total number of
1256 		 * sectors in the file system.
1257 		 */
1258 		range_check(&ntrack, "ntrack", 1,
1259 		    fssize_db > INT_MAX ? INT_MAX : (uint32_t)fssize_db,
1260 		    DFLNTRAK, ntrack_flag);
1261 	}
1262 
1263 	range_check(&apc, "apc", 0, nsect - 1, 0, apc_flag);
1264 
1265 	if (mtb == 'y')
1266 		fragsize = bsize;
1267 
1268 	range_check(&fragsize, "fragsize", sectorsize, bsize,
1269 	    MAX(bsize / MAXFRAG, MIN(DESFRAGSIZE, bsize)), fragsize_flag);
1270 
1271 	if ((bsize / MAXFRAG) > fragsize) {
1272 		(void) fprintf(stderr, gettext(
1273 "fragment size %ld is too small, minimum with block size %ld is %ld\n"),
1274 		    fragsize, bsize, bsize / MAXFRAG);
1275 		(void) fprintf(stderr,
1276 		    gettext("mkfs: fragsize reset to minimum %ld\n"),
1277 		    bsize / MAXFRAG);
1278 		fragsize = bsize / MAXFRAG;
1279 	}
1280 
1281 	if (!POWEROF2(fragsize)) {
1282 		(void) fprintf(stderr,
1283 		    gettext("fragment size must be a power of 2, not %ld\n"),
1284 		    fragsize);
1285 		fragsize = MAX(bsize / MAXFRAG, MIN(DESFRAGSIZE, bsize));
1286 		(void) fprintf(stderr,
1287 		    gettext("mkfs: fragsize reset to %ld\n"),
1288 		    fragsize);
1289 	}
1290 
1291 	/* At this point, bsize must be >= fragsize, so no need to check it */
1292 
1293 	if (bsize < PAGESIZE) {
1294 		(void) fprintf(stderr, gettext(
1295 		    "WARNING: filesystem block size (%ld) is smaller than "
1296 		    "memory page size (%ld).\nResulting filesystem can not be "
1297 		    "mounted on this system.\n\n"),
1298 		    bsize, (long)PAGESIZE);
1299 	}
1300 
1301 	range_check(&rps, "rps", 1, 1000, DEFHZ, rps_flag);
1302 	range_check(&minfree, "free", 0, 99, MINFREE, minfree_flag);
1303 	range_check(&nrpos, "nrpos", 1, nsect, MIN(nsect, NRPOS), nrpos_flag);
1304 
1305 	/*
1306 	 * nbpi is variable, but 2MB seems a reasonable upper limit,
1307 	 * as 4MB tends to cause problems (using otherwise-default
1308 	 * parameters).  The true limit is where we end up with one
1309 	 * inode per cylinder group.  If this file system is being
1310 	 * configured for multi-terabyte access, nbpi must be at least 1MB.
1311 	 */
1312 	if (mtb == 'y' && nbpi < MTB_NBPI) {
1313 		if (nbpi_flag != RC_DEFAULT)
1314 			(void) fprintf(stderr, gettext("mkfs: bad value for "
1315 			    "nbpi: must be at least 1048576 for multi-terabyte,"
1316 			    " nbpi reset to default 1048576\n"));
1317 		nbpi = MTB_NBPI;
1318 	}
1319 
1320 	if (mtb == 'y')
1321 		range_check(&nbpi, "nbpi", MTB_NBPI, 2 * MB, MTB_NBPI,
1322 		    nbpi_flag);
1323 	else
1324 		range_check(&nbpi, "nbpi", DEV_BSIZE, 2 * MB, NBPI, nbpi_flag);
1325 
1326 	/*
1327 	 * maxcpg is another variably-limited parameter.  Calculate
1328 	 * the limit based on what we've got for its dependent
1329 	 * variables.  Effectively, it's how much space is left in the
1330 	 * superblock after all the other bits are accounted for.  We
1331 	 * only fill in sblock fields so we can use MAXIpG.
1332 	 *
1333 	 * If the calculation of maxcpg below (for the mtb == 'n'
1334 	 * case) is changed, update newfs as well.
1335 	 *
1336 	 * For old-style, non-MTB format file systems, use the old
1337 	 * algorithm for calculating the maximum cylinder group size,
1338 	 * even though it limits the cylinder group more than necessary.
1339 	 * Since layout can affect performance, we don't want to change
1340 	 * the default layout for non-MTB file systems at this time.
1341 	 * However, for MTB file systems, use the new maxcpg calculation,
1342 	 * which really maxes out the cylinder group size.
1343 	 */
1344 
1345 	sblock.fs_bsize = bsize;
1346 	sblock.fs_inopb = sblock.fs_bsize / sizeof (struct dinode);
1347 
1348 	if (mtb == 'n') {
1349 		maxcpg = (bsize - sizeof (struct cg) -
1350 		    howmany(MAXIpG(&sblock), NBBY)) /
1351 		    (sizeof (long) + nrpos * sizeof (short) +
1352 		    nsect / (MAXFRAG * NBBY));
1353 	} else {
1354 		maxcpg = compute_maxcpg(bsize, fragsize, nbpi, nrpos,
1355 		    nsect * ntrack);
1356 	}
1357 
1358 	dprintf(("DeBuG cpg : %ld\n", cpg));
1359 	/*
1360 	 * Increase the cpg to maxcpg if either newfs was invoked
1361 	 * with -T option or if mkfs wants to create a mtb file system
1362 	 * and if the user has not specified the cpg.
1363 	 */
1364 	if (cpg == -1 || (mtb == 'y' && cpg_flag == RC_DEFAULT))
1365 		cpg = maxcpg;
1366 	dprintf(("DeBuG cpg : %ld\n", cpg));
1367 
1368 	/*
1369 	 * mincpg is variable in complex ways, so we really can't
1370 	 * do a sane lower-end limit check at this point.
1371 	 */
1372 	range_check(&cpg, "cgsize", 1, maxcpg, MIN(maxcpg, DESCPG), cpg_flag);
1373 
1374 	/*
1375 	 * get the controller info
1376 	 */
1377 	islog = 0;
1378 	islogok = 0;
1379 	waslog = 0;
1380 
1381 	/*
1382 	 * Do not grow the file system, but print on stdout the maximum
1383 	 * size in sectors to which the file system can be increased.
1384 	 * The calculated size is limited by fssize_db.
1385 	 * Note that we don't lock the filesystem and therefore under rare
1386 	 * conditions (the filesystem is mounted, the free block count is
1387 	 * almost zero, and the superuser is still changing it) the calculated
1388 	 * size can be imprecise.
1389 	 */
1390 	if (Pflag) {
1391 		(void) printf("%llu\n", probe_summaryinfo());
1392 		exit(0);
1393 	}
1394 
1395 	/*
1396 	 * If we're growing an existing filesystem, then we're about
1397 	 * to start doing things that can require recovery efforts if
1398 	 * we get interrupted, so make sure we get a chance to do so.
1399 	 */
1400 	if (grow) {
1401 		sigact.sa_handler = recover_from_sigint;
1402 		sigemptyset(&sigact.sa_mask);
1403 		sigact.sa_flags = SA_RESTART;
1404 
1405 		if (sigaction(SIGINT, &sigact, (struct sigaction *)NULL) < 0) {
1406 			perror(gettext("Could not register SIGINT handler"));
1407 			lockexit(3);
1408 		}
1409 	}
1410 
1411 	if (!Nflag) {
1412 		/*
1413 		 * Check if MNTTAB is trustable
1414 		 */
1415 		if (statvfs64(MNTTAB, &fs) < 0) {
1416 			(void) fprintf(stderr, gettext("can't statvfs %s\n"),
1417 			    MNTTAB);
1418 			exit(32);
1419 		}
1420 
1421 		if (strcmp(MNTTYPE_MNTFS, fs.f_basetype) != 0) {
1422 			(void) fprintf(stderr, gettext(
1423 			    "%s file system type is not %s, can't mkfs\n"),
1424 			    MNTTAB, MNTTYPE_MNTFS);
1425 			exit(32);
1426 		}
1427 
1428 		special = getfullblkname(fsys);
1429 		checkdev(fsys, special);
1430 
1431 		/*
1432 		 * If we found the block device name,
1433 		 * then check the mount table.
1434 		 * if mounted, and growing write lock the file system
1435 		 *
1436 		 */
1437 		if ((special != NULL) && (*special != '\0')) {
1438 			if ((mnttab = fopen(MNTTAB, "r")) == NULL) {
1439 				(void) fprintf(stderr, gettext(
1440 				    "can't open %s\n"), MNTTAB);
1441 				exit(32);
1442 			}
1443 			while ((getmntent(mnttab, &mntp)) == 0) {
1444 				if (grow) {
1445 					checkmount(&mntp, special);
1446 					continue;
1447 				}
1448 				if (strcmp(special, mntp.mnt_special) == 0) {
1449 					(void) fprintf(stderr, gettext(
1450 					    "%s is mounted, can't mkfs\n"),
1451 					    special);
1452 					exit(32);
1453 				}
1454 			}
1455 			(void) fclose(mnttab);
1456 		}
1457 
1458 		if (directory && (ismounted == 0)) {
1459 			(void) fprintf(stderr, gettext("%s is not mounted\n"),
1460 			    special);
1461 			lockexit(32);
1462 		}
1463 
1464 		fso = (grow) ? open64(fsys, O_WRONLY) : creat64(fsys, 0666);
1465 		if (fso < 0) {
1466 			saverr = errno;
1467 			(void) fprintf(stderr,
1468 			    gettext("%s: cannot create: %s\n"),
1469 			    fsys, strerror(saverr));
1470 			lockexit(32);
1471 		}
1472 
1473 	} else {
1474 
1475 		/*
1476 		 * For the -N case, a file descriptor is needed for the llseek()
1477 		 * in wtfs(). See the comment in wtfs() for more information.
1478 		 *
1479 		 * Get a file descriptor that's read-only so that this code
1480 		 * doesn't accidentally write to the file.
1481 		 */
1482 		fso = open64(fsys, O_RDONLY);
1483 		if (fso < 0) {
1484 			saverr = errno;
1485 			(void) fprintf(stderr, gettext("%s: cannot open: %s\n"),
1486 			    fsys, strerror(saverr));
1487 			lockexit(32);
1488 		}
1489 	}
1490 
1491 	/*
1492 	 * Check the media sector size
1493 	 */
1494 	if (ioctl(fso, DKIOCGMEDIAINFO, &dkminfo) != -1) {
1495 		if (dkminfo.dki_lbsize != 0 &&
1496 		    POWEROF2(dkminfo.dki_lbsize / DEV_BSIZE) &&
1497 		    dkminfo.dki_lbsize != DEV_BSIZE) {
1498 			fprintf(stderr,
1499 			    gettext("The device sector size %u is not "
1500 			    "supported by ufs!\n"), dkminfo.dki_lbsize);
1501 			(void) close(fso);
1502 			exit(1);
1503 		}
1504 	}
1505 
1506 	/*
1507 	 * seed random # generator (for ic_generation)
1508 	 */
1509 #ifdef MKFS_DEBUG
1510 	srand48(12962);	/* reproducible results */
1511 #else
1512 	srand48((long)(time((time_t *)NULL) + getpid()));
1513 #endif
1514 
1515 	if (grow) {
1516 		growinit(fsys);
1517 		goto grow00;
1518 	}
1519 
1520 	/*
1521 	 * Validate the given file system size.
1522 	 * Verify that its last block can actually be accessed.
1523 	 *
1524 	 * Note: it's ok to use sblock as a buffer because it is immediately
1525 	 * overwritten by the rdfs() of the superblock in the next line.
1526 	 *
1527 	 * ToDo: Because the size checking is done in rdfs()/wtfs(), the
1528 	 * error message for specifying an illegal size is very unfriendly.
1529 	 * In the future, one could replace the rdfs()/wtfs() calls
1530 	 * below with in-line calls to read() or write(). This allows better
1531 	 * error messages to be put in place.
1532 	 */
1533 	rdfs(fssize_db - 1, (int)sectorsize, (char *)&sblock);
1534 
1535 	/*
1536 	 * make the fs unmountable
1537 	 */
1538 	rdfs((diskaddr_t)(SBOFF / sectorsize), (int)sbsize, (char *)&sblock);
1539 	sblock.fs_magic = -1;
1540 	sblock.fs_clean = FSBAD;
1541 	sblock.fs_state = FSOKAY - sblock.fs_time;
1542 	wtfs((diskaddr_t)(SBOFF / sectorsize), (int)sbsize, (char *)&sblock);
1543 	bzero(&sblock, (size_t)sbsize);
1544 
1545 	sblock.fs_nsect = nsect;
1546 	sblock.fs_ntrak = ntrack;
1547 
1548 	/*
1549 	 * Validate specified/determined spc
1550 	 * and calculate minimum cylinders per group.
1551 	 */
1552 
1553 	/*
1554 	 * sectors/cyl = tracks/cyl * sectors/track
1555 	 */
1556 	sblock.fs_spc = sblock.fs_ntrak * sblock.fs_nsect;
1557 
1558 grow00:
1559 	if (apc_flag) {
1560 		sblock.fs_spc -= apc;
1561 	}
1562 	/*
1563 	 * Have to test for this separately from apc_flag, due to
1564 	 * the growfs case....
1565 	 */
1566 	if (sblock.fs_spc != sblock.fs_ntrak * sblock.fs_nsect) {
1567 		spc_flag = 1;
1568 	}
1569 	if (grow)
1570 		goto grow10;
1571 
1572 	sblock.fs_nrpos = nrpos;
1573 	sblock.fs_bsize = bsize;
1574 	sblock.fs_fsize = fragsize;
1575 	sblock.fs_minfree = minfree;
1576 
1577 grow10:
1578 	if (nbpi < sblock.fs_fsize) {
1579 		(void) fprintf(stderr, gettext(
1580 		"warning: wasteful data byte allocation / inode (nbpi):\n"));
1581 		(void) fprintf(stderr, gettext(
1582 		    "%ld smaller than allocatable fragment size of %d\n"),
1583 		    nbpi, sblock.fs_fsize);
1584 	}
1585 	if (grow)
1586 		goto grow20;
1587 
1588 	if (opt == 's')
1589 		sblock.fs_optim = FS_OPTSPACE;
1590 	else
1591 		sblock.fs_optim = FS_OPTTIME;
1592 
1593 	sblock.fs_bmask = ~(sblock.fs_bsize - 1);
1594 	sblock.fs_fmask = ~(sblock.fs_fsize - 1);
1595 	/*
1596 	 * Planning now for future expansion.
1597 	 */
1598 #if defined(_BIG_ENDIAN)
1599 		sblock.fs_qbmask.val[0] = 0;
1600 		sblock.fs_qbmask.val[1] = ~sblock.fs_bmask;
1601 		sblock.fs_qfmask.val[0] = 0;
1602 		sblock.fs_qfmask.val[1] = ~sblock.fs_fmask;
1603 #endif
1604 #if defined(_LITTLE_ENDIAN)
1605 		sblock.fs_qbmask.val[0] = ~sblock.fs_bmask;
1606 		sblock.fs_qbmask.val[1] = 0;
1607 		sblock.fs_qfmask.val[0] = ~sblock.fs_fmask;
1608 		sblock.fs_qfmask.val[1] = 0;
1609 #endif
1610 	for (sblock.fs_bshift = 0, i = sblock.fs_bsize; i > 1; i >>= 1)
1611 		sblock.fs_bshift++;
1612 	for (sblock.fs_fshift = 0, i = sblock.fs_fsize; i > 1; i >>= 1)
1613 		sblock.fs_fshift++;
1614 	sblock.fs_frag = numfrags(&sblock, sblock.fs_bsize);
1615 	for (sblock.fs_fragshift = 0, i = sblock.fs_frag; i > 1; i >>= 1)
1616 		sblock.fs_fragshift++;
1617 	if (sblock.fs_frag > MAXFRAG) {
1618 		(void) fprintf(stderr, gettext(
1619 	"fragment size %d is too small, minimum with block size %d is %d\n"),
1620 		    sblock.fs_fsize, sblock.fs_bsize,
1621 		    sblock.fs_bsize / MAXFRAG);
1622 		lockexit(32);
1623 	}
1624 	sblock.fs_nindir = sblock.fs_bsize / sizeof (daddr32_t);
1625 	sblock.fs_inopb = sblock.fs_bsize / sizeof (struct dinode);
1626 	sblock.fs_nspf = sblock.fs_fsize / sectorsize;
1627 	for (sblock.fs_fsbtodb = 0, i = NSPF(&sblock); i > 1; i >>= 1)
1628 		sblock.fs_fsbtodb++;
1629 
1630 	/*
1631 	 * Compute the super-block, cylinder group, and inode blocks.
1632 	 * Note that these "blkno" are really fragment addresses.
1633 	 * For example, on an 8K/1K (block/fragment) system, fs_sblkno is 16,
1634 	 * fs_cblkno is 24, and fs_iblkno is 32. This is why CGSIZE is so
1635 	 * important: only 1 FS block is allocated for the cg struct (fragment
1636 	 * numbers 24 through 31).
1637 	 */
1638 	sblock.fs_sblkno =
1639 	    roundup(howmany(bbsize + sbsize, sblock.fs_fsize), sblock.fs_frag);
1640 	sblock.fs_cblkno = (daddr32_t)(sblock.fs_sblkno +
1641 	    roundup(howmany(sbsize, sblock.fs_fsize), sblock.fs_frag));
1642 	sblock.fs_iblkno = sblock.fs_cblkno + sblock.fs_frag;
1643 
1644 	sblock.fs_cgoffset = roundup(
1645 	    howmany(sblock.fs_nsect, NSPF(&sblock)), sblock.fs_frag);
1646 	for (sblock.fs_cgmask = -1, i = sblock.fs_ntrak; i > 1; i >>= 1)
1647 		sblock.fs_cgmask <<= 1;
1648 	if (!POWEROF2(sblock.fs_ntrak))
1649 		sblock.fs_cgmask <<= 1;
1650 	/*
1651 	 * Validate specified/determined spc
1652 	 * and calculate minimum cylinders per group.
1653 	 */
1654 
1655 	for (sblock.fs_cpc = NSPB(&sblock), i = sblock.fs_spc;
1656 	    sblock.fs_cpc > 1 && (i & 1) == 0;
1657 	    sblock.fs_cpc >>= 1, i >>= 1)
1658 		/* void */;
1659 	mincpc = sblock.fs_cpc;
1660 
1661 	/* if these calculations are changed, check dump_fscmd also */
1662 	bpcg = (uint64_t)sblock.fs_spc * sectorsize;
1663 	inospercg = (uint64_t)roundup(bpcg / sizeof (struct dinode),
1664 	    INOPB(&sblock));
1665 	if (inospercg > MAXIpG(&sblock))
1666 		inospercg = MAXIpG(&sblock);
1667 	used = (uint64_t)(sblock.fs_iblkno + inospercg /
1668 	    INOPF(&sblock)) * NSPF(&sblock);
1669 	mincpgcnt = (long)howmany((uint64_t)sblock.fs_cgoffset *
1670 	    (~sblock.fs_cgmask) + used, sblock.fs_spc);
1671 	mincpg = roundup(mincpgcnt, mincpc);
1672 	/*
1673 	 * Insure that cylinder group with mincpg has enough space
1674 	 * for block maps
1675 	 */
1676 	sblock.fs_cpg = mincpg;
1677 	sblock.fs_ipg = (int32_t)inospercg;
1678 	mapcramped = 0;
1679 
1680 	/*
1681 	 * Make sure the cg struct fits within the file system block.
1682 	 * Use larger block sizes until it fits
1683 	 */
1684 	while (CGSIZE(&sblock) > sblock.fs_bsize) {
1685 		mapcramped = 1;
1686 		if (sblock.fs_bsize < MAXBSIZE) {
1687 			sblock.fs_bsize <<= 1;
1688 			if ((i & 1) == 0) {
1689 				i >>= 1;
1690 			} else {
1691 				sblock.fs_cpc <<= 1;
1692 				mincpc <<= 1;
1693 				mincpg = roundup(mincpgcnt, mincpc);
1694 				sblock.fs_cpg = mincpg;
1695 			}
1696 			sblock.fs_frag <<= 1;
1697 			sblock.fs_fragshift += 1;
1698 			if (sblock.fs_frag <= MAXFRAG)
1699 				continue;
1700 		}
1701 
1702 		/*
1703 		 * Looped far enough. The fragment is now as large as the
1704 		 * filesystem block!
1705 		 */
1706 		if (sblock.fs_fsize == sblock.fs_bsize) {
1707 			(void) fprintf(stderr, gettext(
1708 		    "There is no block size that can support this disk\n"));
1709 			lockexit(32);
1710 		}
1711 
1712 		/*
1713 		 * Try a larger fragment. Double the fragment size.
1714 		 */
1715 		sblock.fs_frag >>= 1;
1716 		sblock.fs_fragshift -= 1;
1717 		sblock.fs_fsize <<= 1;
1718 		sblock.fs_nspf <<= 1;
1719 	}
1720 	/*
1721 	 * Insure that cylinder group with mincpg has enough space for inodes
1722 	 */
1723 	inodecramped = 0;
1724 	used *= sectorsize;
1725 	nbytes64 = (uint64_t)mincpg * bpcg - used;
1726 	inospercg = (uint64_t)roundup((nbytes64 / nbpi), INOPB(&sblock));
1727 	sblock.fs_ipg = (int32_t)inospercg;
1728 	while (inospercg > MAXIpG(&sblock)) {
1729 		inodecramped = 1;
1730 		if (mincpc == 1 || sblock.fs_frag == 1 ||
1731 		    sblock.fs_bsize == MINBSIZE)
1732 			break;
1733 		nbytes64 = (uint64_t)mincpg * bpcg - used;
1734 		(void) fprintf(stderr,
1735 		    gettext("With a block size of %d %s %lu\n"),
1736 		    sblock.fs_bsize, gettext("minimum bytes per inode is"),
1737 		    (uint32_t)(nbytes64 / MAXIpG(&sblock) + 1));
1738 		sblock.fs_bsize >>= 1;
1739 		sblock.fs_frag >>= 1;
1740 		sblock.fs_fragshift -= 1;
1741 		mincpc >>= 1;
1742 		sblock.fs_cpg = roundup(mincpgcnt, mincpc);
1743 		if (CGSIZE(&sblock) > sblock.fs_bsize) {
1744 			sblock.fs_bsize <<= 1;
1745 			break;
1746 		}
1747 		mincpg = sblock.fs_cpg;
1748 		nbytes64 = (uint64_t)mincpg * bpcg - used;
1749 		inospercg = (uint64_t)roundup((nbytes64 / nbpi),
1750 		    INOPB(&sblock));
1751 		sblock.fs_ipg = (int32_t)inospercg;
1752 	}
1753 	if (inodecramped) {
1754 		if (inospercg > MAXIpG(&sblock)) {
1755 			nbytes64 = (uint64_t)mincpg * bpcg - used;
1756 			(void) fprintf(stderr, gettext(
1757 			    "Minimum bytes per inode is %d\n"),
1758 			    (uint32_t)(nbytes64 / MAXIpG(&sblock) + 1));
1759 		} else if (!mapcramped) {
1760 			(void) fprintf(stderr, gettext(
1761 	    "With %ld bytes per inode, minimum cylinders per group is %ld\n"),
1762 			    nbpi, mincpg);
1763 		}
1764 	}
1765 	if (mapcramped) {
1766 		(void) fprintf(stderr, gettext(
1767 		    "With %d sectors per cylinder, minimum cylinders "
1768 		    "per group is %ld\n"),
1769 		    sblock.fs_spc, mincpg);
1770 	}
1771 	if (inodecramped || mapcramped) {
1772 		/*
1773 		 * To make this at least somewhat comprehensible in
1774 		 * the world of i18n, figure out what we're going to
1775 		 * say and then say it all at one time.  The days of
1776 		 * needing to scrimp on string space are behind us....
1777 		 */
1778 		if ((sblock.fs_bsize != bsize) &&
1779 		    (sblock.fs_fsize != fragsize)) {
1780 			(void) fprintf(stderr, gettext(
1781 	    "This requires the block size to be changed from %ld to %d\n"
1782 	    "and the fragment size to be changed from %ld to %d\n"),
1783 			    bsize, sblock.fs_bsize,
1784 			    fragsize, sblock.fs_fsize);
1785 		} else if (sblock.fs_bsize != bsize) {
1786 			(void) fprintf(stderr, gettext(
1787 	    "This requires the block size to be changed from %ld to %d\n"),
1788 			    bsize, sblock.fs_bsize);
1789 		} else if (sblock.fs_fsize != fragsize) {
1790 			(void) fprintf(stderr, gettext(
1791 	    "This requires the fragment size to be changed from %ld to %d\n"),
1792 			    fragsize, sblock.fs_fsize);
1793 		} else {
1794 			(void) fprintf(stderr, gettext(
1795 	    "Unable to make filesystem fit with the given constraints\n"));
1796 		}
1797 		(void) fprintf(stderr, gettext(
1798 		    "Please re-run mkfs with corrected parameters\n"));
1799 		lockexit(32);
1800 	}
1801 	/*
1802 	 * Calculate the number of cylinders per group
1803 	 */
1804 	sblock.fs_cpg = cpg;
1805 	if (sblock.fs_cpg % mincpc != 0) {
1806 		(void) fprintf(stderr, gettext(
1807 		    "Warning: cylinder groups must have a multiple "
1808 		    "of %ld cylinders with the given\n         parameters\n"),
1809 		    mincpc);
1810 		sblock.fs_cpg = roundup(sblock.fs_cpg, mincpc);
1811 		(void) fprintf(stderr, gettext("Rounded cgsize up to %d\n"),
1812 		    sblock.fs_cpg);
1813 	}
1814 	/*
1815 	 * Must insure there is enough space for inodes
1816 	 */
1817 	/* if these calculations are changed, check dump_fscmd also */
1818 	nbytes64 = (uint64_t)sblock.fs_cpg * bpcg - used;
1819 	sblock.fs_ipg = roundup((uint32_t)(nbytes64 / nbpi), INOPB(&sblock));
1820 
1821 	/*
1822 	 * Slim down cylinders per group, until the inodes can fit.
1823 	 */
1824 	while (sblock.fs_ipg > MAXIpG(&sblock)) {
1825 		inodecramped = 1;
1826 		sblock.fs_cpg -= mincpc;
1827 		nbytes64 = (uint64_t)sblock.fs_cpg * bpcg - used;
1828 		sblock.fs_ipg = roundup((uint32_t)(nbytes64 / nbpi),
1829 		    INOPB(&sblock));
1830 	}
1831 	/*
1832 	 * Must insure there is enough space to hold block map.
1833 	 * Cut down on cylinders per group, until the cg struct fits in a
1834 	 * filesystem block.
1835 	 */
1836 	while (CGSIZE(&sblock) > sblock.fs_bsize) {
1837 		mapcramped = 1;
1838 		sblock.fs_cpg -= mincpc;
1839 		nbytes64 = (uint64_t)sblock.fs_cpg * bpcg - used;
1840 		sblock.fs_ipg = roundup((uint32_t)(nbytes64 / nbpi),
1841 		    INOPB(&sblock));
1842 	}
1843 	sblock.fs_fpg = (sblock.fs_cpg * sblock.fs_spc) / NSPF(&sblock);
1844 	if ((sblock.fs_cpg * sblock.fs_spc) % NSPB(&sblock) != 0) {
1845 		(void) fprintf(stderr,
1846 		gettext("newfs: panic (fs_cpg * fs_spc) %% NSPF != 0\n"));
1847 		lockexit(32);
1848 	}
1849 	if (sblock.fs_cpg < mincpg) {
1850 		(void) fprintf(stderr, gettext(
1851 "With the given parameters, cgsize must be at least %ld; please re-run mkfs\n"),
1852 		    mincpg);
1853 		lockexit(32);
1854 	}
1855 	sblock.fs_cgsize = fragroundup(&sblock, CGSIZE(&sblock));
1856 grow20:
1857 	/*
1858 	 * Now have size for file system and nsect and ntrak.
1859 	 * Determine number of cylinders and blocks in the file system.
1860 	 */
1861 	fssize_frag = (int64_t)dbtofsb(&sblock, fssize_db);
1862 	if (fssize_frag > INT_MAX) {
1863 		(void) fprintf(stderr, gettext(
1864 "There are too many fragments in the system, increase fragment size\n"),
1865 		    mincpg);
1866 		lockexit(32);
1867 	}
1868 	sblock.fs_size = (int32_t)fssize_frag;
1869 	sblock.fs_ncyl = (int32_t)(fssize_frag * NSPF(&sblock) / sblock.fs_spc);
1870 	if (fssize_frag * NSPF(&sblock) >
1871 	    (uint64_t)sblock.fs_ncyl * sblock.fs_spc) {
1872 		sblock.fs_ncyl++;
1873 		warn = 1;
1874 	}
1875 	if (sblock.fs_ncyl < 1) {
1876 		(void) fprintf(stderr, gettext(
1877 		    "file systems must have at least one cylinder\n"));
1878 		lockexit(32);
1879 	}
1880 	if (grow)
1881 		goto grow30;
1882 	/*
1883 	 * Determine feasability/values of rotational layout tables.
1884 	 *
1885 	 * The size of the rotational layout tables is limited by the size
1886 	 * of the file system block, fs_bsize.  The amount of space
1887 	 * available for tables is calculated as (fs_bsize - sizeof (struct
1888 	 * fs)).  The size of these tables is inversely proportional to the
1889 	 * block size of the file system. The size increases if sectors per
1890 	 * track are not powers of two, because more cylinders must be
1891 	 * described by the tables before the rotational pattern repeats
1892 	 * (fs_cpc).
1893 	 */
1894 	sblock.fs_postblformat = FS_DYNAMICPOSTBLFMT;
1895 	sblock.fs_sbsize = fragroundup(&sblock, sizeof (struct fs));
1896 	sblock.fs_npsect = sblock.fs_nsect;
1897 	if (sblock.fs_ntrak == 1) {
1898 		sblock.fs_cpc = 0;
1899 		goto next;
1900 	}
1901 	postblsize = sblock.fs_nrpos * sblock.fs_cpc * sizeof (short);
1902 	rotblsize = sblock.fs_cpc * sblock.fs_spc / NSPB(&sblock);
1903 	totalsbsize = sizeof (struct fs) + rotblsize;
1904 
1905 	/* do static allocation if nrpos == 8 and fs_cpc == 16  */
1906 	if (sblock.fs_nrpos == 8 && sblock.fs_cpc <= 16) {
1907 		/* use old static table space */
1908 		sblock.fs_postbloff = (char *)(&sblock.fs_opostbl[0][0]) -
1909 		    (char *)(&sblock.fs_link);
1910 		sblock.fs_rotbloff = &sblock.fs_space[0] -
1911 		    (uchar_t *)(&sblock.fs_link);
1912 	} else {
1913 		/* use 4.3 dynamic table space */
1914 		sblock.fs_postbloff = &sblock.fs_space[0] -
1915 		    (uchar_t *)(&sblock.fs_link);
1916 		sblock.fs_rotbloff = sblock.fs_postbloff + postblsize;
1917 		totalsbsize += postblsize;
1918 	}
1919 	if (totalsbsize > sblock.fs_bsize ||
1920 	    sblock.fs_nsect > (1 << NBBY) * NSPB(&sblock)) {
1921 		(void) fprintf(stderr, gettext(
1922 		    "Warning: insufficient space in super block for\n"
1923 		    "rotational layout tables with nsect %d, ntrack %d, "
1924 		    "and nrpos %d.\nOmitting tables - file system "
1925 		    "performance may be impaired.\n"),
1926 		    sblock.fs_nsect, sblock.fs_ntrak, sblock.fs_nrpos);
1927 
1928 		/*
1929 		 * Setting fs_cpc to 0 tells alloccgblk() in ufs_alloc.c to
1930 		 * ignore the positional layout table and rotational
1931 		 * position table.
1932 		 */
1933 		sblock.fs_cpc = 0;
1934 		goto next;
1935 	}
1936 	sblock.fs_sbsize = fragroundup(&sblock, totalsbsize);
1937 
1938 
1939 	/*
1940 	 * calculate the available blocks for each rotational position
1941 	 */
1942 	for (cylno = 0; cylno < sblock.fs_cpc; cylno++)
1943 		for (rpos = 0; rpos < sblock.fs_nrpos; rpos++)
1944 			fs_postbl(&sblock, cylno)[rpos] = -1;
1945 	for (i = (rotblsize - 1) * sblock.fs_frag;
1946 	    i >= 0; i -= sblock.fs_frag) {
1947 		cylno = cbtocylno(&sblock, i);
1948 		rpos = cbtorpos(&sblock, i);
1949 		blk = fragstoblks(&sblock, i);
1950 		if (fs_postbl(&sblock, cylno)[rpos] == -1)
1951 			fs_rotbl(&sblock)[blk] = 0;
1952 		else
1953 			fs_rotbl(&sblock)[blk] =
1954 			    fs_postbl(&sblock, cylno)[rpos] - blk;
1955 		fs_postbl(&sblock, cylno)[rpos] = blk;
1956 	}
1957 next:
1958 grow30:
1959 	/*
1960 	 * Compute/validate number of cylinder groups.
1961 	 * Note that if an excessively large filesystem is specified
1962 	 * (e.g., more than 16384 cylinders for an 8K filesystem block), it
1963 	 * does not get detected until checksummarysize()
1964 	 */
1965 	sblock.fs_ncg = sblock.fs_ncyl / sblock.fs_cpg;
1966 	if (sblock.fs_ncyl % sblock.fs_cpg)
1967 		sblock.fs_ncg++;
1968 	sblock.fs_dblkno = sblock.fs_iblkno + sblock.fs_ipg / INOPF(&sblock);
1969 	i = MIN(~sblock.fs_cgmask, sblock.fs_ncg - 1);
1970 	ibpcl = cgdmin(&sblock, i) - cgbase(&sblock, i);
1971 	if (ibpcl >= sblock.fs_fpg) {
1972 		(void) fprintf(stderr, gettext(
1973 		    "inode blocks/cyl group (%d) >= data blocks (%d)\n"),
1974 		    cgdmin(&sblock, i) - cgbase(&sblock, i) / sblock.fs_frag,
1975 		    sblock.fs_fpg / sblock.fs_frag);
1976 		if ((ibpcl < 0) || (sblock.fs_fpg < 0)) {
1977 			(void) fprintf(stderr, gettext(
1978 	    "number of cylinders per cylinder group (%d) must be decreased.\n"),
1979 			    sblock.fs_cpg);
1980 		} else {
1981 			(void) fprintf(stderr, gettext(
1982 	    "number of cylinders per cylinder group (%d) must be increased.\n"),
1983 			    sblock.fs_cpg);
1984 		}
1985 		(void) fprintf(stderr, gettext(
1986 "Note that cgsize may have been adjusted to allow struct cg to fit.\n"));
1987 		lockexit(32);
1988 	}
1989 	j = sblock.fs_ncg - 1;
1990 	if ((i = fssize_frag - j * sblock.fs_fpg) < sblock.fs_fpg &&
1991 	    cgdmin(&sblock, j) - cgbase(&sblock, j) > i) {
1992 		(void) fprintf(stderr, gettext(
1993 		    "Warning: inode blocks/cyl group (%d) >= data "
1994 		    "blocks (%ld) in last\n    cylinder group. This "
1995 		    "implies %ld sector(s) cannot be allocated.\n"),
1996 		    (cgdmin(&sblock, j) - cgbase(&sblock, j)) / sblock.fs_frag,
1997 		    i / sblock.fs_frag, i * NSPF(&sblock));
1998 		/*
1999 		 * If there is only one cylinder group and that is not even
2000 		 * big enough to hold the inodes, exit.
2001 		 */
2002 		if (sblock.fs_ncg == 1)
2003 			cg_too_small = 1;
2004 		sblock.fs_ncg--;
2005 		sblock.fs_ncyl = sblock.fs_ncg * sblock.fs_cpg;
2006 		sblock.fs_size = fssize_frag =
2007 		    (int64_t)sblock.fs_ncyl * (int64_t)sblock.fs_spc /
2008 		    (int64_t)NSPF(&sblock);
2009 		warn = 0;
2010 	}
2011 	if (warn && !spc_flag) {
2012 		(void) fprintf(stderr, gettext(
2013 		    "Warning: %d sector(s) in last cylinder unallocated\n"),
2014 		    sblock.fs_spc - (uint32_t)(fssize_frag * NSPF(&sblock) -
2015 		    (uint64_t)(sblock.fs_ncyl - 1) * sblock.fs_spc));
2016 	}
2017 	/*
2018 	 * fill in remaining fields of the super block
2019 	 */
2020 
2021 	/*
2022 	 * The csum records are stored in cylinder group 0, starting at
2023 	 * cgdmin, the first data block.
2024 	 */
2025 	sblock.fs_csaddr = cgdmin(&sblock, 0);
2026 	sblock.fs_cssize =
2027 	    fragroundup(&sblock, sblock.fs_ncg * sizeof (struct csum));
2028 	i = sblock.fs_bsize / sizeof (struct csum);
2029 	sblock.fs_csmask = ~(i - 1);
2030 	for (sblock.fs_csshift = 0; i > 1; i >>= 1)
2031 		sblock.fs_csshift++;
2032 	fscs = (struct csum *)calloc(1, sblock.fs_cssize);
2033 
2034 	checksummarysize();
2035 	if (mtb == 'y') {
2036 		sblock.fs_magic = MTB_UFS_MAGIC;
2037 		sblock.fs_version = MTB_UFS_VERSION_1;
2038 	} else {
2039 		sblock.fs_magic = FS_MAGIC;
2040 		if (use_efi_dflts)
2041 			sblock.fs_version = UFS_EFISTYLE4NONEFI_VERSION_2;
2042 		else
2043 			sblock.fs_version = UFS_VERSION_MIN;
2044 	}
2045 
2046 	if (grow) {
2047 		bcopy((caddr_t)grow_fscs, (caddr_t)fscs, (int)grow_fs_cssize);
2048 		extendsummaryinfo();
2049 		goto grow40;
2050 	}
2051 	sblock.fs_rotdelay = rotdelay;
2052 	sblock.fs_maxcontig = maxcontig;
2053 	sblock.fs_maxbpg = MAXBLKPG(sblock.fs_bsize);
2054 
2055 	sblock.fs_rps = rps;
2056 	sblock.fs_cgrotor = 0;
2057 	sblock.fs_cstotal.cs_ndir = 0;
2058 	sblock.fs_cstotal.cs_nbfree = 0;
2059 	sblock.fs_cstotal.cs_nifree = 0;
2060 	sblock.fs_cstotal.cs_nffree = 0;
2061 	sblock.fs_fmod = 0;
2062 	sblock.fs_ronly = 0;
2063 	sblock.fs_time = mkfstime;
2064 	sblock.fs_state = FSOKAY - sblock.fs_time;
2065 	sblock.fs_clean = FSCLEAN;
2066 grow40:
2067 
2068 	/*
2069 	 * If all that's needed is a dump of the superblock we
2070 	 * would use by default, we've got it now.  So, splat it
2071 	 * out and leave.
2072 	 */
2073 	if (rflag) {
2074 		dump_sblock();
2075 		lockexit(0);
2076 	}
2077 	/*
2078 	 * Dump out summary information about file system.
2079 	 */
2080 	(void) fprintf(stderr, gettext(
2081 	    "%s:\t%lld sectors in %d cylinders of %d tracks, %d sectors\n"),
2082 	    fsys, (uint64_t)sblock.fs_size * NSPF(&sblock), sblock.fs_ncyl,
2083 	    sblock.fs_ntrak, sblock.fs_nsect);
2084 	(void) fprintf(stderr, gettext(
2085 	    "\t%.1fMB in %d cyl groups (%d c/g, %.2fMB/g, %d i/g)\n"),
2086 	    (float)sblock.fs_size * sblock.fs_fsize / MB, sblock.fs_ncg,
2087 	    sblock.fs_cpg, (float)sblock.fs_fpg * sblock.fs_fsize / MB,
2088 	    sblock.fs_ipg);
2089 
2090 	tmpbuf = calloc(sblock.fs_ncg / 50 + 500, 1);
2091 	if (tmpbuf == NULL) {
2092 		perror("calloc");
2093 		lockexit(32);
2094 	}
2095 	if (cg_too_small) {
2096 		(void) fprintf(stderr, gettext("File system creation failed. "
2097 		    "There is only one cylinder group and\nthat is "
2098 		    "not even big enough to hold the inodes.\n"));
2099 		lockexit(32);
2100 	}
2101 	/*
2102 	 * Now build the cylinders group blocks and
2103 	 * then print out indices of cylinder groups.
2104 	 */
2105 	tprintf(gettext(
2106 	    "super-block backups (for fsck -F ufs -o b=#) at:\n"));
2107 	for (width = cylno = 0; cylno < sblock.fs_ncg && cylno < 10; cylno++) {
2108 		if ((grow == 0) || (cylno >= grow_fs_ncg))
2109 			initcg(cylno);
2110 		num = fsbtodb(&sblock, (uint64_t)cgsblock(&sblock, cylno));
2111 		/*
2112 		 * If Nflag and if the disk is larger than the CHSLIMIT,
2113 		 * then sanity test the superblocks before reporting. If there
2114 		 * are too many superblocks which look insane, we have
2115 		 * to retry with alternate logic. If both methods have
2116 		 * failed, then our efforts to arrive at alternate
2117 		 * superblocks failed, so complain and exit.
2118 		 */
2119 		if (Nflag && retry) {
2120 			skip_this_sb = 0;
2121 			rdfs((diskaddr_t)num, sbsize, (char *)&altsblock);
2122 			ret = checksblock(altsblock, 1);
2123 			if (ret) {
2124 				skip_this_sb = 1;
2125 				invalid_sb_cnt++;
2126 				dprintf(("DeBuG checksblock() failed - error :"
2127 				    " %d for sb : %llu invalid_sb_cnt : %d\n",
2128 				    ret, num, invalid_sb_cnt));
2129 			} else {
2130 				/*
2131 				 * Though the superblock looks sane, verify if
2132 				 * the fs_version in the superblock and the
2133 				 * logic that we are using to arrive at the
2134 				 * superblocks match.
2135 				 */
2136 				if (use_efi_dflts && altsblock.fs_version
2137 				    != UFS_EFISTYLE4NONEFI_VERSION_2) {
2138 					skip_this_sb = 1;
2139 					invalid_sb_cnt++;
2140 				}
2141 			}
2142 			if (invalid_sb_cnt >= INVALIDSBLIMIT) {
2143 				if (retry > 1) {
2144 					(void) fprintf(stderr, gettext(
2145 					    "Error determining alternate "
2146 					    "superblock locations\n"));
2147 					free(tmpbuf);
2148 					lockexit(32);
2149 				}
2150 				retry++;
2151 				use_efi_dflts = !use_efi_dflts;
2152 				free(tmpbuf);
2153 				goto retry_alternate_logic;
2154 			}
2155 			if (skip_this_sb)
2156 				continue;
2157 		}
2158 		(void) sprintf(pbuf, " %llu,", num);
2159 		plen = strlen(pbuf);
2160 		if ((width + plen) > (WIDTH - 1)) {
2161 			width = plen;
2162 			tprintf("\n");
2163 		} else {
2164 			width += plen;
2165 		}
2166 		if (Nflag && retry)
2167 			(void) strncat(tmpbuf, pbuf, strlen(pbuf));
2168 		else
2169 			(void) fprintf(stderr, "%s", pbuf);
2170 	}
2171 	tprintf("\n");
2172 
2173 	remaining_cg = sblock.fs_ncg - cylno;
2174 
2175 	/*
2176 	 * If there are more than 300 cylinder groups still to be
2177 	 * initialized, print a "." for every 50 cylinder groups.
2178 	 */
2179 	if (remaining_cg > 300) {
2180 		tprintf(gettext("Initializing cylinder groups:\n"));
2181 		do_dot = 1;
2182 	}
2183 
2184 	/*
2185 	 * Now initialize all cylinder groups between the first ten
2186 	 * and the last ten.
2187 	 *
2188 	 * If the number of cylinder groups was less than 10, all of the
2189 	 * cylinder group offsets would have printed in the last loop
2190 	 * and cylno will already be equal to sblock.fs_ncg and so this
2191 	 * loop will not be entered.  If there are less than 20 cylinder
2192 	 * groups, cylno is already less than fs_ncg - 10, so this loop
2193 	 * won't be entered in that case either.
2194 	 */
2195 
2196 	i = 0;
2197 	for (; cylno < sblock.fs_ncg - 10; cylno++) {
2198 		if ((grow == 0) || (cylno >= grow_fs_ncg))
2199 			initcg(cylno);
2200 		if (do_dot && cylno % 50 == 0) {
2201 			tprintf(".");
2202 			i++;
2203 			if (i == WIDTH - 1) {
2204 				tprintf("\n");
2205 				i = 0;
2206 			}
2207 		}
2208 	}
2209 
2210 	/*
2211 	 * Now print the cylinder group offsets for the last 10
2212 	 * cylinder groups, if any are left.
2213 	 */
2214 
2215 	if (do_dot) {
2216 		tprintf(gettext(
2217 	    "\nsuper-block backups for last 10 cylinder groups at:\n"));
2218 	}
2219 	for (width = 0; cylno < sblock.fs_ncg; cylno++) {
2220 		if ((grow == 0) || (cylno >= grow_fs_ncg))
2221 			initcg(cylno);
2222 		num = fsbtodb(&sblock, (uint64_t)cgsblock(&sblock, cylno));
2223 		if (Nflag && retry) {
2224 			skip_this_sb = 0;
2225 			rdfs((diskaddr_t)num, sbsize, (char *)&altsblock);
2226 			ret = checksblock(altsblock, 1);
2227 			if (ret) {
2228 				skip_this_sb = 1;
2229 				invalid_sb_cnt++;
2230 				dprintf(("DeBuG checksblock() failed - error :"
2231 				    " %d for sb : %llu invalid_sb_cnt : %d\n",
2232 				    ret, num, invalid_sb_cnt));
2233 			} else {
2234 				/*
2235 				 * Though the superblock looks sane, verify if
2236 				 * the fs_version in the superblock and the
2237 				 * logic that we are using to arrive at the
2238 				 * superblocks match.
2239 				 */
2240 				if (use_efi_dflts && altsblock.fs_version
2241 				    != UFS_EFISTYLE4NONEFI_VERSION_2) {
2242 					skip_this_sb = 1;
2243 					invalid_sb_cnt++;
2244 				}
2245 			}
2246 			if (invalid_sb_cnt >= INVALIDSBLIMIT) {
2247 				if (retry > 1) {
2248 					(void) fprintf(stderr, gettext(
2249 					    "Error determining alternate "
2250 					    "superblock locations\n"));
2251 					free(tmpbuf);
2252 					lockexit(32);
2253 				}
2254 				retry++;
2255 				use_efi_dflts = !use_efi_dflts;
2256 				free(tmpbuf);
2257 				goto retry_alternate_logic;
2258 			}
2259 			if (skip_this_sb)
2260 				continue;
2261 		}
2262 		/* Don't print ',' for the last superblock */
2263 		if (cylno == sblock.fs_ncg-1)
2264 			(void) sprintf(pbuf, " %llu", num);
2265 		else
2266 			(void) sprintf(pbuf, " %llu,", num);
2267 		plen = strlen(pbuf);
2268 		if ((width + plen) > (WIDTH - 1)) {
2269 			width = plen;
2270 			tprintf("\n");
2271 		} else {
2272 			width += plen;
2273 		}
2274 		if (Nflag && retry)
2275 			(void) strncat(tmpbuf, pbuf, strlen(pbuf));
2276 		else
2277 			(void) fprintf(stderr, "%s", pbuf);
2278 	}
2279 	tprintf("\n");
2280 	if (Nflag) {
2281 		if (retry)
2282 			(void) fprintf(stderr, "%s", tmpbuf);
2283 		free(tmpbuf);
2284 		lockexit(0);
2285 	}
2286 
2287 	free(tmpbuf);
2288 	if (grow)
2289 		goto grow50;
2290 
2291 	/*
2292 	 * Now construct the initial file system,
2293 	 * then write out the super-block.
2294 	 */
2295 	fsinit();
2296 grow50:
2297 	/*
2298 	 * write the superblock and csum information
2299 	 */
2300 	wtsb();
2301 
2302 	/*
2303 	 * extend the last cylinder group in the original file system
2304 	 */
2305 	if (grow) {
2306 		extendcg(grow_fs_ncg-1);
2307 		wtsb();
2308 	}
2309 
2310 	/*
2311 	 * Write out the duplicate super blocks to the first 10
2312 	 * cylinder groups (or fewer, if there are fewer than 10
2313 	 * cylinder groups).
2314 	 */
2315 	for (cylno = 0; cylno < sblock.fs_ncg && cylno < 10; cylno++)
2316 		awtfs(fsbtodb(&sblock, (uint64_t)cgsblock(&sblock, cylno)),
2317 		    (int)sbsize, (char *)&sblock, SAVE);
2318 
2319 	/*
2320 	 * Now write out duplicate super blocks to the remaining
2321 	 * cylinder groups.  In the case of multi-terabyte file
2322 	 * systems, just write out the super block to the last ten
2323 	 * cylinder groups (or however many are left).
2324 	 */
2325 	if (mtb == 'y') {
2326 		if (sblock.fs_ncg <= 10)
2327 			cylno = sblock.fs_ncg;
2328 		else if (sblock.fs_ncg <= 20)
2329 			cylno = 10;
2330 		else
2331 			cylno = sblock.fs_ncg - 10;
2332 	}
2333 
2334 	for (; cylno < sblock.fs_ncg; cylno++)
2335 		awtfs(fsbtodb(&sblock, (uint64_t)cgsblock(&sblock, cylno)),
2336 		    (int)sbsize, (char *)&sblock, SAVE);
2337 
2338 	/*
2339 	 * Flush out all the AIO writes we've done.  It's not
2340 	 * necessary to do this explicitly, but it's the only
2341 	 * way to report any errors from those writes.
2342 	 */
2343 	flush_writes();
2344 
2345 	/*
2346 	 * set clean flag
2347 	 */
2348 	if (grow)
2349 		sblock.fs_clean = grow_fs_clean;
2350 	else
2351 		sblock.fs_clean = FSCLEAN;
2352 	sblock.fs_time = mkfstime;
2353 	sblock.fs_state = FSOKAY - sblock.fs_time;
2354 	wtfs((diskaddr_t)(SBOFF / sectorsize), sbsize, (char *)&sblock);
2355 	isbad = 0;
2356 
2357 	if (fsync(fso) == -1) {
2358 		saverr = errno;
2359 		(void) fprintf(stderr,
2360 		    gettext("mkfs: fsync failed on write disk: %s\n"),
2361 		    strerror(saverr));
2362 		/* we're just cleaning up, so keep going */
2363 	}
2364 	if (close(fsi) == -1) {
2365 		saverr = errno;
2366 		(void) fprintf(stderr,
2367 		    gettext("mkfs: close failed on read disk: %s\n"),
2368 		    strerror(saverr));
2369 		/* we're just cleaning up, so keep going */
2370 	}
2371 	if (close(fso) == -1) {
2372 		saverr = errno;
2373 		(void) fprintf(stderr,
2374 		    gettext("mkfs: close failed on write disk: %s\n"),
2375 		    strerror(saverr));
2376 		/* we're just cleaning up, so keep going */
2377 	}
2378 	fsi = fso = -1;
2379 
2380 #ifndef STANDALONE
2381 	lockexit(0);
2382 #endif
2383 
2384 	return (0);
2385 }
2386 
2387 static diskaddr_t
get_device_size(int fd)2388 get_device_size(int fd)
2389 {
2390 	struct dk_minfo	disk_info;
2391 
2392 	if ((ioctl(fd, DKIOCGMEDIAINFO, (caddr_t)&disk_info)) == -1)
2393 		return (0);
2394 
2395 	return (disk_info.dki_capacity);
2396 }
2397 
2398 /*
2399  * Figure out how big the partition we're dealing with is.
2400  * The value returned is in disk blocks (sectors);
2401  */
2402 static diskaddr_t
get_max_size(int fd)2403 get_max_size(int fd)
2404 {
2405 	struct extvtoc vtoc;
2406 	dk_gpt_t *efi_vtoc;
2407 	diskaddr_t	slicesize;
2408 
2409 	int index = read_extvtoc(fd, &vtoc);
2410 
2411 	if (index >= 0) {
2412 		label_type = LABEL_TYPE_VTOC;
2413 	} else {
2414 		if (index == VT_ENOTSUP || index == VT_ERROR) {
2415 			/* it might be an EFI label */
2416 			index = efi_alloc_and_read(fd, &efi_vtoc);
2417 			label_type = LABEL_TYPE_EFI;
2418 		}
2419 	}
2420 
2421 	if (index < 0) {
2422 		/*
2423 		 * Since both attempts to read the label failed, we're
2424 		 * going to use DKIOCGMEDIAINFO to get device size.
2425 		 */
2426 
2427 		label_type = LABEL_TYPE_OTHER;
2428 		slicesize = get_device_size(fd);
2429 		if (slicesize == 0) {
2430 			switch (index) {
2431 			case VT_ERROR:
2432 				break;
2433 			case VT_EIO:
2434 				errno = EIO;
2435 				break;
2436 			case VT_EINVAL:
2437 				errno = EINVAL;
2438 			}
2439 			perror(gettext("Can not determine partition size"));
2440 			lockexit(32);
2441 		}
2442 	}
2443 
2444 	if (label_type == LABEL_TYPE_EFI) {
2445 		slicesize = efi_vtoc->efi_parts[index].p_size;
2446 		efi_free(efi_vtoc);
2447 	} else if (label_type == LABEL_TYPE_VTOC) {
2448 		/*
2449 		 * In the vtoc struct, p_size is a 32-bit signed quantity.
2450 		 * In the dk_gpt struct (efi's version of the vtoc), p_size
2451 		 * is an unsigned 64-bit quantity.  By casting the vtoc's
2452 		 * psize to an unsigned 32-bit quantity, it will be copied
2453 		 * to 'slicesize' (an unsigned 64-bit diskaddr_t) without
2454 		 * sign extension.
2455 		 */
2456 
2457 		slicesize = (uint32_t)vtoc.v_part[index].p_size;
2458 	}
2459 
2460 	dprintf(("DeBuG get_max_size index = %d, p_size = %lld, dolimit = %d\n",
2461 	    index, slicesize, (slicesize > FS_MAX)));
2462 
2463 	/*
2464 	 * The next line limits a UFS file system to the maximum
2465 	 * supported size.
2466 	 */
2467 
2468 	if (slicesize > FS_MAX)
2469 		return (FS_MAX);
2470 	return (slicesize);
2471 }
2472 
2473 static long
get_max_track_size(int fd)2474 get_max_track_size(int fd)
2475 {
2476 	struct dk_cinfo ci;
2477 	long track_size = -1;
2478 
2479 	if (ioctl(fd, DKIOCINFO, &ci) == 0) {
2480 		track_size = ci.dki_maxtransfer * DEV_BSIZE;
2481 	}
2482 
2483 	if ((track_size < 0)) {
2484 		int	error = 0;
2485 		int	maxphys;
2486 		int	gotit = 0;
2487 
2488 		gotit = fsgetmaxphys(&maxphys, &error);
2489 		if (gotit) {
2490 			track_size = MIN(MB, maxphys);
2491 		} else {
2492 			(void) fprintf(stderr, gettext(
2493 "Warning: Could not get system value for maxphys. The value for\n"
2494 "maxcontig will default to 1MB.\n"));
2495 			track_size = MB;
2496 		}
2497 	}
2498 	return (track_size);
2499 }
2500 
2501 /*
2502  * Initialize a cylinder group.
2503  */
2504 static void
initcg(int cylno)2505 initcg(int cylno)
2506 {
2507 	diskaddr_t cbase, d;
2508 	diskaddr_t dlower;	/* last data block before cg metadata */
2509 	diskaddr_t dupper;	/* first data block after cg metadata */
2510 	diskaddr_t dmax;
2511 	int64_t i;
2512 	struct csum *cs;
2513 	struct dinode *inode_buffer;
2514 	int size;
2515 
2516 	/*
2517 	 * Variables used to store intermediate results as a part of
2518 	 * the internal implementation of the cbtocylno() macros.
2519 	 */
2520 	diskaddr_t bno;		/* UFS block number (not sector number) */
2521 	int	cbcylno;	/* current cylinder number */
2522 	int	cbcylno_sect;	/* sector offset within cylinder */
2523 	int	cbsect_incr;	/* amount to increment sector offset */
2524 
2525 	/*
2526 	 * Variables used to store intermediate results as a part of
2527 	 * the internal implementation of the cbtorpos() macros.
2528 	 */
2529 	short	*cgblks;	/* pointer to array of free blocks in cg */
2530 	int	trackrpos;	/* tmp variable for rotation position */
2531 	int	trackoff;	/* offset within a track */
2532 	int	trackoff_incr;	/* amount to increment trackoff */
2533 	int	rpos;		/* rotation position of current block */
2534 	int	rpos_incr;	/* amount to increment rpos per block */
2535 
2536 	union cgun *icgun;	/* local pointer to a cg summary block */
2537 #define	icg	(icgun->cg)
2538 
2539 	icgun = (union cgun *)getbuf(&cgsumbuf, sizeof (union cgun));
2540 
2541 	/*
2542 	 * Determine block bounds for cylinder group.
2543 	 * Allow space for super block summary information in first
2544 	 * cylinder group.
2545 	 */
2546 	cbase = cgbase(&sblock, cylno);
2547 	dmax = cbase + sblock.fs_fpg;
2548 	if (dmax > sblock.fs_size)	/* last cg may be smaller than normal */
2549 		dmax = sblock.fs_size;
2550 	dlower = cgsblock(&sblock, cylno) - cbase;
2551 	dupper = cgdmin(&sblock, cylno) - cbase;
2552 	if (cylno == 0)
2553 		dupper += howmany(sblock.fs_cssize, sblock.fs_fsize);
2554 	cs = fscs + cylno;
2555 	icg.cg_time = mkfstime;
2556 	icg.cg_magic = CG_MAGIC;
2557 	icg.cg_cgx = cylno;
2558 	/* last one gets whatever's left */
2559 	if (cylno == sblock.fs_ncg - 1)
2560 		icg.cg_ncyl = sblock.fs_ncyl - (sblock.fs_cpg * cylno);
2561 	else
2562 		icg.cg_ncyl = sblock.fs_cpg;
2563 	icg.cg_niblk = sblock.fs_ipg;
2564 	icg.cg_ndblk = dmax - cbase;
2565 	icg.cg_cs.cs_ndir = 0;
2566 	icg.cg_cs.cs_nffree = 0;
2567 	icg.cg_cs.cs_nbfree = 0;
2568 	icg.cg_cs.cs_nifree = 0;
2569 	icg.cg_rotor = 0;
2570 	icg.cg_frotor = 0;
2571 	icg.cg_irotor = 0;
2572 	icg.cg_btotoff = &icg.cg_space[0] - (uchar_t *)(&icg.cg_link);
2573 	icg.cg_boff = icg.cg_btotoff + sblock.fs_cpg * sizeof (long);
2574 	icg.cg_iusedoff = icg.cg_boff +
2575 	    sblock.fs_cpg * sblock.fs_nrpos * sizeof (short);
2576 	icg.cg_freeoff = icg.cg_iusedoff + howmany(sblock.fs_ipg, NBBY);
2577 	icg.cg_nextfreeoff = icg.cg_freeoff +
2578 	    howmany(sblock.fs_cpg * sblock.fs_spc / NSPF(&sblock), NBBY);
2579 	for (i = 0; i < sblock.fs_frag; i++) {
2580 		icg.cg_frsum[i] = 0;
2581 	}
2582 	bzero((caddr_t)cg_inosused(&icg), icg.cg_freeoff - icg.cg_iusedoff);
2583 	icg.cg_cs.cs_nifree += sblock.fs_ipg;
2584 	if (cylno == 0)
2585 		for (i = 0; i < UFSROOTINO; i++) {
2586 			setbit(cg_inosused(&icg), i);
2587 			icg.cg_cs.cs_nifree--;
2588 		}
2589 
2590 	/*
2591 	 * Initialize all the inodes in the cylinder group using
2592 	 * random numbers.
2593 	 */
2594 	size = sblock.fs_ipg * sizeof (struct dinode);
2595 	inode_buffer = (struct dinode *)getbuf(&inodebuf, size);
2596 
2597 	for (i = 0; i < sblock.fs_ipg; i++) {
2598 		IRANDOMIZE(&(inode_buffer[i].di_ic));
2599 	}
2600 
2601 	/*
2602 	 * Write all inodes in a single write for performance.
2603 	 */
2604 	awtfs(fsbtodb(&sblock, (uint64_t)cgimin(&sblock, cylno)), (int)size,
2605 	    (char *)inode_buffer, RELEASE);
2606 
2607 	bzero((caddr_t)cg_blktot(&icg), icg.cg_boff - icg.cg_btotoff);
2608 	bzero((caddr_t)cg_blks(&sblock, &icg, 0),
2609 	    icg.cg_iusedoff - icg.cg_boff);
2610 	bzero((caddr_t)cg_blksfree(&icg), icg.cg_nextfreeoff - icg.cg_freeoff);
2611 
2612 	if (cylno > 0) {
2613 		for (d = 0; d < dlower; d += sblock.fs_frag) {
2614 			setblock(&sblock, cg_blksfree(&icg), d/sblock.fs_frag);
2615 			icg.cg_cs.cs_nbfree++;
2616 			cg_blktot(&icg)[cbtocylno(&sblock, d)]++;
2617 			cg_blks(&sblock, &icg, cbtocylno(&sblock, d))
2618 			    [cbtorpos(&sblock, d)]++;
2619 		}
2620 		sblock.fs_dsize += dlower;
2621 	}
2622 	sblock.fs_dsize += icg.cg_ndblk - dupper;
2623 	if ((i = dupper % sblock.fs_frag) != 0) {
2624 		icg.cg_frsum[sblock.fs_frag - i]++;
2625 		for (d = dupper + sblock.fs_frag - i; dupper < d; dupper++) {
2626 			setbit(cg_blksfree(&icg), dupper);
2627 			icg.cg_cs.cs_nffree++;
2628 		}
2629 	}
2630 
2631 	/*
2632 	 * WARNING: The following code is somewhat confusing, but
2633 	 * results in a substantial performance improvement in mkfs.
2634 	 *
2635 	 * Instead of using cbtocylno() and cbtorpos() macros, we
2636 	 * keep track of all the intermediate state of those macros
2637 	 * in some variables.  This allows simple addition to be
2638 	 * done to calculate the results as we step through the
2639 	 * blocks in an orderly fashion instead of the slower
2640 	 * multiplication and division the macros are forced to
2641 	 * used so they can support random input.  (Multiplication,
2642 	 * division, and remainder operations typically take about
2643 	 * 10x as many processor cycles as other operations.)
2644 	 *
2645 	 * The basic idea is to take code:
2646 	 *
2647 	 *	for (x = starting_x; x < max; x++)
2648 	 *		y = (x * c) / z
2649 	 *
2650 	 * and rewrite it to take advantage of the fact that
2651 	 * the variable x is incrementing in an orderly way:
2652 	 *
2653 	 *	intermediate = starting_x * c
2654 	 *	yval = intermediate / z
2655 	 *	for (x = starting_x; x < max; x++) {
2656 	 *		y = yval;
2657 	 *		intermediate += c
2658 	 *		if (intermediate > z) {
2659 	 *			yval++;
2660 	 *			intermediate -= z
2661 	 *		}
2662 	 *	}
2663 	 *
2664 	 * Performance has improved as much as 4X using this code.
2665 	 */
2666 
2667 	/*
2668 	 * Initialize the starting points for all the cbtocylno()
2669 	 * macro variables and figure out the increments needed each
2670 	 * time through the loop.
2671 	 */
2672 	cbcylno_sect = dupper * NSPF(&sblock);
2673 	cbsect_incr = sblock.fs_frag * NSPF(&sblock);
2674 	cbcylno = cbcylno_sect / sblock.fs_spc;
2675 	cbcylno_sect %= sblock.fs_spc;
2676 	cgblks = cg_blks(&sblock, &icg, cbcylno);
2677 	bno = dupper / sblock.fs_frag;
2678 
2679 	/*
2680 	 * Initialize the starting points for all the cbtorpos()
2681 	 * macro variables and figure out the increments needed each
2682 	 * time through the loop.
2683 	 *
2684 	 * It's harder to simplify the cbtorpos() macro if there were
2685 	 * alternate sectors specified (or if they previously existed
2686 	 * in the growfs case).  Since this is rare, we just revert to
2687 	 * using the macros in this case and skip the variable setup.
2688 	 */
2689 	if (!spc_flag) {
2690 		trackrpos = (cbcylno_sect % sblock.fs_nsect) * sblock.fs_nrpos;
2691 		rpos = trackrpos / sblock.fs_nsect;
2692 		trackoff = trackrpos % sblock.fs_nsect;
2693 		trackoff_incr = cbsect_incr * sblock.fs_nrpos;
2694 		rpos_incr = (trackoff_incr / sblock.fs_nsect) % sblock.fs_nrpos;
2695 		trackoff_incr = trackoff_incr % sblock.fs_nsect;
2696 	}
2697 
2698 	/*
2699 	 * Loop through all the blocks, marking them free and
2700 	 * updating totals kept in the superblock and cg summary.
2701 	 */
2702 	for (d = dupper; d + sblock.fs_frag <= dmax - cbase; ) {
2703 		setblock(&sblock, cg_blksfree(&icg),  bno);
2704 		icg.cg_cs.cs_nbfree++;
2705 
2706 		cg_blktot(&icg)[cbcylno]++;
2707 
2708 		if (!spc_flag)
2709 			cgblks[rpos]++;
2710 		else
2711 			cg_blks(&sblock, &icg, cbtocylno(&sblock, d))
2712 			    [cbtorpos(&sblock, d)]++;
2713 
2714 		d += sblock.fs_frag;
2715 		bno++;
2716 
2717 		/*
2718 		 * Increment the sector offset within the cylinder
2719 		 * for the cbtocylno() macro reimplementation.  If
2720 		 * we're beyond the end of the cylinder, update the
2721 		 * cylinder number, calculate the offset in the
2722 		 * new cylinder, and update the cgblks pointer
2723 		 * to the next rotational position.
2724 		 */
2725 		cbcylno_sect += cbsect_incr;
2726 		if (cbcylno_sect >= sblock.fs_spc) {
2727 			cbcylno++;
2728 			cbcylno_sect -= sblock.fs_spc;
2729 			cgblks += sblock.fs_nrpos;
2730 		}
2731 
2732 		/*
2733 		 * If there aren't alternate sectors, increment the
2734 		 * rotational position variables for the cbtorpos()
2735 		 * reimplementation.  Note that we potentially
2736 		 * increment rpos twice.  Once by rpos_incr, and one
2737 		 * more time when we wrap to a new track because
2738 		 * trackoff >= fs_nsect.
2739 		 */
2740 		if (!spc_flag) {
2741 			trackoff += trackoff_incr;
2742 			rpos += rpos_incr;
2743 			if (trackoff >= sblock.fs_nsect) {
2744 				trackoff -= sblock.fs_nsect;
2745 				rpos++;
2746 			}
2747 			if (rpos >= sblock.fs_nrpos)
2748 				rpos -= sblock.fs_nrpos;
2749 		}
2750 	}
2751 
2752 	if (d < dmax - cbase) {
2753 		icg.cg_frsum[dmax - cbase - d]++;
2754 		for (; d < dmax - cbase; d++) {
2755 			setbit(cg_blksfree(&icg), d);
2756 			icg.cg_cs.cs_nffree++;
2757 		}
2758 	}
2759 	sblock.fs_cstotal.cs_ndir += icg.cg_cs.cs_ndir;
2760 	sblock.fs_cstotal.cs_nffree += icg.cg_cs.cs_nffree;
2761 	sblock.fs_cstotal.cs_nbfree += icg.cg_cs.cs_nbfree;
2762 	sblock.fs_cstotal.cs_nifree += icg.cg_cs.cs_nifree;
2763 	*cs = icg.cg_cs;
2764 	awtfs(fsbtodb(&sblock, (uint64_t)cgtod(&sblock, cylno)),
2765 	    sblock.fs_bsize, (char *)&icg, RELEASE);
2766 }
2767 
2768 /*
2769  * initialize the file system
2770  */
2771 struct inode node;
2772 
2773 #define	LOSTDIR
2774 #ifdef LOSTDIR
2775 #define	PREDEFDIR 3
2776 #else
2777 #define	PREDEFDIR 2
2778 #endif
2779 
2780 struct direct root_dir[] = {
2781 	{ UFSROOTINO, sizeof (struct direct), 1, "." },
2782 	{ UFSROOTINO, sizeof (struct direct), 2, ".." },
2783 #ifdef LOSTDIR
2784 	{ LOSTFOUNDINO, sizeof (struct direct), 10, "lost+found" },
2785 #endif
2786 };
2787 #ifdef LOSTDIR
2788 struct direct lost_found_dir[] = {
2789 	{ LOSTFOUNDINO, sizeof (struct direct), 1, "." },
2790 	{ UFSROOTINO, sizeof (struct direct), 2, ".." },
2791 	{ 0, DIRBLKSIZ, 0, 0 },
2792 };
2793 #endif
2794 char buf[MAXBSIZE];
2795 
2796 static void
fsinit()2797 fsinit()
2798 {
2799 	int i;
2800 
2801 
2802 	/*
2803 	 * initialize the node
2804 	 */
2805 	node.i_atime = mkfstime;
2806 	node.i_mtime = mkfstime;
2807 	node.i_ctime = mkfstime;
2808 #ifdef LOSTDIR
2809 	/*
2810 	 * create the lost+found directory
2811 	 */
2812 	(void) makedir(lost_found_dir, 2);
2813 	for (i = DIRBLKSIZ; i < sblock.fs_bsize; i += DIRBLKSIZ) {
2814 		bcopy(&lost_found_dir[2], &buf[i], DIRSIZ(&lost_found_dir[2]));
2815 	}
2816 	node.i_number = LOSTFOUNDINO;
2817 	node.i_smode = IFDIR | 0700;
2818 	node.i_nlink = 2;
2819 	node.i_size = sblock.fs_bsize;
2820 	node.i_db[0] = alloc((int)node.i_size, node.i_mode);
2821 	node.i_blocks = btodb(fragroundup(&sblock, (int)node.i_size));
2822 	IRANDOMIZE(&node.i_ic);
2823 	wtfs(fsbtodb(&sblock, (uint64_t)node.i_db[0]), (int)node.i_size, buf);
2824 	iput(&node);
2825 #endif
2826 	/*
2827 	 * create the root directory
2828 	 */
2829 	node.i_number = UFSROOTINO;
2830 	node.i_mode = IFDIR | UMASK;
2831 	node.i_nlink = PREDEFDIR;
2832 	node.i_size = makedir(root_dir, PREDEFDIR);
2833 	node.i_db[0] = alloc(sblock.fs_fsize, node.i_mode);
2834 	/* i_size < 2GB because we are initializing the file system */
2835 	node.i_blocks = btodb(fragroundup(&sblock, (int)node.i_size));
2836 	IRANDOMIZE(&node.i_ic);
2837 	wtfs(fsbtodb(&sblock, (uint64_t)node.i_db[0]), sblock.fs_fsize, buf);
2838 	iput(&node);
2839 }
2840 
2841 /*
2842  * construct a set of directory entries in "buf".
2843  * return size of directory.
2844  */
2845 static int
makedir(struct direct * protodir,int entries)2846 makedir(struct direct *protodir, int entries)
2847 {
2848 	char *cp;
2849 	int i;
2850 	ushort_t spcleft;
2851 
2852 	spcleft = DIRBLKSIZ;
2853 	for (cp = buf, i = 0; i < entries - 1; i++) {
2854 		protodir[i].d_reclen = DIRSIZ(&protodir[i]);
2855 		bcopy(&protodir[i], cp, protodir[i].d_reclen);
2856 		cp += protodir[i].d_reclen;
2857 		spcleft -= protodir[i].d_reclen;
2858 	}
2859 	protodir[i].d_reclen = spcleft;
2860 	bcopy(&protodir[i], cp, DIRSIZ(&protodir[i]));
2861 	return (DIRBLKSIZ);
2862 }
2863 
2864 /*
2865  * allocate a block or frag
2866  */
2867 static daddr32_t
alloc(int size,int mode)2868 alloc(int size, int mode)
2869 {
2870 	int i, frag;
2871 	daddr32_t d;
2872 
2873 	rdfs(fsbtodb(&sblock, (uint64_t)cgtod(&sblock, 0)), sblock.fs_cgsize,
2874 	    (char *)&acg);
2875 	if (acg.cg_magic != CG_MAGIC) {
2876 		(void) fprintf(stderr, gettext("cg 0: bad magic number\n"));
2877 		lockexit(32);
2878 	}
2879 	if (acg.cg_cs.cs_nbfree == 0) {
2880 		(void) fprintf(stderr,
2881 		    gettext("first cylinder group ran out of space\n"));
2882 		lockexit(32);
2883 	}
2884 	for (d = 0; d < acg.cg_ndblk; d += sblock.fs_frag)
2885 		if (isblock(&sblock, cg_blksfree(&acg), d / sblock.fs_frag))
2886 			goto goth;
2887 	(void) fprintf(stderr,
2888 	    gettext("internal error: can't find block in cyl 0\n"));
2889 	lockexit(32);
2890 goth:
2891 	clrblock(&sblock, cg_blksfree(&acg), d / sblock.fs_frag);
2892 	acg.cg_cs.cs_nbfree--;
2893 	sblock.fs_cstotal.cs_nbfree--;
2894 	fscs[0].cs_nbfree--;
2895 	if (mode & IFDIR) {
2896 		acg.cg_cs.cs_ndir++;
2897 		sblock.fs_cstotal.cs_ndir++;
2898 		fscs[0].cs_ndir++;
2899 	}
2900 	cg_blktot(&acg)[cbtocylno(&sblock, d)]--;
2901 	cg_blks(&sblock, &acg, cbtocylno(&sblock, d))[cbtorpos(&sblock, d)]--;
2902 	if (size != sblock.fs_bsize) {
2903 		frag = howmany(size, sblock.fs_fsize);
2904 		fscs[0].cs_nffree += sblock.fs_frag - frag;
2905 		sblock.fs_cstotal.cs_nffree += sblock.fs_frag - frag;
2906 		acg.cg_cs.cs_nffree += sblock.fs_frag - frag;
2907 		acg.cg_frsum[sblock.fs_frag - frag]++;
2908 		for (i = frag; i < sblock.fs_frag; i++)
2909 			setbit(cg_blksfree(&acg), d + i);
2910 	}
2911 	wtfs(fsbtodb(&sblock, (uint64_t)cgtod(&sblock, 0)), sblock.fs_cgsize,
2912 	    (char *)&acg);
2913 	return (d);
2914 }
2915 
2916 /*
2917  * Allocate an inode on the disk
2918  */
2919 static void
iput(struct inode * ip)2920 iput(struct inode *ip)
2921 {
2922 	struct dinode buf[MAXINOPB];
2923 	diskaddr_t d;
2924 
2925 	rdfs(fsbtodb(&sblock, (uint64_t)cgtod(&sblock, 0)), sblock.fs_cgsize,
2926 	    (char *)&acg);
2927 	if (acg.cg_magic != CG_MAGIC) {
2928 		(void) fprintf(stderr, gettext("cg 0: bad magic number\n"));
2929 		lockexit(32);
2930 	}
2931 	acg.cg_cs.cs_nifree--;
2932 	setbit(cg_inosused(&acg), ip->i_number);
2933 	wtfs(fsbtodb(&sblock, (uint64_t)cgtod(&sblock, 0)), sblock.fs_cgsize,
2934 	    (char *)&acg);
2935 	sblock.fs_cstotal.cs_nifree--;
2936 	fscs[0].cs_nifree--;
2937 	if ((int)ip->i_number >= sblock.fs_ipg * sblock.fs_ncg) {
2938 		(void) fprintf(stderr,
2939 		    gettext("fsinit: inode value out of range (%d).\n"),
2940 		    ip->i_number);
2941 		lockexit(32);
2942 	}
2943 	d = fsbtodb(&sblock, (uint64_t)itod(&sblock, (int)ip->i_number));
2944 	rdfs(d, sblock.fs_bsize, (char *)buf);
2945 	buf[itoo(&sblock, (int)ip->i_number)].di_ic = ip->i_ic;
2946 	wtfs(d, sblock.fs_bsize, (char *)buf);
2947 }
2948 
2949 /*
2950  * getbuf()	-- Get a buffer for use in an AIO operation.  Buffer
2951  *		is zero'd the first time returned, left with whatever
2952  *		was in memory after that.  This function actually gets
2953  *		enough memory the first time it's called to support
2954  *		MAXBUF buffers like a slab allocator.  When all the
2955  *		buffers are in use, it waits for an aio to complete
2956  *		and make a buffer available.
2957  *
2958  *		Never returns an error.  Either succeeds or exits.
2959  */
2960 static char *
getbuf(bufhdr * bufhead,int size)2961 getbuf(bufhdr *bufhead, int size)
2962 {
2963 	bufhdr *pbuf;
2964 	bufhdr *prev;
2965 	int i;
2966 	int buf_size, max_bufs;
2967 
2968 	/*
2969 	 * Initialize all the buffers
2970 	 */
2971 	if (bufhead->head == NULL) {
2972 		/*
2973 		 * round up the size of our buffer header to a
2974 		 * 16 byte boundary so the address we return to
2975 		 * the caller is "suitably aligned".
2976 		 */
2977 		bufhdrsize = (sizeof (bufhdr) + 15) & ~15;
2978 
2979 		/*
2980 		 * Add in our header to the buffer and round it all up to
2981 		 * a 16 byte boundry so each member of the slab is aligned.
2982 		 */
2983 		buf_size = (size + bufhdrsize + 15) & ~15;
2984 
2985 		/*
2986 		 * Limit number of buffers to lesser of MAXBUFMEM's worth
2987 		 * or MAXBUF, whichever is less.
2988 		 */
2989 		max_bufs = MAXBUFMEM / buf_size;
2990 		if (max_bufs > MAXBUF)
2991 			max_bufs = MAXBUF;
2992 
2993 		pbuf = (bufhdr *)calloc(max_bufs, buf_size);
2994 		if (pbuf == NULL) {
2995 			perror("calloc");
2996 			lockexit(32);
2997 		}
2998 
2999 		bufhead->head = bufhead;
3000 		prev = bufhead;
3001 		for (i = 0; i < max_bufs; i++) {
3002 			pbuf->head = bufhead;
3003 			prev->next = pbuf;
3004 			prev = pbuf;
3005 			pbuf = (bufhdr *)((char *)pbuf + buf_size);
3006 		}
3007 	}
3008 
3009 	/*
3010 	 * Get an available buffer, waiting for I/O if necessary
3011 	 */
3012 	wait_for_write(NOBLOCK);
3013 	while (bufhead->next == NULL)
3014 		wait_for_write(BLOCK);
3015 
3016 	/*
3017 	 * Take the buffer off the list
3018 	 */
3019 	pbuf = bufhead->next;
3020 	bufhead->next = pbuf->next;
3021 	pbuf->next = NULL;
3022 
3023 	/*
3024 	 * return the empty buffer space just past the header
3025 	 */
3026 	return ((char *)pbuf + bufhdrsize);
3027 }
3028 
3029 /*
3030  * freebuf()	-- Free a buffer gotten previously through getbuf.
3031  *		Puts the buffer back on the appropriate list for
3032  *		later use.  Never calls free().
3033  *
3034  * Assumes that SIGINT is blocked.
3035  */
3036 static void
freebuf(char * buf)3037 freebuf(char *buf)
3038 {
3039 	bufhdr *pbuf;
3040 	bufhdr *bufhead;
3041 
3042 	/*
3043 	 * get the header for this buffer
3044 	 */
3045 	pbuf = (bufhdr *)(buf - bufhdrsize);
3046 
3047 	/*
3048 	 * Put it back on the list of available buffers
3049 	 */
3050 	bufhead = pbuf->head;
3051 	pbuf->next = bufhead->next;
3052 	bufhead->next = pbuf;
3053 }
3054 
3055 /*
3056  * freetrans()	-- Free a transaction gotten previously through getaiop.
3057  *		Puts the transaction struct back on the appropriate list for
3058  *		later use.  Never calls free().
3059  *
3060  * Assumes that SIGINT is blocked.
3061  */
3062 static void
freetrans(aio_trans * transp)3063 freetrans(aio_trans *transp)
3064 {
3065 	/*
3066 	 * free the buffer associated with this AIO if needed
3067 	 */
3068 	if (transp->release == RELEASE)
3069 		freebuf(transp->buffer);
3070 
3071 	/*
3072 	 * Put transaction on the free list
3073 	 */
3074 	transp->next = results.trans;
3075 	results.trans = transp;
3076 }
3077 
3078 /*
3079  * wait_for_write()	-- Wait for an aio write to complete.  Return
3080  *			the transaction structure for that write.
3081  *
3082  * Blocks SIGINT if necessary.
3083  */
3084 aio_trans *
wait_for_write(int block)3085 wait_for_write(int block)
3086 {
3087 	aio_trans	*transp;
3088 	aio_result_t	*resultp;
3089 	static struct timeval  zero_wait = { 0, 0 };
3090 	sigset_t	old_mask;
3091 
3092 	/*
3093 	 * If we know there aren't any outstanding transactions, just return
3094 	 */
3095 	if (results.outstanding == 0)
3096 		return ((aio_trans *) 0);
3097 
3098 	block_sigint(&old_mask);
3099 
3100 	resultp = aiowait(block ? NULL : &zero_wait);
3101 	if (resultp == NULL ||
3102 	    (resultp == (aio_result_t *)-1 && errno == EINVAL)) {
3103 		unblock_sigint(&old_mask);
3104 		return ((aio_trans *) 0);
3105 	}
3106 
3107 	results.outstanding--;
3108 	transp = (aio_trans *)resultp;
3109 
3110 	if (resultp->aio_return != transp->size) {
3111 		if (resultp->aio_return == -1) {
3112 			/*
3113 			 * The aiowrite() may have failed because the
3114 			 * kernel didn't have enough memory to do the job.
3115 			 * Flush all pending writes and try a normal
3116 			 * write().  wtfs_breakup() will call exit if it
3117 			 * fails, so we don't worry about errors here.
3118 			 */
3119 			flush_writes();
3120 			wtfs_breakup(transp->bno, transp->size, transp->buffer);
3121 		} else {
3122 			(void) fprintf(stderr, gettext(
3123 			    "short write (%d of %d bytes) on sector %lld\n"),
3124 			    resultp->aio_return, transp->size,
3125 			    transp->bno);
3126 			/*
3127 			 * Don't unblock SIGINT, to avoid potential
3128 			 * looping due to queued interrupts and
3129 			 * error handling.
3130 			 */
3131 			lockexit(32);
3132 		}
3133 	}
3134 
3135 	resultp->aio_return = 0;
3136 	freetrans(transp);
3137 	unblock_sigint(&old_mask);
3138 	return (transp);
3139 }
3140 
3141 /*
3142  * flush_writes()	-- flush all the outstanding aio writes.
3143  */
3144 static void
flush_writes(void)3145 flush_writes(void)
3146 {
3147 	while (wait_for_write(BLOCK))
3148 		;
3149 }
3150 
3151 /*
3152  * get_aiop()	-- find and return an aio_trans structure on which a new
3153  *		aio can be done.  Blocks on aiowait() if needed.  Reaps
3154  *		all outstanding completed aio's.
3155  *
3156  * Assumes that SIGINT is blocked.
3157  */
3158 aio_trans *
get_aiop()3159 get_aiop()
3160 {
3161 	int i;
3162 	aio_trans *transp;
3163 	aio_trans *prev;
3164 
3165 	/*
3166 	 * initialize aio stuff
3167 	 */
3168 	if (!aio_inited) {
3169 		aio_inited = 1;
3170 
3171 		results.maxpend = 0;
3172 		results.outstanding = 0;
3173 		results.max = MAXAIO;
3174 
3175 		results.trans = (aio_trans *)calloc(results.max,
3176 		    sizeof (aio_trans));
3177 		if (results.trans == NULL) {
3178 			perror("calloc");
3179 			lockexit(32);
3180 		}
3181 
3182 		/*
3183 		 * Initialize the linked list of aio transaction
3184 		 * structures.  Note that the final "next" pointer
3185 		 * will be NULL since we got the buffer from calloc().
3186 		 */
3187 		prev = results.trans;
3188 		for (i = 1; i < results.max; i++) {
3189 			prev->next = &(results.trans[i]);
3190 			prev = prev->next;
3191 		}
3192 	}
3193 
3194 	wait_for_write(NOBLOCK);
3195 	while (results.trans == NULL)
3196 		wait_for_write(BLOCK);
3197 	transp = results.trans;
3198 	results.trans = results.trans->next;
3199 
3200 	transp->next = 0;
3201 	transp->resultbuf.aio_return = AIO_INPROGRESS;
3202 	return (transp);
3203 }
3204 
3205 /*
3206  * read a block from the file system
3207  */
3208 static void
rdfs(diskaddr_t bno,int size,char * bf)3209 rdfs(diskaddr_t bno, int size, char *bf)
3210 {
3211 	int n, saverr;
3212 
3213 	/*
3214 	 * In case we need any data that's pending in an aiowrite(),
3215 	 * we wait for them all to complete before doing a read.
3216 	 */
3217 	flush_writes();
3218 
3219 	/*
3220 	 * Note: the llseek() can succeed, even if the offset is out of range.
3221 	 * It's not until the file i/o operation (the read()) that one knows
3222 	 * for sure if the raw device can handle the offset.
3223 	 */
3224 	if (llseek(fsi, (offset_t)bno * sectorsize, 0) < 0) {
3225 		saverr = errno;
3226 		(void) fprintf(stderr,
3227 		    gettext("seek error on sector %lld: %s\n"),
3228 		    bno, strerror(saverr));
3229 		lockexit(32);
3230 	}
3231 	n = read(fsi, bf, size);
3232 	if (n != size) {
3233 		saverr = errno;
3234 		if (n == -1)
3235 			(void) fprintf(stderr,
3236 			    gettext("read error on sector %lld: %s\n"),
3237 			    bno, strerror(saverr));
3238 		else
3239 			(void) fprintf(stderr, gettext(
3240 			    "short read (%d of %d bytes) on sector %lld\n"),
3241 			    n, size, bno);
3242 		lockexit(32);
3243 	}
3244 }
3245 
3246 /*
3247  * write a block to the file system
3248  */
3249 static void
wtfs(diskaddr_t bno,int size,char * bf)3250 wtfs(diskaddr_t bno, int size, char *bf)
3251 {
3252 	int n, saverr;
3253 
3254 	if (fso == -1)
3255 		return;
3256 
3257 	/*
3258 	 * Note: the llseek() can succeed, even if the offset is out of range.
3259 	 * It's not until the file i/o operation (the write()) that one knows
3260 	 * for sure if the raw device can handle the offset.
3261 	 */
3262 	if (llseek(fso, (offset_t)bno * sectorsize, 0) < 0) {
3263 		saverr = errno;
3264 		(void) fprintf(stderr,
3265 		    gettext("seek error on sector %lld: %s\n"),
3266 		    bno, strerror(saverr));
3267 		lockexit(32);
3268 	}
3269 	if (Nflag)
3270 		return;
3271 	n = write(fso, bf, size);
3272 	if (n != size) {
3273 		saverr = errno;
3274 		if (n == -1)
3275 			(void) fprintf(stderr,
3276 			    gettext("write error on sector %lld: %s\n"),
3277 			    bno, strerror(saverr));
3278 		else
3279 			(void) fprintf(stderr, gettext(
3280 			    "short write (%d of %d bytes) on sector %lld\n"),
3281 			    n, size, bno);
3282 		lockexit(32);
3283 	}
3284 }
3285 
3286 /*
3287  * write a block to the file system -- buffered with aio
3288  */
3289 static void
awtfs(diskaddr_t bno,int size,char * bf,int release)3290 awtfs(diskaddr_t bno, int size, char *bf, int release)
3291 {
3292 	int n;
3293 	aio_trans	*transp;
3294 	sigset_t	old_mask;
3295 
3296 	if (fso == -1)
3297 		return;
3298 
3299 	/*
3300 	 * We need to keep things consistent if we get interrupted,
3301 	 * so defer any expected interrupts for the time being.
3302 	 */
3303 	block_sigint(&old_mask);
3304 
3305 	if (Nflag) {
3306 		if (release == RELEASE)
3307 			freebuf(bf);
3308 	} else {
3309 		transp = get_aiop();
3310 		transp->bno = bno;
3311 		transp->buffer = bf;
3312 		transp->size = size;
3313 		transp->release = release;
3314 
3315 		n = aiowrite(fso, bf, size, (off_t)bno * sectorsize,
3316 		    SEEK_SET, &transp->resultbuf);
3317 
3318 		if (n < 0) {
3319 			/*
3320 			 * The aiowrite() may have failed because the
3321 			 * kernel didn't have enough memory to do the job.
3322 			 * Flush all pending writes and try a normal
3323 			 * write().  wtfs_breakup() will call exit if it
3324 			 * fails, so we don't worry about errors here.
3325 			 */
3326 			flush_writes();
3327 			wtfs_breakup(transp->bno, transp->size, transp->buffer);
3328 			freetrans(transp);
3329 		} else {
3330 			/*
3331 			 * Keep track of our pending writes.
3332 			 */
3333 			results.outstanding++;
3334 			if (results.outstanding > results.maxpend)
3335 				results.maxpend = results.outstanding;
3336 		}
3337 	}
3338 
3339 	unblock_sigint(&old_mask);
3340 }
3341 
3342 
3343 /*
3344  * write a block to the file system, but break it up into sbsize
3345  * chunks to avoid forcing a large amount of memory to be locked down.
3346  * Only used as a fallback when an aio write has failed.
3347  */
3348 static void
wtfs_breakup(diskaddr_t bno,int size,char * bf)3349 wtfs_breakup(diskaddr_t bno, int size, char *bf)
3350 {
3351 	int n, saverr;
3352 	int wsize;
3353 	int block_incr = sbsize / sectorsize;
3354 
3355 	if (size < sbsize)
3356 		wsize = size;
3357 	else
3358 		wsize = sbsize;
3359 
3360 	n = 0;
3361 	while (size) {
3362 		/*
3363 		 * Note: the llseek() can succeed, even if the offset is
3364 		 * out of range.  It's not until the file i/o operation
3365 		 * (the write()) that one knows for sure if the raw device
3366 		 * can handle the offset.
3367 		 */
3368 		if (llseek(fso, (offset_t)bno * sectorsize, 0) < 0) {
3369 			saverr = errno;
3370 			(void) fprintf(stderr,
3371 			    gettext("seek error on sector %lld: %s\n"),
3372 			    bno, strerror(saverr));
3373 			lockexit(32);
3374 		}
3375 
3376 		n = write(fso, bf, wsize);
3377 		if (n == -1) {
3378 			saverr = errno;
3379 			(void) fprintf(stderr,
3380 			    gettext("write error on sector %lld: %s\n"),
3381 			    bno, strerror(saverr));
3382 			lockexit(32);
3383 		}
3384 		if (n != wsize) {
3385 			saverr = errno;
3386 			(void) fprintf(stderr, gettext(
3387 			    "short write (%d of %d bytes) on sector %lld\n"),
3388 			    n, size, bno);
3389 			lockexit(32);
3390 		}
3391 
3392 		bno += block_incr;
3393 		bf += wsize;
3394 		size -= wsize;
3395 		if (size < wsize)
3396 			wsize = size;
3397 	}
3398 }
3399 
3400 
3401 /*
3402  * check if a block is available
3403  */
3404 static int
isblock(struct fs * fs,unsigned char * cp,int h)3405 isblock(struct fs *fs, unsigned char *cp, int h)
3406 {
3407 	unsigned char mask;
3408 
3409 	switch (fs->fs_frag) {
3410 	case 8:
3411 		return (cp[h] == 0xff);
3412 	case 4:
3413 		mask = 0x0f << ((h & 0x1) << 2);
3414 		return ((cp[h >> 1] & mask) == mask);
3415 	case 2:
3416 		mask = 0x03 << ((h & 0x3) << 1);
3417 		return ((cp[h >> 2] & mask) == mask);
3418 	case 1:
3419 		mask = 0x01 << (h & 0x7);
3420 		return ((cp[h >> 3] & mask) == mask);
3421 	default:
3422 		(void) fprintf(stderr, "isblock bad fs_frag %d\n", fs->fs_frag);
3423 		return (0);
3424 	}
3425 }
3426 
3427 /*
3428  * take a block out of the map
3429  */
3430 static void
clrblock(struct fs * fs,unsigned char * cp,int h)3431 clrblock(struct fs *fs, unsigned char *cp, int h)
3432 {
3433 	switch ((fs)->fs_frag) {
3434 	case 8:
3435 		cp[h] = 0;
3436 		return;
3437 	case 4:
3438 		cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2));
3439 		return;
3440 	case 2:
3441 		cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1));
3442 		return;
3443 	case 1:
3444 		cp[h >> 3] &= ~(0x01 << (h & 0x7));
3445 		return;
3446 	default:
3447 		(void) fprintf(stderr,
3448 		    gettext("clrblock: bad fs_frag value %d\n"), fs->fs_frag);
3449 		return;
3450 	}
3451 }
3452 
3453 /*
3454  * put a block into the map
3455  */
3456 static void
setblock(struct fs * fs,unsigned char * cp,int h)3457 setblock(struct fs *fs, unsigned char *cp, int h)
3458 {
3459 	switch (fs->fs_frag) {
3460 	case 8:
3461 		cp[h] = 0xff;
3462 		return;
3463 	case 4:
3464 		cp[h >> 1] |= (0x0f << ((h & 0x1) << 2));
3465 		return;
3466 	case 2:
3467 		cp[h >> 2] |= (0x03 << ((h & 0x3) << 1));
3468 		return;
3469 	case 1:
3470 		cp[h >> 3] |= (0x01 << (h & 0x7));
3471 		return;
3472 	default:
3473 		(void) fprintf(stderr,
3474 		    gettext("setblock: bad fs_frag value %d\n"), fs->fs_frag);
3475 		return;
3476 	}
3477 }
3478 
3479 static void
usage(void)3480 usage(void)
3481 {
3482 	(void) fprintf(stderr,
3483 	    gettext("ufs usage: mkfs [-F FSType] [-V] [-m] [-o options] "
3484 	    "special "				/* param 0 */
3485 	    "size(sectors) \\ \n"));		/* param 1 */
3486 	(void) fprintf(stderr,
3487 	    "[nsect "				/* param 2 */
3488 	    "ntrack "				/* param 3 */
3489 	    "bsize "				/* param 4 */
3490 	    "fragsize "				/* param 5 */
3491 	    "cpg "				/* param 6 */
3492 	    "free "				/* param 7 */
3493 	    "rps "				/* param 8 */
3494 	    "nbpi "				/* param 9 */
3495 	    "opt "				/* param 10 */
3496 	    "apc "				/* param 11 */
3497 	    "gap "				/* param 12 */
3498 	    "nrpos "				/* param 13 */
3499 	    "maxcontig "			/* param 14 */
3500 	    "mtb]\n");				/* param 15 */
3501 	(void) fprintf(stderr,
3502 	    gettext(" -m : dump fs cmd line used to make this partition\n"
3503 	    " -V :print this command line and return\n"
3504 	    " -o :ufs options: :nsect=%d,ntrack=%d,bsize=%d,fragsize=%d\n"
3505 	    " -o :ufs options: :cgsize=%d,free=%d,rps=%d,nbpi=%d,opt=%c\n"
3506 	    " -o :ufs options: :apc=%d,gap=%d,nrpos=%d,maxcontig=%d\n"
3507 	    " -o :ufs options: :mtb=%c,calcsb,calcbinsb\n"
3508 "NOTE that all -o suboptions: must be separated only by commas so as to\n"
3509 "be parsed as a single argument\n"),
3510 	    nsect, ntrack, bsize, fragsize, cpg, sblock.fs_minfree, rps,
3511 	    nbpi, opt, apc, (rotdelay == -1) ? 0 : rotdelay,
3512 	    sblock.fs_nrpos, maxcontig, mtb);
3513 	lockexit(32);
3514 }
3515 
3516 /*ARGSUSED*/
3517 static void
dump_fscmd(char * fsys,int fsi)3518 dump_fscmd(char *fsys, int fsi)
3519 {
3520 	int64_t used, bpcg, inospercg;
3521 	int64_t nbpi;
3522 	uint64_t nbytes64;
3523 
3524 	bzero((char *)&sblock, sizeof (sblock));
3525 	rdfs((diskaddr_t)SBLOCK, SBSIZE, (char *)&sblock);
3526 
3527 	/*
3528 	 * ensure a valid file system and if not, exit with error or else
3529 	 * we will end up computing block numbers etc and dividing by zero
3530 	 * which will cause floating point errors in this routine.
3531 	 */
3532 
3533 	if ((sblock.fs_magic != FS_MAGIC) &&
3534 	    (sblock.fs_magic != MTB_UFS_MAGIC)) {
3535 		(void) fprintf(stderr, gettext(
3536 		    "[not currently a valid file system - bad superblock]\n"));
3537 		lockexit(32);
3538 	}
3539 
3540 	if (sblock.fs_magic == FS_MAGIC &&
3541 	    (sblock.fs_version != UFS_EFISTYLE4NONEFI_VERSION_2 &&
3542 	    sblock.fs_version != UFS_VERSION_MIN)) {
3543 		(void) fprintf(stderr, gettext(
3544 		    "Unknown version of UFS format: %d\n"), sblock.fs_version);
3545 		lockexit(32);
3546 	}
3547 
3548 	if (sblock.fs_magic == MTB_UFS_MAGIC &&
3549 	    (sblock.fs_version > MTB_UFS_VERSION_1 ||
3550 	    sblock.fs_version < MTB_UFS_VERSION_MIN)) {
3551 		(void) fprintf(stderr, gettext(
3552 		    "Unknown version of UFS format: %d\n"), sblock.fs_version);
3553 		lockexit(32);
3554 	}
3555 
3556 	/*
3557 	 * Compute a reasonable nbpi value.
3558 	 * The algorithm for "used" is copied from code
3559 	 * in main() verbatim.
3560 	 * The nbpi equation is taken from main where the
3561 	 * fs_ipg value is set for the last time.  The INOPB(...) - 1
3562 	 * is used to account for the roundup.
3563 	 * The problem is that a range of nbpi values map to
3564 	 * the same file system layout.  So it is not possible
3565 	 * to calculate the exact value specified when the file
3566 	 * system was created.  So instead we determine the top
3567 	 * end of the range of values.
3568 	 */
3569 	bpcg = sblock.fs_spc * sectorsize;
3570 	inospercg = (int64_t)roundup(bpcg / sizeof (struct dinode),
3571 	    INOPB(&sblock));
3572 	if (inospercg > MAXIpG(&sblock))
3573 		inospercg = MAXIpG(&sblock);
3574 	used = (int64_t)
3575 	    (sblock.fs_iblkno + inospercg / INOPF(&sblock)) * NSPF(&sblock);
3576 	used *= sectorsize;
3577 	nbytes64 = (uint64_t)sblock.fs_cpg * bpcg - used;
3578 
3579 	/*
3580 	 * The top end of the range of values for nbpi may not be
3581 	 * a valid command line value for mkfs. Report the bottom
3582 	 * end instead.
3583 	 */
3584 	nbpi = (int64_t)(nbytes64 / (sblock.fs_ipg));
3585 
3586 	(void) fprintf(stdout, gettext("mkfs -F ufs -o "), fsys);
3587 	(void) fprintf(stdout, "nsect=%d,ntrack=%d,",
3588 	    sblock.fs_nsect, sblock.fs_ntrak);
3589 	(void) fprintf(stdout, "bsize=%d,fragsize=%d,cgsize=%d,free=%d,",
3590 	    sblock.fs_bsize, sblock.fs_fsize, sblock.fs_cpg, sblock.fs_minfree);
3591 	(void) fprintf(stdout, "rps=%d,nbpi=%lld,opt=%c,apc=%d,gap=%d,",
3592 	    sblock.fs_rps, nbpi, (sblock.fs_optim == FS_OPTSPACE) ? 's' : 't',
3593 	    (sblock.fs_ntrak * sblock.fs_nsect) - sblock.fs_spc,
3594 	    sblock.fs_rotdelay);
3595 	(void) fprintf(stdout, "nrpos=%d,maxcontig=%d,mtb=%c ",
3596 	    sblock.fs_nrpos, sblock.fs_maxcontig,
3597 	    ((sblock.fs_magic == MTB_UFS_MAGIC) ? 'y' : 'n'));
3598 	(void) fprintf(stdout, "%s %lld\n", fsys,
3599 	    fsbtodb(&sblock, sblock.fs_size));
3600 
3601 	bzero((char *)&sblock, sizeof (sblock));
3602 }
3603 
3604 /* number ************************************************************* */
3605 /*									*/
3606 /* Convert a numeric string arg to binary				*/
3607 /*									*/
3608 /* Args:	d_value - default value, if have parse error		*/
3609 /*		param - the name of the argument, for error messages	*/
3610 /*		flags - parser state and what's allowed in the arg	*/
3611 /* Global arg:  string - pointer to command arg				*/
3612 /*									*/
3613 /* Valid forms: 123 | 123k | 123*123 | 123x123				*/
3614 /*									*/
3615 /* Return:	converted number					*/
3616 /*									*/
3617 /* ******************************************************************** */
3618 
3619 static uint64_t
number(uint64_t d_value,char * param,int flags)3620 number(uint64_t d_value, char *param, int flags)
3621 {
3622 	char *cs;
3623 	uint64_t n, t;
3624 	uint64_t cut = BIG / 10;    /* limit to avoid overflow */
3625 	int minus = 0;
3626 
3627 	cs = string;
3628 	if (*cs == '-') {
3629 		minus = 1;
3630 		cs += 1;
3631 	}
3632 	if ((*cs < '0') || (*cs > '9')) {
3633 		goto bail_out;
3634 	}
3635 	n = 0;
3636 	while ((*cs >= '0') && (*cs <= '9') && (n <= cut)) {
3637 		n = n*10 + *cs++ - '0';
3638 	}
3639 	if (minus)
3640 		n = -n;
3641 	for (;;) {
3642 		switch (*cs++) {
3643 		case 'k':
3644 			if (flags & ALLOW_END_ONLY)
3645 				goto bail