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
 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)) == NULL) {
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
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
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
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
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
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
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
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
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 *
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
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
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 *
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
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 *
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
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
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
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
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
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
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
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
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
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
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_out;
3646                         if (n > (BIG / 1024))
3647                                 goto overflow;
3648                         n *= 1024;
3649                         continue;
3650 
3651                 case '*':
3652                 case 'x':
3653                         if (flags & ALLOW_END_ONLY)
3654                                 goto bail_out;
3655                         string = cs;
3656                         t = number(d_value, param, flags);
3657                         if (n > (BIG / t))
3658                                 goto overflow;
3659                         n *= t;
3660                         cs = string + 1; /* adjust for -- below */
3661 
3662                         /* recursion has read rest of expression */
3663                         /* FALLTHROUGH */
3664 
3665                 case ',':
3666                 case '\0':
3667                         cs--;
3668                         string = cs;
3669                         return (n);
3670 
3671                 case '%':
3672                         if (flags & ALLOW_END_ONLY)
3673                                 goto bail_out;
3674                         if (flags & ALLOW_PERCENT) {
3675                                 flags &= ~ALLOW_PERCENT;
3676                                 flags |= ALLOW_END_ONLY;
3677                                 continue;
3678                         }
3679                         goto bail_out;
3680 
3681                 case 'm':
3682                         if (flags & ALLOW_END_ONLY)
3683                                 goto bail_out;
3684                         if (flags & ALLOW_MS1) {
3685                                 flags &= ~ALLOW_MS1;
3686                                 flags |= ALLOW_MS2;
3687                                 continue;
3688                         }
3689                         goto bail_out;
3690 
3691                 case 's':
3692                         if (flags & ALLOW_END_ONLY)
3693                                 goto bail_out;
3694                         if (flags & ALLOW_MS2) {
3695                                 flags &= ~ALLOW_MS2;
3696                                 flags |= ALLOW_END_ONLY;
3697                                 continue;
3698                         }
3699                         goto bail_out;
3700 
3701                 case '0': case '1': case '2': case '3': case '4':
3702                 case '5': case '6': case '7': case '8': case '9':
3703 overflow:
3704                         (void) fprintf(stderr,
3705                             gettext("mkfs: value for %s overflowed\n"),
3706                             param);
3707                         while ((*cs != '\0') && (*cs != ','))
3708                                 cs++;
3709                         string = cs;
3710                         return (BIG);
3711 
3712                 default:
3713 bail_out:
3714                         (void) fprintf(stderr, gettext(
3715                             "mkfs: bad numeric arg for %s: \"%s\"\n"),
3716                             param, string);
3717                         while ((*cs != '\0') && (*cs != ','))
3718                                 cs++;
3719                         string = cs;
3720                         if (d_value != NO_DEFAULT) {
3721                                 (void) fprintf(stderr,
3722                                     gettext("mkfs: %s reset to default %lld\n"),
3723                                     param, d_value);
3724                                 return (d_value);
3725                         }
3726                         lockexit(2);
3727 
3728                 }
3729         } /* never gets here */
3730 }
3731 
3732 /* match ************************************************************** */
3733 /*                                                                      */
3734 /* Compare two text strings for equality                                */
3735 /*                                                                      */
3736 /* Arg:  s - pointer to string to match with a command arg              */
3737 /* Global arg:  string - pointer to command arg                         */
3738 /*                                                                      */
3739 /* Return:      1 if match, 0 if no match                               */
3740 /*              If match, also reset `string' to point to the text      */
3741 /*              that follows the matching text.                         */
3742 /*                                                                      */
3743 /* ******************************************************************** */
3744 
3745 static int
3746 match(char *s)
3747 {
3748         char *cs;
3749 
3750         cs = string;
3751         while (*cs++ == *s) {
3752                 if (*s++ == '\0') {
3753                         goto true;
3754                 }
3755         }
3756         if (*s != '\0') {
3757                 return (0);
3758         }
3759 
3760 true:
3761         cs--;
3762         string = cs;
3763         return (1);
3764 }
3765 
3766 /*
3767  * GROWFS ROUTINES
3768  */
3769 
3770 /* ARGSUSED */
3771 void
3772 lockexit(int exitstatus)
3773 {
3774         if (Pflag) {
3775                 /* the probe mode neither changes nor locks the filesystem */
3776                 exit(exitstatus);
3777         }
3778 
3779         /*
3780          * flush the dirty cylinder group
3781          */
3782         if (inlockexit == 0) {
3783                 inlockexit = 1;
3784                 flcg();
3785         }
3786 
3787         if (aio_inited) {
3788                 flush_writes();
3789         }
3790 
3791         /*
3792          * make sure the file system is unlocked before exiting
3793          */
3794         if ((inlockexit == 1) && (!isbad)) {
3795                 inlockexit = 2;
3796                 ulockfs();
3797                 /*
3798                  * if logging was enabled, then re-enable it
3799                  */
3800                 if (waslog) {
3801                         if (rl_log_control(fsys, _FIOLOGENABLE) != RL_SUCCESS) {
3802                                 (void) fprintf(stderr, gettext(
3803                                     "failed to re-enable logging\n"));
3804                         }
3805                 }
3806         } else if (grow) {
3807                 if (isbad) {
3808                         (void) fprintf(stderr, gettext(
3809                             "Filesystem is currently inconsistent.  It "
3810                             "must be repaired with fsck(1M)\nbefore being "
3811                             "used.  Use the following command to "
3812                             "do this:\n\n\tfsck %s\n\n"), fsys);
3813 
3814                         if (ismounted) {
3815                                 (void) fprintf(stderr, gettext(
3816                                     "You will be told that the filesystem "
3817                                     "is already mounted, and asked if you\n"
3818                                     "wish to continue.  Answer `yes' to "
3819                                     "this question.\n\n"));
3820                         }
3821 
3822                         (void) fprintf(stderr, gettext(
3823                             "One problem should be reported, that the summary "
3824                             "information is bad.\nYou will then be asked if it "
3825                             "should be salvaged.  Answer `yes' to\nthis "
3826                             "question.\n\n"));
3827                 }
3828 
3829                 if (ismounted) {
3830                         /*
3831                          * In theory, there's no way to get here without
3832                          * isbad also being set, but be robust in the
3833                          * face of future code changes.
3834                          */
3835                         (void) fprintf(stderr, gettext(
3836                             "The filesystem is currently mounted "
3837                             "read-only and write-locked.  "));
3838                         if (isbad) {
3839                                 (void) fprintf(stderr, gettext(
3840                                     "After\nrunning fsck, unlock the "
3841                                     "filesystem and "));
3842                         } else {
3843                                 (void) fprintf(stderr, gettext(
3844                                     "Unlock the filesystem\nand "));
3845                         }
3846 
3847                         (void) fprintf(stderr, gettext(
3848                             "re-enable writing with\nthe following "
3849                             "command:\n\n\tlockfs -u %s\n\n"), directory);
3850                 }
3851         }
3852 
3853         exit(exitstatus);
3854 }
3855 
3856 void
3857 randomgeneration()
3858 {
3859         int              i;
3860         struct dinode   *dp;
3861 
3862         /*
3863          * always perform fsirand(1) function... newfs will notice that
3864          * the inodes have been randomized and will not call fsirand itself
3865          */
3866         for (i = 0, dp = zino; i < sblock.fs_inopb; ++i, ++dp)
3867                 IRANDOMIZE(&dp->di_ic);
3868 }
3869 
3870 /*
3871  * Check the size of the summary information.
3872  * Fields in sblock are not changed in this function.
3873  *
3874  * For an 8K filesystem block, the maximum number of cylinder groups is 16384.
3875  *     MAXCSBUFS {32}  *   8K  {FS block size}
3876  *                         divided by (sizeof csum) {16}
3877  *
3878  * Note that MAXCSBUFS is not used in the kernel; as of Solaris 2.6 build 32,
3879  * this is the only place where it's referenced.
3880  */
3881 void
3882 checksummarysize()
3883 {
3884         diskaddr_t      dmax;
3885         diskaddr_t      dmin;
3886         int64_t cg0frags;
3887         int64_t cg0blocks;
3888         int64_t maxncg;
3889         int64_t maxfrags;
3890         uint64_t        fs_size;
3891         uint64_t maxfs_blocks; /* filesystem blocks for max filesystem size */
3892 
3893         /*
3894          * compute the maximum summary info size
3895          */
3896         dmin = cgdmin(&sblock, 0);
3897         dmax = cgbase(&sblock, 0) + sblock.fs_fpg;
3898         fs_size = (grow) ? grow_fs_size : sblock.fs_size;
3899         if (dmax > fs_size)
3900                 dmax = fs_size;
3901         cg0frags  = dmax - dmin;
3902         cg0blocks = cg0frags / sblock.fs_frag;
3903         cg0frags = cg0blocks * sblock.fs_frag;
3904         maxncg   = (longlong_t)cg0blocks *
3905             (longlong_t)(sblock.fs_bsize / sizeof (struct csum));
3906 
3907         maxfs_blocks = FS_MAX;
3908 
3909         if (maxncg > ((longlong_t)maxfs_blocks / (longlong_t)sblock.fs_fpg) + 1)
3910                 maxncg = ((longlong_t)maxfs_blocks /
3911                     (longlong_t)sblock.fs_fpg) + 1;
3912 
3913         maxfrags = maxncg * (longlong_t)sblock.fs_fpg;
3914 
3915         if (maxfrags > maxfs_blocks)
3916                 maxfrags = maxfs_blocks;
3917 
3918 
3919         /*
3920          * remember for later processing in extendsummaryinfo()
3921          */
3922         if (test)
3923                 grow_sifrag = dmin + (cg0blocks * sblock.fs_frag);
3924         if (testfrags == 0)
3925                 testfrags = cg0frags;
3926         if (testforce)
3927                 if (testfrags > cg0frags) {
3928                         (void) fprintf(stderr,
3929                             gettext("Too many test frags (%lld); "
3930                             "try %lld\n"), testfrags, cg0frags);
3931                         lockexit(32);
3932                 }
3933 
3934         /*
3935          * if summary info is too large (too many cg's) tell the user and exit
3936          */
3937         if ((longlong_t)sblock.fs_size > maxfrags) {
3938                 (void) fprintf(stderr, gettext(
3939                     "Too many cylinder groups with %llu sectors;\n    try "
3940                     "increasing cgsize, or decreasing fssize to %llu\n"),
3941                     fsbtodb(&sblock, (uint64_t)sblock.fs_size),
3942                     fsbtodb(&sblock, (uint64_t)maxfrags));
3943                 lockexit(32);
3944         }
3945 }
3946 
3947 /*
3948  * checksblock() has two uses:
3949  *      - One is to sanity test the superblock and is used when newfs(1M)
3950  *        is invoked with the "-N" option. If any discrepancy was found,
3951  *        just return whatever error was found and do not exit.
3952  *      - the other use of it is in places where you expect the superblock
3953  *        to be sane, and if it isn't, then we exit.
3954  * Which of the above two actions to take is indicated with the second argument.
3955  */
3956 
3957 int
3958 checksblock(struct fs sb, int proceed)
3959 {
3960         int err = 0;
3961         char *errmsg;
3962 
3963         if ((sb.fs_magic != FS_MAGIC) && (sb.fs_magic != MTB_UFS_MAGIC)) {
3964                 err = 1;
3965                 errmsg = gettext("Bad superblock; magic number wrong\n");
3966         } else if ((sb.fs_magic == FS_MAGIC &&
3967             (sb.fs_version != UFS_EFISTYLE4NONEFI_VERSION_2 &&
3968             sb.fs_version != UFS_VERSION_MIN)) ||
3969             (sb.fs_magic == MTB_UFS_MAGIC &&
3970             (sb.fs_version > MTB_UFS_VERSION_1 ||
3971             sb.fs_version < MTB_UFS_VERSION_MIN))) {
3972                 err = 2;
3973                 errmsg = gettext("Unrecognized version of UFS\n");
3974         } else if (sb.fs_ncg < 1) {
3975                 err = 3;
3976                 errmsg = gettext("Bad superblock; ncg out of range\n");
3977         } else if (sb.fs_cpg < 1) {
3978                 err = 4;
3979                 errmsg = gettext("Bad superblock; cpg out of range\n");
3980         } else if (sb.fs_ncg * sb.fs_cpg < sb.fs_ncyl ||
3981             (sb.fs_ncg - 1) * sb.fs_cpg >= sb.fs_ncyl) {
3982                 err = 5;
3983                 errmsg = gettext("Bad superblock; ncyl out of range\n");
3984         } else if (sb.fs_sbsize <= 0 || sb.fs_sbsize > sb.fs_bsize) {
3985                 err = 6;
3986                 errmsg = gettext("Bad superblock; superblock size out of "
3987                     "range\n");
3988         }
3989 
3990         if (proceed) {
3991                 if (err) dprintf(("%s", errmsg));
3992                 return (err);
3993         }
3994 
3995         if (err) {
3996                 fprintf(stderr, "%s", errmsg);
3997                 lockexit(32);
3998         }
3999         return (32);
4000 }
4001 
4002 /*
4003  * Roll the embedded log, if any, and set up the global variables
4004  * islog and islogok.
4005  */
4006 static void
4007 logsetup(char *devstr)
4008 {
4009         void            *buf, *ud_buf;
4010         extent_block_t  *ebp;
4011         ml_unit_t       *ul;
4012         ml_odunit_t     *ud;
4013 
4014         /*
4015          * Does the superblock indicate that we are supposed to have a log ?
4016          */
4017         if (sblock.fs_logbno == 0) {
4018                 /*
4019                  * No log present, nothing to do.
4020                  */
4021                 islog = 0;
4022                 islogok = 0;
4023                 return;
4024         } else {
4025                 /*
4026                  * There's a log in a yet unknown state, attempt to roll it.
4027                  */
4028                 islogok = 0;
4029 
4030                 /*
4031                  * We failed to roll the log, bail out.
4032                  */
4033                 if (rl_roll_log(devstr) != RL_SUCCESS)
4034                         return;
4035 
4036                 islog = 1;
4037 
4038                 /* log is not okay; check the fs */
4039                 if ((FSOKAY != (sblock.fs_state + sblock.fs_time)) ||
4040                     (sblock.fs_clean != FSLOG))
4041                         return;
4042 
4043                 /* get the log allocation block */
4044                 buf = (void *)malloc(DEV_BSIZE);
4045                 if (buf == (void *) NULL)
4046                         return;
4047 
4048                 ud_buf = (void *)malloc(DEV_BSIZE);
4049                 if (ud_buf == (void *) NULL) {
4050                         free(buf);
4051                         return;
4052                 }
4053 
4054                 rdfs((diskaddr_t)logbtodb(&sblock, sblock.fs_logbno),
4055                     DEV_BSIZE, buf);
4056                 ebp = (extent_block_t *)buf;
4057 
4058                 /* log allocation block is not okay; check the fs */
4059                 if (ebp->type != LUFS_EXTENTS) {
4060                         free(buf);
4061                         free(ud_buf);
4062                         return;
4063                 }
4064 
4065                 /* get the log state block(s) */
4066                 rdfs((diskaddr_t)logbtodb(&sblock, ebp->extents[0].pbno),
4067                     DEV_BSIZE, ud_buf);
4068                 ud = (ml_odunit_t *)ud_buf;
4069                 ul = (ml_unit_t *)malloc(sizeof (*ul));
4070                 ul->un_ondisk = *ud;
4071 
4072                 /* log state is okay */
4073                 if ((ul->un_chksum == ul->un_head_ident + ul->un_tail_ident) &&
4074                     (ul->un_version == LUFS_VERSION_LATEST) &&
4075                     (ul->un_badlog == 0))
4076                         islogok = 1;
4077                 free(ud_buf);
4078                 free(buf);
4079                 free(ul);
4080         }
4081 }
4082 
4083 void
4084 growinit(char *devstr)
4085 {
4086         int     i;
4087         char    buf[DEV_BSIZE];
4088 
4089         /*
4090          * Read and verify the superblock
4091          */
4092         rdfs((diskaddr_t)(SBOFF / sectorsize), (int)sbsize, (char *)&sblock);
4093         (void) checksblock(sblock, 0);
4094         if (sblock.fs_postblformat != FS_DYNAMICPOSTBLFMT) {
4095                 (void) fprintf(stderr,
4096                     gettext("old file system format; can't growfs\n"));
4097                 lockexit(32);
4098         }
4099 
4100         /*
4101          * can't shrink a file system
4102          */
4103         grow_fssize = fsbtodb(&sblock, (uint64_t)sblock.fs_size);
4104         if (fssize_db < grow_fssize) {
4105                 (void) fprintf(stderr,
4106                     gettext("%lld sectors < current size of %lld sectors\n"),
4107                     fssize_db, grow_fssize);
4108                 lockexit(32);
4109         }
4110 
4111         /*
4112          * can't grow a system to over a terabyte unless it was set up
4113          * as an MTB UFS file system.
4114          */
4115         if (mtb == 'y' && sblock.fs_magic != MTB_UFS_MAGIC) {
4116                 if (fssize_db >= SECTORS_PER_TERABYTE) {
4117                         (void) fprintf(stderr, gettext(
4118 "File system was not set up with the multi-terabyte format.\n"));
4119                         (void) fprintf(stderr, gettext(
4120 "Its size cannot be increased to a terabyte or more.\n"));
4121                 } else {
4122                         (void) fprintf(stderr, gettext(
4123 "Cannot convert file system to multi-terabyte format.\n"));
4124                 }
4125                 lockexit(32);
4126         }
4127 
4128         logsetup(devstr);
4129 
4130         /*
4131          * can't growfs when logging device has errors
4132          */
4133         if ((islog && !islogok) ||
4134             ((FSOKAY == (sblock.fs_state + sblock.fs_time)) &&
4135             (sblock.fs_clean == FSLOG && !islog))) {
4136                 (void) fprintf(stderr,
4137                     gettext("logging device has errors; can't growfs\n"));
4138                 lockexit(32);
4139         }
4140 
4141         /*
4142          * disable ufs logging for growing
4143          */
4144         if (islog) {
4145                 if (rl_log_control(devstr, _FIOLOGDISABLE) != RL_SUCCESS) {
4146                         (void) fprintf(stderr, gettext(
4147                             "failed to disable logging\n"));
4148                         lockexit(32);
4149                 }
4150                 islog = 0;
4151                 waslog = 1;
4152         }
4153 
4154         /*
4155          * if mounted write lock the file system to be grown
4156          */
4157         if (ismounted)
4158                 wlockfs();
4159 
4160         /*
4161          * refresh dynamic superblock state - disabling logging will have
4162          * changed the amount of free space available in the file system
4163          */
4164         rdfs((diskaddr_t)(SBOFF / sectorsize), sbsize, (char *)&sblock);
4165 
4166         /*
4167          * make sure device is big enough
4168          */
4169         rdfs((diskaddr_t)fssize_db - 1, DEV_BSIZE, buf);
4170         wtfs((diskaddr_t)fssize_db - 1, DEV_BSIZE, buf);
4171 
4172         /*
4173          * read current summary information
4174          */
4175         grow_fscs = read_summaryinfo(&sblock);
4176 
4177         /*
4178          * save some current size related fields from the superblock
4179          * These are used in extendsummaryinfo()
4180          */
4181         grow_fs_size    = sblock.fs_size;
4182         grow_fs_ncg     = sblock.fs_ncg;
4183         grow_fs_csaddr  = (diskaddr_t)sblock.fs_csaddr;
4184         grow_fs_cssize  = sblock.fs_cssize;
4185 
4186         /*
4187          * save and reset the clean flag
4188          */
4189         if (FSOKAY == (sblock.fs_state + sblock.fs_time))
4190                 grow_fs_clean = sblock.fs_clean;
4191         else
4192                 grow_fs_clean = FSBAD;
4193         sblock.fs_clean = FSBAD;
4194         sblock.fs_state = FSOKAY - sblock.fs_time;
4195         isbad = 1;
4196         wtfs((diskaddr_t)(SBOFF / sectorsize), sbsize, (char *)&sblock);
4197 }
4198 
4199 void
4200 checkdev(char *rdev, char *bdev)
4201 {
4202         struct stat64   statarea;
4203 
4204         if (stat64(bdev, &statarea) < 0) {
4205                 (void) fprintf(stderr, gettext("can't check mount point; "));
4206                 (void) fprintf(stderr, gettext("can't stat %s\n"), bdev);
4207                 lockexit(32);
4208         }
4209         if ((statarea.st_mode & S_IFMT) != S_IFBLK) {
4210                 (void) fprintf(stderr, gettext(
4211                     "can't check mount point; %s is not a block device\n"),
4212                     bdev);
4213                 lockexit(32);
4214         }
4215         if (stat64(rdev, &statarea) < 0) {
4216                 (void) fprintf(stderr, gettext("can't stat %s\n"), rdev);
4217                 lockexit(32);
4218         }
4219         if ((statarea.st_mode & S_IFMT) != S_IFCHR) {
4220                 (void) fprintf(stderr,
4221                     gettext("%s is not a character device\n"), rdev);
4222                 lockexit(32);
4223         }
4224 }
4225 
4226 void
4227 checkmount(struct mnttab *mntp, char *bdevname)
4228 {
4229         struct stat64   statdir;
4230         struct stat64   statdev;
4231 
4232         if (strcmp(bdevname, mntp->mnt_special) == 0) {
4233                 if (stat64(mntp->mnt_mountp, &statdir) == -1) {
4234                         (void) fprintf(stderr, gettext("can't stat %s\n"),
4235                             mntp->mnt_mountp);
4236                         lockexit(32);
4237                 }
4238                 if (stat64(mntp->mnt_special, &statdev) == -1) {
4239                         (void) fprintf(stderr, gettext("can't stat %s\n"),
4240                             mntp->mnt_special);
4241                         lockexit(32);
4242                 }
4243                 if (statdir.st_dev != statdev.st_rdev) {
4244                         (void) fprintf(stderr, gettext(
4245                             "%s is not mounted on %s; mnttab(4) wrong\n"),
4246                             mntp->mnt_special, mntp->mnt_mountp);
4247                         lockexit(32);
4248                 }
4249                 ismounted = 1;
4250                 if (directory) {
4251                         if (strcmp(mntp->mnt_mountp, directory) != 0) {
4252                                 (void) fprintf(stderr,
4253                                     gettext("%s is mounted on %s, not %s\n"),
4254                                     bdevname, mntp->mnt_mountp, directory);
4255                                 lockexit(32);
4256                         }
4257                 } else {
4258                         if (grow)
4259                                 (void) fprintf(stderr, gettext(
4260                                     "%s is mounted on %s; can't growfs\n"),
4261                                     bdevname, mntp->mnt_mountp);
4262                         else
4263                                 (void) fprintf(stderr,
4264                                     gettext("%s is mounted, can't mkfs\n"),
4265                                     bdevname);
4266                         lockexit(32);
4267                 }
4268         }
4269 }
4270 
4271 struct dinode   *dibuf  = 0;
4272 diskaddr_t      difrag  = 0;
4273 
4274 struct dinode *
4275 gdinode(ino_t ino)
4276 {
4277         /*
4278          * read the block of inodes containing inode number ino
4279          */
4280         if (dibuf == 0)
4281                 dibuf = (struct dinode *)malloc((unsigned)sblock.fs_bsize);
4282         if (itod(&sblock, ino) != difrag) {
4283                 difrag = itod(&sblock, ino);
4284                 rdfs(fsbtodb(&sblock, (uint64_t)difrag), (int)sblock.fs_bsize,
4285                     (char *)dibuf);
4286         }
4287         return (dibuf + (ino % INOPB(&sblock)));
4288 }
4289 
4290 /*
4291  * structure that manages the frags we need for extended summary info
4292  *      These frags can be:
4293  *              free
4294  *              data  block
4295  *              alloc block
4296  */
4297 struct csfrag {
4298         struct csfrag   *next;          /* next entry */
4299         daddr32_t        ofrag;         /* old frag */
4300         daddr32_t        nfrag;         /* new frag */
4301         long             cylno;         /* cylno of nfrag */
4302         long             frags;         /* number of frags */
4303         long             size;          /* size in bytes */
4304         ino_t            ino;           /* inode number */
4305         long             fixed;         /* Boolean - Already fixed? */
4306 };
4307 struct csfrag   *csfrag;                /* state unknown */
4308 struct csfrag   *csfragino;             /* frags belonging to an inode */
4309 struct csfrag   *csfragfree;            /* frags that are free */
4310 
4311 daddr32_t maxcsfrag     = 0;            /* maximum in range */
4312 daddr32_t mincsfrag     = 0x7fffffff;   /* minimum in range */
4313 
4314 int
4315 csfraginrange(daddr32_t frag)
4316 {
4317         return ((frag >= mincsfrag) && (frag <= maxcsfrag));
4318 }
4319 
4320 struct csfrag *
4321 findcsfrag(daddr32_t frag, struct csfrag **cfap)
4322 {
4323         struct csfrag   *cfp;
4324 
4325         if (!csfraginrange(frag))
4326                 return (NULL);
4327 
4328         for (cfp = *cfap; cfp; cfp = cfp->next)
4329                 if (cfp->ofrag == frag)
4330                         return (cfp);
4331         return (NULL);
4332 }
4333 
4334 void
4335 checkindirect(ino_t ino, daddr32_t *fragsp, daddr32_t frag, int level)
4336 {
4337         int                     i;
4338         int                     ne      = sblock.fs_bsize / sizeof (daddr32_t);
4339         daddr32_t                       fsb[MAXBSIZE / sizeof (daddr32_t)];
4340 
4341         if (frag == 0)
4342                 return;
4343 
4344         rdfs(fsbtodb(&sblock, frag), (int)sblock.fs_bsize,
4345             (char *)fsb);
4346 
4347         checkdirect(ino, fragsp, fsb, sblock.fs_bsize / sizeof (daddr32_t));
4348 
4349         if (level)
4350                 for (i = 0; i < ne && *fragsp; ++i)
4351                         checkindirect(ino, fragsp, fsb[i], level-1);
4352 }
4353 
4354 void
4355 addcsfrag(ino_t ino, daddr32_t frag, struct csfrag **cfap)
4356 {
4357         struct csfrag   *cfp, *curr, *prev;
4358 
4359         /*
4360          * establish a range for faster checking in csfraginrange()
4361          */
4362         if (frag > maxcsfrag)
4363                 maxcsfrag = frag;
4364         if (frag < mincsfrag)
4365                 mincsfrag = frag;
4366 
4367         /*
4368          * if this frag belongs to an inode and is not the start of a block
4369          *      then see if it is part of a frag range for this inode
4370          */
4371         if (ino && (frag % sblock.fs_frag))
4372                 for (cfp = *cfap; cfp; cfp = cfp->next) {
4373                         if (ino != cfp->ino)
4374                                 continue;
4375                         if (frag != cfp->ofrag + cfp->frags)
4376                                 continue;
4377                         cfp->frags++;
4378                         cfp->size += sblock.fs_fsize;
4379                         return;
4380                 }
4381         /*
4382          * allocate a csfrag entry and insert it in an increasing order into the
4383          * specified list
4384          */
4385         cfp = (struct csfrag *)calloc(1, sizeof (struct csfrag));
4386         cfp->ino     = ino;
4387         cfp->ofrag   = frag;
4388         cfp->frags   = 1;
4389         cfp->size    = sblock.fs_fsize;
4390         for (prev = NULL, curr = *cfap; curr != NULL;
4391             prev = curr, curr = curr->next) {
4392                 if (frag < curr->ofrag) {
4393                         cfp->next = curr;
4394                         if (prev)
4395                                 prev->next = cfp;    /* middle element */
4396                         else
4397                                 *cfap = cfp;            /* first element */
4398                         break;
4399                 }
4400                 if (curr->next == NULL) {
4401                         curr->next = cfp;            /* last element */
4402                         break;
4403                 }
4404         }
4405         if (*cfap == NULL)      /* will happen only once */
4406                 *cfap = cfp;
4407 }
4408 
4409 void
4410 delcsfrag(daddr32_t frag, struct csfrag **cfap)
4411 {
4412         struct csfrag   *cfp;
4413         struct csfrag   **cfpp;
4414 
4415         /*
4416          * free up entry whose beginning frag matches
4417          */
4418         for (cfpp = cfap; *cfpp; cfpp = &(*cfpp)->next) {
4419                 if (frag == (*cfpp)->ofrag) {
4420                         cfp = *cfpp;
4421                         *cfpp = (*cfpp)->next;
4422                         free((char *)cfp);
4423                         return;
4424                 }
4425         }
4426 }
4427 
4428 /*
4429  * See whether any of the direct blocks in the array pointed by "db" and of
4430  * length "ne" are within the range of frags needed to extend the cylinder
4431  * summary. If so, remove those frags from the "as-yet-unclassified" list
4432  * (csfrag) and add them to the "owned-by-inode" list (csfragino).
4433  * For each such frag found, decrement the frag count pointed to by fragsp.
4434  * "ino" is the inode that contains (either directly or indirectly) the frags
4435  * being checked.
4436  */
4437 void
4438 checkdirect(ino_t ino, daddr32_t *fragsp, daddr32_t *db, int ne)
4439 {
4440         int      i;
4441         int      j;
4442         int      found;
4443         diskaddr_t       frag;
4444 
4445         /*
4446          * scan for allocation within the new summary info range
4447          */
4448         for (i = 0; i < ne && *fragsp; ++i) {
4449                 if ((frag = *db++) != 0) {
4450                         found = 0;
4451                         for (j = 0; j < sblock.fs_frag && *fragsp; ++j) {
4452                                 if (found || (found = csfraginrange(frag))) {
4453                                         addcsfrag(ino, frag, &csfragino);
4454                                         delcsfrag(frag, &csfrag);
4455                                 }
4456                                 ++frag;
4457                                 --(*fragsp);
4458                         }
4459                 }
4460         }
4461 }
4462 
4463 void
4464 findcsfragino()
4465 {
4466         int              i;
4467         int              j;
4468         daddr32_t                frags;
4469         struct dinode   *dp;
4470 
4471         /*
4472          * scan all old inodes looking for allocations in the new
4473          * summary info range.  Move the affected frag from the
4474          * generic csfrag list onto the `owned-by-inode' list csfragino.
4475          */
4476         for (i = UFSROOTINO; i < grow_fs_ncg*sblock.fs_ipg && csfrag; ++i) {
4477                 dp = gdinode((ino_t)i);
4478                 switch (dp->di_mode & IFMT) {
4479                         case IFSHAD     :
4480                         case IFLNK      :
4481                         case IFDIR      :
4482                         case IFREG      : break;
4483                         default         : continue;
4484                 }
4485 
4486                 frags   = dbtofsb(&sblock, dp->di_blocks);
4487 
4488                 checkdirect((ino_t)i, &frags, &dp->di_db[0], NDADDR+NIADDR);
4489                 for (j = 0; j < NIADDR && frags; ++j) {
4490                         /* Negate the block if its an fallocate'd block */
4491                         if (dp->di_ib[j] < 0 && dp->di_ib[j] != UFS_HOLE)
4492                                 checkindirect((ino_t)i, &frags,
4493                                     -(dp->di_ib[j]), j);
4494                         else
4495                                 checkindirect((ino_t)i, &frags,
4496                                     dp->di_ib[j], j);
4497                 }
4498         }
4499 }
4500 
4501 void
4502 fixindirect(daddr32_t frag, int level)
4503 {
4504         int                      i;
4505         int                      ne     = sblock.fs_bsize / sizeof (daddr32_t);
4506         daddr32_t                       fsb[MAXBSIZE / sizeof (daddr32_t)];
4507 
4508         if (frag == 0)
4509                 return;
4510 
4511         rdfs(fsbtodb(&sblock, (uint64_t)frag), (int)sblock.fs_bsize,
4512             (char *)fsb);
4513 
4514         fixdirect((caddr_t)fsb, frag, fsb, ne);
4515 
4516         if (level)
4517                 for (i = 0; i < ne; ++i)
4518                         fixindirect(fsb[i], level-1);
4519 }
4520 
4521 void
4522 fixdirect(caddr_t bp, daddr32_t frag, daddr32_t *db, int ne)
4523 {
4524         int      i;
4525         struct csfrag   *cfp;
4526 
4527         for (i = 0; i < ne; ++i, ++db) {
4528                 if (*db == 0)
4529                         continue;
4530                 if ((cfp = findcsfrag(*db, &csfragino)) == NULL)
4531                         continue;
4532                 *db = cfp->nfrag;
4533                 cfp->fixed = 1;
4534                 wtfs(fsbtodb(&sblock, (uint64_t)frag), (int)sblock.fs_bsize,
4535                     bp);
4536         }
4537 }
4538 
4539 void
4540 fixcsfragino()
4541 {
4542         int              i;
4543         struct dinode   *dp;
4544         struct csfrag   *cfp;
4545 
4546         for (cfp = csfragino; cfp; cfp = cfp->next) {
4547                 if (cfp->fixed)
4548                         continue;
4549                 dp = gdinode((ino_t)cfp->ino);
4550                 fixdirect((caddr_t)dibuf, difrag, dp->di_db, NDADDR+NIADDR);
4551                 for (i = 0; i < NIADDR; ++i)
4552                         fixindirect(dp->di_ib[i], i);
4553         }
4554 }
4555 
4556 /*
4557  * Read the cylinders summary information specified by settings in the
4558  * passed 'fs' structure into a new allocated array of csum structures.
4559  * The caller is responsible for freeing the returned array.
4560  * Return a pointer to an array of csum structures.
4561  */
4562 static struct csum *
4563 read_summaryinfo(struct fs *fsp)
4564 {
4565         struct csum     *csp;
4566         int             i;
4567 
4568         if ((csp = malloc((size_t)fsp->fs_cssize)) == NULL) {
4569                 (void) fprintf(stderr, gettext("cannot create csum list,"
4570                     " not enough memory\n"));
4571                 exit(32);
4572         }
4573 
4574         for (i = 0; i < fsp->fs_cssize; i += fsp->fs_bsize) {
4575                 rdfs(fsbtodb(fsp,
4576                     (uint64_t)(fsp->fs_csaddr + numfrags(fsp, i))),
4577                     (int)(fsp->fs_cssize - i < fsp->fs_bsize ?
4578                     fsp->fs_cssize - i : fsp->fs_bsize), ((caddr_t)csp) + i);
4579         }
4580 
4581         return (csp);
4582 }
4583 
4584 /*
4585  * Check the allocation of fragments that are to be made part of a csum block.
4586  * A fragment is allocated if it is either in the csfragfree list or, it is
4587  * in the csfragino list and has new frags associated with it.
4588  * Return the number of allocated fragments.
4589  */
4590 int64_t
4591 checkfragallocated(daddr32_t frag)
4592 {
4593         struct  csfrag  *cfp;
4594         /*
4595          * Since the lists are sorted we can break the search if the asked
4596          * frag is smaller then the one in the list.
4597          */
4598         for (cfp = csfragfree; cfp != NULL && frag >= cfp->ofrag;
4599             cfp = cfp->next) {
4600                 if (frag == cfp->ofrag)
4601                         return (1);
4602         }
4603         for (cfp = csfragino; cfp != NULL && frag >= cfp->ofrag;
4604             cfp = cfp->next) {
4605                 if (frag == cfp->ofrag && cfp->nfrag != 0)
4606                         return (cfp->frags);
4607         }
4608 
4609         return (0);
4610 }
4611 
4612 /*
4613  * Figure out how much the filesystem can be grown. The limiting factor is
4614  * the available free space needed to extend the cg summary info block.
4615  * The free space is determined in three steps:
4616  * - Try to extend the cg summary block to the required size.
4617  * - Find free blocks in last cg.
4618  * - Find free space in the last already allocated fragment of the summary info
4619  *   block, and use it for additional csum structures.
4620  * Return the maximum size of the new filesystem or 0 if it can't be grown.
4621  * Please note that this function leaves the global list pointers csfrag,
4622  * csfragfree, and csfragino initialized, and the caller is responsible for
4623  * freeing the lists.
4624  */
4625 diskaddr_t
4626 probe_summaryinfo()
4627 {
4628         /* fragments by which the csum block can be extended. */
4629         int64_t         growth_csum_frags = 0;
4630         /* fragments by which the filesystem can be extended. */
4631         int64_t         growth_fs_frags = 0;
4632         int64_t         new_fs_cssize;  /* size of csum blk in the new FS */
4633         int64_t         new_fs_ncg;     /* number of cg in the new FS */
4634         int64_t         spare_csum;
4635         daddr32_t       oldfrag_daddr;
4636         daddr32_t       newfrag_daddr;
4637         daddr32_t       daddr;
4638         int             i;
4639 
4640         /*
4641          * read and verify the superblock
4642          */
4643         rdfs((diskaddr_t)(SBOFF / sectorsize), (int)sbsize, (char *)&sblock);
4644         (void) checksblock(sblock, 0);
4645 
4646         /*
4647          * check how much we can extend the cg summary info block
4648          */
4649 
4650         /*
4651          * read current summary information
4652          */
4653         fscs = read_summaryinfo(&sblock);
4654 
4655         /*
4656          * build list of frags needed for cg summary info block extension
4657          */
4658         oldfrag_daddr = howmany(sblock.fs_cssize, sblock.fs_fsize) +
4659             sblock.fs_csaddr;
4660         new_fs_ncg = howmany(dbtofsb(&sblock, fssize_db), sblock.fs_fpg);
4661         new_fs_cssize = fragroundup(&sblock, new_fs_ncg * sizeof (struct csum));
4662         newfrag_daddr = howmany(new_fs_cssize, sblock.fs_fsize) +
4663             sblock.fs_csaddr;
4664         /*
4665          * add all of the frags that are required to grow the cyl summary to the
4666          * csfrag list, which is the generic/unknown list, since at this point
4667          * we don't yet know the state of those frags.
4668          */
4669         for (daddr = oldfrag_daddr; daddr < newfrag_daddr; daddr++)
4670                 addcsfrag((ino_t)0, daddr, &csfrag);
4671 
4672         /*
4673          * filter free fragments and allocate them. Note that the free frags
4674          * must be allocated first otherwise they could be grabbed by
4675          * alloccsfragino() for data frags.
4676          */
4677         findcsfragfree();
4678         alloccsfragfree();
4679 
4680         /*
4681          * filter fragments owned by inodes and allocate them
4682          */
4683         grow_fs_ncg = sblock.fs_ncg; /* findcsfragino() needs this glob. var. */
4684         findcsfragino();
4685         alloccsfragino();
4686 
4687         if (notenoughspace()) {
4688                 /*
4689                  * check how many consecutive fragments could be allocated
4690                  * in both lists.
4691                  */
4692                 int64_t tmp_frags;
4693                 for (daddr = oldfrag_daddr; daddr < newfrag_daddr;
4694                     daddr += tmp_frags) {
4695                         if ((tmp_frags = checkfragallocated(daddr)) > 0)
4696                                 growth_csum_frags += tmp_frags;
4697                         else
4698                                 break;
4699                 }
4700         } else {
4701                 /*
4702                  * We have all we need for the new desired size,
4703                  * so clean up and report back.
4704                  */
4705                 return (fssize_db);
4706         }
4707 
4708         /*
4709          * given the number of fragments by which the csum block can be grown
4710          * compute by how many new fragments the FS can be increased.
4711          * It is the number of csum instances per fragment multiplied by
4712          * `growth_csum_frags' and the number of fragments per cylinder group.
4713          */
4714         growth_fs_frags = howmany(sblock.fs_fsize, sizeof (struct csum)) *
4715             growth_csum_frags * sblock.fs_fpg;
4716 
4717         /*
4718          * compute free fragments in the last cylinder group
4719          */
4720         rdcg(sblock.fs_ncg - 1);
4721         growth_fs_frags += sblock.fs_fpg - acg.cg_ndblk;
4722 
4723         /*
4724          * compute how many csum instances are unused in the old csum block.
4725          * For each unused csum instance the FS can be grown by one cylinder
4726          * group without extending the csum block.
4727          */
4728         spare_csum = howmany(sblock.fs_cssize, sizeof (struct csum)) -
4729             sblock.fs_ncg;
4730         if (spare_csum > 0)
4731                 growth_fs_frags += spare_csum * sblock.fs_fpg;
4732 
4733         /*
4734          * recalculate the new filesystem size in sectors, shorten it by
4735          * the requested size `fssize_db' if necessary.
4736          */
4737         if (growth_fs_frags > 0) {
4738                 diskaddr_t sect;
4739                 sect = (sblock.fs_size + growth_fs_frags) * sblock.fs_nspf;
4740                 return ((sect > fssize_db) ? fssize_db : sect);
4741         }
4742 
4743         return (0);
4744 }
4745 
4746 void
4747 extendsummaryinfo()
4748 {
4749         int64_t         i;
4750         int             localtest       = test;
4751         int64_t         frags;
4752         daddr32_t               oldfrag;
4753         daddr32_t               newfrag;
4754 
4755         /*
4756          * if no-write (-N), don't bother
4757          */
4758         if (Nflag)
4759                 return;
4760 
4761 again:
4762         flcg();
4763         /*
4764          * summary info did not change size -- do nothing unless in test mode
4765          */
4766         if (grow_fs_cssize == sblock.fs_cssize)
4767                 if (!localtest)
4768                         return;
4769 
4770         /*
4771          * build list of frags needed for additional summary information
4772          */
4773         oldfrag = howmany(grow_fs_cssize, sblock.fs_fsize) + grow_fs_csaddr;
4774         newfrag = howmany(sblock.fs_cssize, sblock.fs_fsize) + grow_fs_csaddr;
4775         /*
4776          * add all of the frags that are required to grow the cyl summary to the
4777          * csfrag list, which is the generic/unknown list, since at this point
4778          * we don't yet know the state of those frags.
4779          */
4780         for (i = oldfrag, frags = 0; i < newfrag; ++i, ++frags)
4781                 addcsfrag((ino_t)0, (diskaddr_t)i, &csfrag);
4782         /*
4783          * reduce the number of data blocks in the file system (fs_dsize) by
4784          * the number of frags that need to be added to the cyl summary
4785          */
4786         sblock.fs_dsize -= (newfrag - oldfrag);
4787 
4788         /*
4789          * In test mode, we move more data than necessary from
4790          * cylinder group 0.  The lookup/allocate/move code can be
4791          * better stressed without having to create HUGE file systems.
4792          */
4793         if (localtest)
4794                 for (i = newfrag; i < grow_sifrag; ++i) {
4795                         if (frags >= testfrags)
4796                                 break;
4797                         frags++;
4798                         addcsfrag((ino_t)0, (diskaddr_t)i, &csfrag);
4799                 }
4800 
4801         /*
4802          * move frags to free or inode lists, depending on owner
4803          */
4804         findcsfragfree();
4805         findcsfragino();
4806 
4807         /*
4808          * if not all frags can be located, file system must be inconsistent
4809          */
4810         if (csfrag) {
4811                 isbad = 1;      /* should already be set, but make sure */
4812                 lockexit(32);
4813         }
4814 
4815         /*
4816          * allocate the free frags. Note that the free frags must be allocated
4817          * first otherwise they could be grabbed by alloccsfragino() for data
4818          * frags.
4819          */
4820         alloccsfragfree();
4821         /*
4822          * allocate extra space for inode frags
4823          */
4824         alloccsfragino();
4825 
4826         /*
4827          * not enough space
4828          */
4829         if (notenoughspace()) {
4830                 unalloccsfragfree();
4831                 unalloccsfragino();
4832                 if (localtest && !testforce) {
4833                         localtest = 0;
4834                         goto again;
4835                 }
4836                 (void) fprintf(stderr, gettext("Not enough free space\n"));
4837                 lockexit(NOTENOUGHSPACE);
4838         }
4839 
4840         /*
4841          * copy the data from old frags to new frags
4842          */
4843         copycsfragino();
4844 
4845         /*
4846          * fix the inodes to point to the new frags
4847          */
4848         fixcsfragino();
4849 
4850         /*
4851          * We may have moved more frags than we needed.  Free them.
4852          */
4853         rdcg((long)0);
4854         for (i = newfrag; i <= maxcsfrag; ++i)
4855                 setbit(cg_blksfree(&acg), i-cgbase(&sblock, 0));
4856         wtcg();
4857 
4858         flcg();
4859 }
4860 
4861 /*
4862  * Check if all fragments in the `csfragino' list were reallocated.
4863  */
4864 int
4865 notenoughspace()
4866 {
4867         struct csfrag   *cfp;
4868 
4869         /*
4870          * If any element in the csfragino array has a "new frag location"
4871          * of 0, the allocfrags() function was unsuccessful in allocating
4872          * space for moving the frag represented by this array element.
4873          */
4874         for (cfp = csfragino; cfp; cfp = cfp->next)
4875                 if (cfp->nfrag == 0)
4876                         return (1);
4877         return (0);
4878 }
4879 
4880 void
4881 unalloccsfragino()
4882 {
4883         struct csfrag   *cfp;
4884 
4885         while ((cfp = csfragino) != NULL) {
4886                 if (cfp->nfrag)
4887                         freefrags(cfp->nfrag, cfp->frags, cfp->cylno);
4888                 delcsfrag(cfp->ofrag, &csfragino);
4889         }
4890 }
4891 
4892 void
4893 unalloccsfragfree()
4894 {
4895         struct csfrag   *cfp;
4896 
4897         while ((cfp = csfragfree) != NULL) {
4898                 freefrags(cfp->ofrag, cfp->frags, cfp->cylno);
4899                 delcsfrag(cfp->ofrag, &csfragfree);
4900         }
4901 }
4902 
4903 /*
4904  * For each frag in the "as-yet-unclassified" list (csfrag), see if
4905  * it's free (i.e., its bit is set in the free frag bit map).  If so,
4906  * move it from the "as-yet-unclassified" list to the csfragfree list.
4907  */
4908 void
4909 findcsfragfree()
4910 {
4911         struct csfrag   *cfp;
4912         struct csfrag   *cfpnext;
4913 
4914         /*
4915          * move free frags onto the free-frag list
4916          */
4917         rdcg((long)0);
4918         for (cfp = csfrag; cfp; cfp = cfpnext) {
4919                 cfpnext = cfp->next;
4920                 if (isset(cg_blksfree(&acg), cfp->ofrag - cgbase(&sblock, 0))) {
4921                         addcsfrag(cfp->ino, cfp->ofrag, &csfragfree);
4922                         delcsfrag(cfp->ofrag, &csfrag);
4923                 }
4924         }
4925 }
4926 
4927 void
4928 copycsfragino()
4929 {
4930         struct csfrag   *cfp;
4931         char            buf[MAXBSIZE];
4932 
4933         /*
4934          * copy data from old frags to newly allocated frags
4935          */
4936         for (cfp = csfragino; cfp; cfp = cfp->next) {
4937                 rdfs(fsbtodb(&sblock, (uint64_t)cfp->ofrag), (int)cfp->size,
4938                     buf);
4939                 wtfs(fsbtodb(&sblock, (uint64_t)cfp->nfrag), (int)cfp->size,
4940                     buf);
4941         }
4942 }
4943 
4944 long    curcylno        = -1;
4945 int     cylnodirty      = 0;
4946 
4947 void
4948 rdcg(long cylno)
4949 {
4950         if (cylno != curcylno) {
4951                 flcg();
4952                 curcylno = cylno;
4953                 rdfs(fsbtodb(&sblock, (uint64_t)cgtod(&sblock, curcylno)),
4954                     (int)sblock.fs_cgsize, (char *)&acg);
4955         }
4956 }
4957 
4958 void
4959 flcg()
4960 {
4961         if (cylnodirty) {
4962                 if (debug && Pflag) {
4963                         (void) fprintf(stderr,
4964                             "Assert: cylnodirty set in probe mode\n");
4965                         return;
4966                 }
4967                 resetallocinfo();
4968                 wtfs(fsbtodb(&sblock, (uint64_t)cgtod(&sblock, curcylno)),
4969                     (int)sblock.fs_cgsize, (char *)&acg);
4970                 cylnodirty = 0;
4971         }
4972         curcylno = -1;
4973 }
4974 
4975 void
4976 wtcg()
4977 {
4978         if (!Pflag) {
4979                 /* probe mode should never write to disk */
4980                 cylnodirty = 1;
4981         }
4982 }
4983 
4984 void
4985 allocfrags(long frags, daddr32_t *fragp, long *cylnop)
4986 {
4987         int      i;
4988         int      j;
4989         long     bits;
4990         long     bit;
4991 
4992         /*
4993          * Allocate a free-frag range in an old cylinder group
4994          */
4995         for (i = 0, *fragp = 0; i < grow_fs_ncg; ++i) {
4996                 if (((fscs+i)->cs_nffree < frags) && ((fscs+i)->cs_nbfree == 0))
4997                         continue;
4998                 rdcg((long)i);
4999                 bit = bits = 0;
5000                 while (findfreerange(&bit, &bits)) {
5001                         if (frags <= bits)  {
5002                                 for (j = 0; j < frags; ++j)
5003                                         clrbit(cg_blksfree(&acg), bit+j);
5004                                 wtcg();
5005                                 *cylnop = i;
5006                                 *fragp  = bit + cgbase(&sblock, i);
5007                                 return;
5008                         }
5009                         bit += bits;
5010                 }
5011         }
5012 }
5013 
5014 /*
5015  * Allocate space for frags that need to be moved in order to free up space for
5016  * expanding the cylinder summary info.
5017  * For each frag that needs to be moved (each frag or range of frags in
5018  * the csfragino list), allocate a new location and store the frag number
5019  * of that new location in the nfrag field of the csfrag struct.
5020  * If a new frag can't be allocated for any element in the csfragino list,
5021  * set the new frag number for that element to 0 and return immediately.
5022  * The notenoughspace() function will detect this condition.
5023  */
5024 void
5025 alloccsfragino()
5026 {
5027         struct csfrag   *cfp;
5028 
5029         /*
5030          * allocate space for inode frag ranges
5031          */
5032         for (cfp = csfragino; cfp; cfp = cfp->next) {
5033                 allocfrags(cfp->frags, &cfp->nfrag, &cfp->cylno);
5034                 if (cfp->nfrag == 0)
5035                         break;
5036         }
5037 }
5038 
5039 void
5040 alloccsfragfree()
5041 {
5042         struct csfrag   *cfp;
5043 
5044         /*
5045          * allocate the free frags needed for extended summary info
5046          */
5047         rdcg((long)0);
5048 
5049         for (cfp = csfragfree; cfp; cfp = cfp->next)
5050                 clrbit(cg_blksfree(&acg), cfp->ofrag - cgbase(&sblock, 0));
5051 
5052         wtcg();
5053 }
5054 
5055 void
5056 freefrags(daddr32_t frag, long frags, long cylno)
5057 {
5058         int     i;
5059 
5060         /*
5061          * free frags
5062          */
5063         rdcg(cylno);
5064         for (i = 0; i < frags; ++i) {
5065                 setbit(cg_blksfree(&acg), (frag+i) - cgbase(&sblock, cylno));
5066         }
5067         wtcg();
5068 }
5069 
5070 int
5071 findfreerange(long *bitp, long *bitsp)
5072 {
5073         long     bit;
5074 
5075         /*
5076          * find a range of free bits in a cylinder group bit map
5077          */
5078         for (bit = *bitp, *bitsp = 0; bit < acg.cg_ndblk; ++bit)
5079                 if (isset(cg_blksfree(&acg), bit))
5080                         break;
5081 
5082         if (bit >= acg.cg_ndblk)
5083                 return (0);
5084 
5085         *bitp  = bit;
5086         *bitsp = 1;
5087         for (++bit; bit < acg.cg_ndblk; ++bit, ++(*bitsp)) {
5088                 if ((bit % sblock.fs_frag) == 0)
5089                         break;
5090                 if (isclr(cg_blksfree(&acg), bit))
5091                         break;
5092         }
5093         return (1);
5094 }
5095 
5096 void
5097 resetallocinfo()
5098 {
5099         long    cno;
5100         long    bit;
5101         long    bits;
5102 
5103         /*
5104          * Compute the free blocks/frags info and update the appropriate
5105          * inmemory superblock, summary info, and cylinder group fields
5106          */
5107         sblock.fs_cstotal.cs_nffree -= acg.cg_cs.cs_nffree;
5108         sblock.fs_cstotal.cs_nbfree -= acg.cg_cs.cs_nbfree;
5109 
5110         acg.cg_cs.cs_nffree = 0;
5111         acg.cg_cs.cs_nbfree = 0;
5112 
5113         bzero((caddr_t)acg.cg_frsum, sizeof (acg.cg_frsum));
5114         bzero((caddr_t)cg_blktot(&acg), (int)(acg.cg_iusedoff-acg.cg_btotoff));
5115 
5116         bit = bits = 0;
5117         while (findfreerange(&bit, &bits)) {
5118                 if (bits == sblock.fs_frag) {
5119                         acg.cg_cs.cs_nbfree++;
5120                         cno = cbtocylno(&sblock, bit);
5121                         cg_blktot(&acg)[cno]++;
5122                         cg_blks(&sblock, &acg, cno)[cbtorpos(&sblock, bit)]++;
5123                 } else {
5124                         acg.cg_cs.cs_nffree += bits;
5125                         acg.cg_frsum[bits]++;
5126                 }
5127                 bit += bits;
5128         }
5129 
5130         *(fscs + acg.cg_cgx) = acg.cg_cs;
5131 
5132         sblock.fs_cstotal.cs_nffree += acg.cg_cs.cs_nffree;
5133         sblock.fs_cstotal.cs_nbfree += acg.cg_cs.cs_nbfree;
5134 }
5135 
5136 void
5137 extendcg(long cylno)
5138 {
5139         int     i;
5140         diskaddr_t      dupper;
5141         diskaddr_t      cbase;
5142         diskaddr_t      dmax;
5143 
5144         /*
5145          * extend the cylinder group at the end of the old file system
5146          * if it was partially allocated becase of lack of space
5147          */
5148         flcg();
5149         rdcg(cylno);
5150 
5151         dupper = acg.cg_ndblk;
5152         if (cylno == sblock.fs_ncg - 1)
5153                 acg.cg_ncyl = sblock.fs_ncyl - (sblock.fs_cpg * cylno);
5154         else
5155                 acg.cg_ncyl = sblock.fs_cpg;
5156         cbase = cgbase(&sblock, cylno);
5157         dmax = cbase + sblock.fs_fpg;
5158         if (dmax > sblock.fs_size)
5159                 dmax = sblock.fs_size;
5160         acg.cg_ndblk = dmax - cbase;
5161 
5162         for (i = dupper; i < acg.cg_ndblk; ++i)
5163                 setbit(cg_blksfree(&acg), i);
5164 
5165         sblock.fs_dsize += (acg.cg_ndblk - dupper);
5166 
5167         wtcg();
5168         flcg();
5169 }
5170 
5171 struct lockfs   lockfs;
5172 int             lockfd;
5173 int             islocked;
5174 int             lockfskey;
5175 char            lockfscomment[128];
5176 
5177 void
5178 ulockfs()
5179 {
5180         /*
5181          * if the file system was locked, unlock it before exiting
5182          */
5183         if (islocked == 0)
5184                 return;
5185 
5186         /*
5187          * first, check if the lock held
5188          */
5189         lockfs.lf_flags = LOCKFS_MOD;
5190         if (ioctl(lockfd, _FIOLFSS, &lockfs) == -1) {
5191                 perror(directory);
5192                 lockexit(32);
5193         }
5194 
5195         if (LOCKFS_IS_MOD(&lockfs)) {
5196                 (void) fprintf(stderr,
5197                     gettext("FILE SYSTEM CHANGED DURING GROWFS!\n"));
5198                 (void) fprintf(stderr,
5199                     gettext("   See lockfs(1), umount(1), and fsck(1)\n"));
5200                 lockexit(32);
5201         }
5202         /*
5203          * unlock the file system
5204          */
5205         lockfs.lf_lock  = LOCKFS_ULOCK;
5206         lockfs.lf_flags = 0;
5207         lockfs.lf_key   = lockfskey;
5208         clockfs();
5209         if (ioctl(lockfd, _FIOLFS, &lockfs) == -1) {
5210                 perror(directory);
5211                 lockexit(32);
5212         }
5213 }
5214 
5215 void
5216 wlockfs()
5217 {
5218 
5219         /*
5220          * if no-write (-N), don't bother
5221          */
5222         if (Nflag)
5223                 return;
5224         /*
5225          * open the mountpoint, and write lock the file system
5226          */
5227         if ((lockfd = open64(directory, O_RDONLY)) == -1) {
5228                 perror(directory);
5229                 lockexit(32);
5230         }
5231 
5232         /*
5233          * check if it is already locked
5234          */
5235         if (ioctl(lockfd, _FIOLFSS, &lockfs) == -1) {
5236                 perror(directory);
5237                 lockexit(32);
5238         }
5239 
5240         if (lockfs.lf_lock != LOCKFS_WLOCK) {
5241                 lockfs.lf_lock  = LOCKFS_WLOCK;
5242                 lockfs.lf_flags = 0;
5243                 lockfs.lf_key   = 0;
5244                 clockfs();
5245                 if (ioctl(lockfd, _FIOLFS, &lockfs) == -1) {
5246                         perror(directory);
5247                         lockexit(32);
5248                 }
5249         }
5250         islocked = 1;
5251         lockfskey = lockfs.lf_key;
5252 }
5253 
5254 void
5255 clockfs()
5256 {
5257         time_t  t;
5258         char    *ct;
5259 
5260         (void) time(&t);
5261         ct = ctime(&t);
5262         ct[strlen(ct)-1] = '\0';
5263 
5264         (void) sprintf(lockfscomment, "%s -- mkfs pid %d", ct, getpid());
5265         lockfs.lf_comlen  = strlen(lockfscomment)+1;
5266         lockfs.lf_comment = lockfscomment;
5267 }
5268 
5269 /*
5270  * Write the csum records and the superblock
5271  */
5272 void
5273 wtsb()
5274 {
5275         long    i;
5276 
5277         /*
5278          * write summary information
5279          */
5280         for (i = 0; i < sblock.fs_cssize; i += sblock.fs_bsize)
5281                 wtfs(fsbtodb(&sblock, (uint64_t)(sblock.fs_csaddr +
5282                     numfrags(&sblock, i))),
5283                     (int)(sblock.fs_cssize - i < sblock.fs_bsize ?
5284                     sblock.fs_cssize - i : sblock.fs_bsize),
5285                     ((char *)fscs) + i);
5286 
5287         /*
5288          * write superblock
5289          */
5290         sblock.fs_time = mkfstime;
5291         wtfs((diskaddr_t)(SBOFF / sectorsize), sbsize, (char *)&sblock);
5292 }
5293 
5294 /*
5295  * Verify that the optimization selection is reasonable, and advance
5296  * the global "string" appropriately.
5297  */
5298 static char
5299 checkopt(char *optim)
5300 {
5301         char    opt;
5302         int     limit = strcspn(optim, ",");
5303 
5304         switch (limit) {
5305         case 0: /* missing indicator (have comma or nul) */
5306                 (void) fprintf(stderr, gettext(
5307                     "mkfs: missing optimization flag reset to `t' (time)\n"));
5308                 opt = 't';
5309                 break;
5310 
5311         case 1: /* single-character indicator */
5312                 opt = *optim;
5313                 if ((opt != 's') && (opt != 't')) {
5314                         (void) fprintf(stderr, gettext(
5315                     "mkfs: bad optimization value `%c' reset to `t' (time)\n"),
5316                             opt);
5317                         opt = 't';
5318                 }
5319                 break;
5320 
5321         default: /* multi-character indicator */
5322                 (void) fprintf(stderr, gettext(
5323             "mkfs: bad optimization value `%*.*s' reset to `t' (time)\n"),
5324                     limit, limit, optim);
5325                 opt = 't';
5326                 break;
5327         }
5328 
5329         string += limit;
5330 
5331         return (opt);
5332 }
5333 
5334 /*
5335  * Verify that the mtb selection is reasonable, and advance
5336  * the global "string" appropriately.
5337  */
5338 static char
5339 checkmtb(char *mtbarg)
5340 {
5341         char    mtbc;
5342         int     limit = strcspn(mtbarg, ",");
5343 
5344         switch (limit) {
5345         case 0: /* missing indicator (have comma or nul) */
5346                 (void) fprintf(stderr, gettext(
5347                     "mkfs: missing mtb flag reset to `n' (no mtb support)\n"));
5348                 mtbc = 'n';
5349                 break;
5350 
5351         case 1: /* single-character indicator */
5352                 mtbc = tolower(*mtbarg);
5353                 if ((mtbc != 'y') && (mtbc != 'n')) {
5354                         (void) fprintf(stderr, gettext(
5355                     "mkfs: bad mtb value `%c' reset to `n' (no mtb support)\n"),
5356                             mtbc);
5357                         mtbc = 'n';
5358                 }
5359                 break;
5360 
5361         default: /* multi-character indicator */
5362                 (void) fprintf(stderr, gettext(
5363             "mkfs: bad mtb value `%*.*s' reset to `n' (no mtb support)\n"),
5364                     limit, limit, mtbarg);
5365                 opt = 'n';
5366                 break;
5367         }
5368 
5369         string += limit;
5370 
5371         return (mtbc);
5372 }
5373 
5374 /*
5375  * Verify that a value is in a range.  If it is not, resets it to
5376  * its default value if one is supplied, exits otherwise.
5377  *
5378  * When testing, can compare user_supplied to RC_KEYWORD or RC_POSITIONAL.
5379  */
5380 static void
5381 range_check(long *varp, char *name, long minimum, long maximum,
5382     long def_val, int user_supplied)
5383 {
5384         dprintf(("DeBuG %s : %ld (%ld %ld %ld)\n",
5385             name, *varp, minimum, maximum, def_val));
5386 
5387         if ((*varp < minimum) || (*varp > maximum)) {
5388                 if (user_supplied != RC_DEFAULT) {
5389                         (void) fprintf(stderr, gettext(
5390             "mkfs: bad value for %s: %ld must be between %ld and %ld\n"),
5391                             name, *varp, minimum, maximum);
5392                 }
5393                 if (def_val != NO_DEFAULT) {
5394                         if (user_supplied) {
5395                                 (void) fprintf(stderr,
5396                                     gettext("mkfs: %s reset to default %ld\n"),
5397                                     name, def_val);
5398                         }
5399                         *varp = def_val;
5400                         dprintf(("DeBuG %s : %ld\n", name, *varp));
5401                         return;
5402                 }
5403                 lockexit(2);
5404                 /*NOTREACHED*/
5405         }
5406 }
5407 
5408 /*
5409  * Verify that a value is in a range.  If it is not, resets it to
5410  * its default value if one is supplied, exits otherwise.
5411  *
5412  * When testing, can compare user_supplied to RC_KEYWORD or RC_POSITIONAL.
5413  */
5414 static void
5415 range_check_64(uint64_t *varp, char *name, uint64_t minimum, uint64_t maximum,
5416     uint64_t def_val, int user_supplied)
5417 {
5418         if ((*varp < minimum) || (*varp > maximum)) {
5419                 if (user_supplied != RC_DEFAULT) {
5420                         (void) fprintf(stderr, gettext(
5421             "mkfs: bad value for %s: %lld must be between %lld and %lld\n"),
5422                             name, *varp, minimum, maximum);
5423                 }
5424                 if (def_val != NO_DEFAULT) {
5425                         if (user_supplied) {
5426                                 (void) fprintf(stderr,
5427                                     gettext("mkfs: %s reset to default %lld\n"),
5428                                     name, def_val);
5429                         }
5430                         *varp = def_val;
5431                         return;
5432                 }
5433                 lockexit(2);
5434                 /*NOTREACHED*/
5435         }
5436 }
5437 
5438 /*
5439  * Blocks SIGINT from delivery.  Returns the previous mask in the
5440  * buffer provided, so that mask may be later restored.
5441  */
5442 static void
5443 block_sigint(sigset_t *old_mask)
5444 {
5445         sigset_t block_mask;
5446 
5447         if (sigemptyset(&block_mask) < 0) {
5448                 fprintf(stderr, gettext("Could not clear signal mask\n"));
5449                 lockexit(3);
5450         }
5451         if (sigaddset(&block_mask, SIGINT) < 0) {
5452                 fprintf(stderr, gettext("Could not set signal mask\n"));
5453                 lockexit(3);
5454         }
5455         if (sigprocmask(SIG_BLOCK, &block_mask, old_mask) < 0) {
5456                 fprintf(stderr, gettext("Could not block SIGINT\n"));
5457                 lockexit(3);
5458         }
5459 }
5460 
5461 /*
5462  * Restores the signal mask that was in force before a call
5463  * to block_sigint().  This may actually still have SIGINT blocked,
5464  * if we've been recursively invoked.
5465  */
5466 static void
5467 unblock_sigint(sigset_t *old_mask)
5468 {
5469         if (sigprocmask(SIG_UNBLOCK, old_mask, (sigset_t *)NULL) < 0) {
5470                 fprintf(stderr, gettext("Could not restore signal mask\n"));
5471                 lockexit(3);
5472         }
5473 }
5474 
5475 /*
5476  * Attempt to be somewhat graceful about being interrupted, rather than
5477  * just silently leaving the filesystem in an unusable state.
5478  *
5479  * The kernel has blocked SIGINT upon entry, so we don't have to worry
5480  * about recursion if the user starts pounding on the keyboard.
5481  */
5482 static void
5483 recover_from_sigint(int signum)
5484 {
5485         if (fso > -1) {
5486                 if ((Nflag != 0) || confirm_abort()) {
5487                         lockexit(4);
5488                 }
5489         }
5490 }
5491 
5492 static int
5493 confirm_abort(void)
5494 {
5495         char line[80];
5496 
5497         printf(gettext("\n\nAborting at this point will leave the filesystem "
5498             "in an inconsistent\nstate.  If you do choose to stop, "
5499             "you will be given instructions on how to\nrecover "
5500             "the filesystem.  Do you wish to cancel the filesystem "
5501             "grow\noperation (y/n)?"));
5502         if (getaline(stdin, line, sizeof (line)) == EOF)
5503                 line[0] = 'y';
5504 
5505         printf("\n");
5506         if (line[0] == 'y' || line[0] == 'Y')
5507                 return (1);
5508         else {
5509                 return (0);
5510         }
5511 }
5512 
5513 static int
5514 getaline(FILE *fp, char *loc, int maxlen)
5515 {
5516         int n;
5517         char *p, *lastloc;
5518 
5519         p = loc;
5520         lastloc = &p[maxlen-1];
5521         while ((n = getc(fp)) != '\n') {
5522                 if (n == EOF)
5523                         return (EOF);
5524                 if (!isspace(n) && p < lastloc)
5525                         *p++ = n;
5526         }
5527         *p = 0;
5528         return (p - loc);
5529 }
5530 
5531 /*
5532  * Calculate the maximum value of cylinders-per-group for a file
5533  * system with the characteristics:
5534  *
5535  *      bsize - file system block size
5536  *      fragsize - frag size
5537  *      nbpi - number of bytes of disk space per inode
5538  *      nrpos - number of rotational positions
5539  *      spc - sectors per cylinder
5540  *
5541  * These five characteristic are not adjustable (by this function).
5542  * The only attribute of the file system which IS adjusted by this
5543  * function in order to maximize cylinders-per-group is the proportion
5544  * of the cylinder group overhead block used for the inode map.  The
5545  * inode map cannot occupy more than one-third of the cylinder group
5546  * overhead block, but it's OK for it to occupy less than one-third
5547  * of the overhead block.
5548  *
5549  * The setting of nbpi determines one possible value for the maximum
5550  * size of a cylinder group.  It does so because it determines the total
5551  * number of inodes in the file system (file system size is fixed, and
5552  * nbpi is fixed, so the total number of inodes is fixed too).  The
5553  * cylinder group has to be small enough so that the number of inodes
5554  * in the cylinder group is less than or equal to the number of bits
5555  * in one-third (or whatever proportion is assumed) of a file system
5556  * block.  The details of the calculation are:
5557  *
5558  *     The macro MAXIpG_B(bsize, inode_divisor) determines the maximum
5559  *     number of inodes that can be in a cylinder group, given the
5560  *     proportion of the cylinder group overhead block used for the
5561  *     inode bitmaps (an inode_divisor of 3 means that 1/3 of the
5562  *     block is used for inode bitmaps; an inode_divisor of 12 means
5563  *     that 1/12 of the block is used for inode bitmaps.)
5564  *
5565  *     Once the number of inodes per cylinder group is known, the
5566  *     maximum value of cylinders-per-group (determined by nbpi)
5567  *     is calculated by the formula
5568  *
5569  *     maxcpg_given_nbpi = (size of a cylinder group)/(size of a cylinder)
5570  *
5571  *                       = (inodes-per-cg * nbpi)/(spc * DEV_BSIZE)
5572  *
5573  *     (Interestingly, the size of the file system never enters
5574  *     into this calculation.)
5575  *
5576  * Another possible value for the maximum cylinder group size is determined
5577  * by frag_size and nrpos.  The frags in the cylinder group must be
5578  * representable in the frag bitmaps in the cylinder overhead block and the
5579  * rotational positions for each cylinder must be represented in the
5580  * rotational position tables.  The calculation of the maximum cpg
5581  * value, given the frag and nrpos vales, is:
5582  *
5583  *     maxcpg_given_fragsize =
5584  *        (available space in the overhead block) / (size of per-cylinder data)
5585  *
5586  *     The available space in the overhead block =
5587  *        bsize - sizeof (struct cg) - space_used_for_inode_bitmaps
5588  *
5589  *     The size of the per-cylinder data is:
5590  *          sizeof(long)            # for the "blocks avail per cylinder" field
5591  *          + nrpos * sizeof(short)   # for the rotational position table entry
5592  *          + frags-per-cylinder/NBBY # number of bytes to represent this
5593  *                                    # cylinder in the frag bitmap
5594  *
5595  * The two calculated maximum values of cylinder-per-group will typically
5596  * turn out to be different, since they are derived from two different
5597  * constraints.  Usually, maxcpg_given_nbpi is much bigger than
5598  * maxcpg_given_fragsize.  But they can be brought together by
5599  * adjusting the proportion of the overhead block dedicated to
5600  * the inode bitmaps.  Decreasing the proportion of the cylinder
5601  * group overhead block used for inode maps will decrease
5602  * maxcpg_given_nbpi and increase maxcpg_given_fragsize.
5603  *
5604  * This function calculates the initial values of maxcpg_given_nbpi
5605  * and maxcpg_given_fragsize assuming that 1/3 of the cg overhead
5606  * block is used for inode bitmaps.  Then it decreases the proportion
5607  * of the cg overhead block used for inode bitmaps (by increasing
5608  * the value of inode_divisor) until maxcpg_given_nbpi and
5609  * maxcpg_given_fragsize are the same, or stop changing, or
5610  * maxcpg_given_nbpi is less than maxcpg_given_fragsize.
5611  *
5612  * The loop terminates when any of the following occur:
5613  *      * maxcpg_given_fragsize is greater than or equal to
5614  *        maxcpg_given_nbpi
5615  *      * neither maxcpg_given_fragsize nor maxcpg_given_nbpi
5616  *        change in the expected direction
5617  *
5618  * The loop is guaranteed to terminate because it only continues
5619  * while maxcpg_given_fragsize and maxcpg_given_nbpi are approaching
5620  * each other.  As soon they cross each other, or neither one changes
5621  * in the direction of the other, or one of them moves in the wrong
5622  * direction, the loop completes.
5623  */
5624 
5625 static long
5626 compute_maxcpg(long bsize, long fragsize, long nbpi, long nrpos, long spc)
5627 {
5628         int     maxcpg_given_nbpi;      /* in cylinders */
5629         int     maxcpg_given_fragsize;  /* in cylinders */
5630         int     spf;                    /* sectors per frag */
5631         int     inode_divisor;
5632         int     old_max_given_frag = 0;
5633         int     old_max_given_nbpi = INT_MAX;
5634 
5635         spf = fragsize / DEV_BSIZE;
5636         inode_divisor = 3;
5637 
5638         while (1) {
5639                 maxcpg_given_nbpi =
5640                     (((int64_t)(MAXIpG_B(bsize, inode_divisor))) * nbpi) /
5641                     (DEV_BSIZE * ((int64_t)spc));
5642                 maxcpg_given_fragsize =
5643                     (bsize - (sizeof (struct cg)) - (bsize / inode_divisor)) /
5644                     (sizeof (long) + nrpos * sizeof (short) +
5645                     (spc / spf) / NBBY);
5646 
5647                 if (maxcpg_given_fragsize >= maxcpg_given_nbpi)
5648                         return (maxcpg_given_nbpi);
5649 
5650                 /*
5651                  * If neither value moves toward the other, return the
5652                  * least of the old values (we use the old instead of the
5653                  * new because: if the old is the same as the new, it
5654                  * doesn't matter which ones we use.  If one of the
5655                  * values changed, but in the wrong direction, the
5656                  * new values are suspect.  Better use the old.  This
5657                  * shouldn't happen, but it's best to check.
5658                  */
5659 
5660                 if (!(maxcpg_given_nbpi < old_max_given_nbpi) &&
5661                     !(maxcpg_given_fragsize > old_max_given_frag))
5662                         return (MIN(old_max_given_nbpi, old_max_given_frag));
5663 
5664                 /*
5665                  * This is probably impossible, but if one of the maxcpg
5666                  * values moved in the "right" direction and one moved
5667                  * in the "wrong" direction (that is, the two values moved
5668                  * in the same direction), the previous conditional won't
5669                  * recognize that the values aren't converging (since at
5670                  * least one value moved in the "right" direction, the
5671                  * last conditional says "keep going").
5672                  *
5673                  * Just to make absolutely certain that the loop terminates,
5674                  * check for one of the values moving in the "wrong" direction
5675                  * and terminate the loop if it happens.
5676                  */
5677 
5678                 if (maxcpg_given_nbpi > old_max_given_nbpi ||
5679                     maxcpg_given_fragsize < old_max_given_frag)
5680                         return (MIN(old_max_given_nbpi, old_max_given_frag));
5681 
5682                 old_max_given_nbpi = maxcpg_given_nbpi;
5683                 old_max_given_frag = maxcpg_given_fragsize;
5684 
5685                 inode_divisor++;
5686         }
5687 }
5688 
5689 static int
5690 in_64bit_mode(void)
5691 {
5692         /*  cmd must be an absolute path, for security */
5693         char *cmd = "/usr/bin/isainfo -b";
5694         char buf[BUFSIZ];
5695         FILE *ptr;
5696         int retval = 0;
5697 
5698         putenv("IFS= \t");
5699         if ((ptr = popen(cmd, "r")) != NULL) {
5700                 if (fgets(buf, BUFSIZ, ptr) != NULL &&
5701                     strncmp(buf, "64", 2) == 0)
5702                         retval = 1;
5703                 (void) pclose(ptr);
5704         }
5705         return (retval);
5706 }
5707 
5708 /*
5709  * validate_size
5710  *
5711  * Return 1 if the device appears to be at least "size" sectors long.
5712  * Return 0 if it's shorter or we can't read it.
5713  */
5714 
5715 static int
5716 validate_size(int fd, diskaddr_t size)
5717 {
5718         char    buf[DEV_BSIZE];
5719         int rc;
5720 
5721         if ((llseek(fd, (offset_t)((size - 1) * DEV_BSIZE), SEEK_SET) == -1) ||
5722             (read(fd, buf, DEV_BSIZE)) != DEV_BSIZE)
5723                 rc = 0;
5724         else
5725                 rc = 1;
5726         return (rc);
5727 }
5728 
5729 /*
5730  * Print every field of the calculated superblock, along with
5731  * its value.  To make parsing easier on the caller, the value
5732  * is printed first, then the name.  Additionally, there's only
5733  * one name/value pair per line.  All values are reported in
5734  * hexadecimal (with the traditional 0x prefix), as that's slightly
5735  * easier for humans to read.  Not that they're expected to, but
5736  * debugging happens.
5737  */
5738 static void
5739 dump_sblock(void)
5740 {
5741         int row, column, pending, written;
5742         caddr_t source;
5743 
5744         if (Rflag) {
5745                 pending = sizeof (sblock);
5746                 source = (caddr_t)&sblock;
5747                 do {
5748                         written = write(fileno(stdout), source, pending);
5749                         pending -= written;
5750                         source += written;
5751                 } while ((pending > 0) && (written > 0));
5752 
5753                 if (written < 0) {
5754                         perror(gettext("Binary dump of superblock failed"));
5755                         lockexit(1);
5756                 }
5757                 return;
5758         } else {
5759                 printf("0x%x sblock.fs_link\n", sblock.fs_link);
5760                 printf("0x%x sblock.fs_rolled\n", sblock.fs_rolled);
5761                 printf("0x%x sblock.fs_sblkno\n", sblock.fs_sblkno);
5762                 printf("0x%x sblock.fs_cblkno\n", sblock.fs_cblkno);
5763                 printf("0x%x sblock.fs_iblkno\n", sblock.fs_iblkno);
5764                 printf("0x%x sblock.fs_dblkno\n", sblock.fs_dblkno);
5765                 printf("0x%x sblock.fs_cgoffset\n", sblock.fs_cgoffset);
5766                 printf("0x%x sblock.fs_cgmask\n", sblock.fs_cgmask);
5767                 printf("0x%x sblock.fs_time\n", sblock.fs_time);
5768                 printf("0x%x sblock.fs_size\n", sblock.fs_size);
5769                 printf("0x%x sblock.fs_dsize\n", sblock.fs_dsize);
5770                 printf("0x%x sblock.fs_ncg\n", sblock.fs_ncg);
5771                 printf("0x%x sblock.fs_bsize\n", sblock.fs_bsize);
5772                 printf("0x%x sblock.fs_fsize\n", sblock.fs_fsize);
5773                 printf("0x%x sblock.fs_frag\n", sblock.fs_frag);
5774                 printf("0x%x sblock.fs_minfree\n", sblock.fs_minfree);
5775                 printf("0x%x sblock.fs_rotdelay\n", sblock.fs_rotdelay);
5776                 printf("0x%x sblock.fs_rps\n", sblock.fs_rps);
5777                 printf("0x%x sblock.fs_bmask\n", sblock.fs_bmask);
5778                 printf("0x%x sblock.fs_fmask\n", sblock.fs_fmask);
5779                 printf("0x%x sblock.fs_bshift\n", sblock.fs_bshift);
5780                 printf("0x%x sblock.fs_fshift\n", sblock.fs_fshift);
5781                 printf("0x%x sblock.fs_maxcontig\n", sblock.fs_maxcontig);
5782                 printf("0x%x sblock.fs_maxbpg\n", sblock.fs_maxbpg);
5783                 printf("0x%x sblock.fs_fragshift\n", sblock.fs_fragshift);
5784                 printf("0x%x sblock.fs_fsbtodb\n", sblock.fs_fsbtodb);
5785                 printf("0x%x sblock.fs_sbsize\n", sblock.fs_sbsize);
5786                 printf("0x%x sblock.fs_csmask\n", sblock.fs_csmask);
5787                 printf("0x%x sblock.fs_csshift\n", sblock.fs_csshift);
5788                 printf("0x%x sblock.fs_nindir\n", sblock.fs_nindir);
5789                 printf("0x%x sblock.fs_inopb\n", sblock.fs_inopb);
5790                 printf("0x%x sblock.fs_nspf\n", sblock.fs_nspf);
5791                 printf("0x%x sblock.fs_optim\n", sblock.fs_optim);
5792 #ifdef _LITTLE_ENDIAN
5793                 printf("0x%x sblock.fs_state\n", sblock.fs_state);
5794 #else
5795                 printf("0x%x sblock.fs_npsect\n", sblock.fs_npsect);
5796 #endif
5797                 printf("0x%x sblock.fs_si\n", sblock.fs_si);
5798                 printf("0x%x sblock.fs_trackskew\n", sblock.fs_trackskew);
5799                 printf("0x%x sblock.fs_id[0]\n", sblock.fs_id[0]);
5800                 printf("0x%x sblock.fs_id[1]\n", sblock.fs_id[1]);
5801                 printf("0x%x sblock.fs_csaddr\n", sblock.fs_csaddr);
5802                 printf("0x%x sblock.fs_cssize\n", sblock.fs_cssize);
5803                 printf("0x%x sblock.fs_cgsize\n", sblock.fs_cgsize);
5804                 printf("0x%x sblock.fs_ntrak\n", sblock.fs_ntrak);
5805                 printf("0x%x sblock.fs_nsect\n", sblock.fs_nsect);
5806                 printf("0x%x sblock.fs_spc\n", sblock.fs_spc);
5807                 printf("0x%x sblock.fs_ncyl\n", sblock.fs_ncyl);
5808                 printf("0x%x sblock.fs_cpg\n", sblock.fs_cpg);
5809                 printf("0x%x sblock.fs_ipg\n", sblock.fs_ipg);
5810                 printf("0x%x sblock.fs_fpg\n", sblock.fs_fpg);
5811                 printf("0x%x sblock.fs_cstotal\n", sblock.fs_cstotal);
5812                 printf("0x%x sblock.fs_fmod\n", sblock.fs_fmod);
5813                 printf("0x%x sblock.fs_clean\n", sblock.fs_clean);
5814                 printf("0x%x sblock.fs_ronly\n", sblock.fs_ronly);
5815                 printf("0x%x sblock.fs_flags\n", sblock.fs_flags);
5816                 printf("0x%x sblock.fs_fsmnt\n", sblock.fs_fsmnt);
5817                 printf("0x%x sblock.fs_cgrotor\n", sblock.fs_cgrotor);
5818                 printf("0x%x sblock.fs_u.fs_csp\n", sblock.fs_u.fs_csp);
5819                 printf("0x%x sblock.fs_cpc\n", sblock.fs_cpc);
5820 
5821                 /*
5822                  * No macros are defined for the dimensions of the
5823                  * opostbl array.
5824                  */
5825                 for (row = 0; row < 16; row++) {
5826                         for (column = 0; column < 8; column++) {
5827                                 printf("0x%x sblock.fs_opostbl[%d][%d]\n",
5828                                     sblock.fs_opostbl[row][column],
5829                                     row, column);
5830                         }
5831                 }
5832 
5833                 /*
5834                  * Ditto the size of sparecon.
5835                  */
5836                 for (row = 0; row < 51; row++) {
5837                         printf("0x%x sblock.fs_sparecon[%d]\n",
5838                             sblock.fs_sparecon[row], row);
5839                 }
5840 
5841                 printf("0x%x sblock.fs_version\n", sblock.fs_version);
5842                 printf("0x%x sblock.fs_logbno\n", sblock.fs_logbno);
5843                 printf("0x%x sblock.fs_reclaim\n", sblock.fs_reclaim);
5844                 printf("0x%x sblock.fs_sparecon2\n", sblock.fs_sparecon2);
5845 #ifdef _LITTLE_ENDIAN
5846                 printf("0x%x sblock.fs_npsect\n", sblock.fs_npsect);
5847 #else
5848                 printf("0x%x sblock.fs_state\n", sblock.fs_state);
5849 #endif
5850                 printf("0x%llx sblock.fs_qbmask\n", sblock.fs_qbmask);
5851                 printf("0x%llx sblock.fs_qfmask\n", sblock.fs_qfmask);
5852                 printf("0x%x sblock.fs_postblformat\n", sblock.fs_postblformat);
5853                 printf("0x%x sblock.fs_nrpos\n", sblock.fs_nrpos);
5854                 printf("0x%x sblock.fs_postbloff\n", sblock.fs_postbloff);
5855                 printf("0x%x sblock.fs_rotbloff\n", sblock.fs_rotbloff);
5856                 printf("0x%x sblock.fs_magic\n", sblock.fs_magic);
5857 
5858                 /*
5859                  * fs_space isn't of much use in this context, so we'll
5860                  * just ignore it for now.
5861                  */
5862         }
5863 }