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