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