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