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