]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blobdiff - mkfs/xfs_mkfs.c
libxfs: fix libxfs_trans_alloc callsite problems
[thirdparty/xfsprogs-dev.git] / mkfs / xfs_mkfs.c
index dc1a6aacf587c7180f2110f5be174a67a39ddf2f..c6ef3a710fd04c097895b021eed00da73ff16ff0 100644 (file)
@@ -1,26 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (c) 2000-2005 Silicon Graphics, Inc.
  * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 #include "libfrog.h"
 #include "libxfs.h"
 #include <ctype.h>
 #include "xfs_multidisk.h"
 #include "libxcmd.h"
-
+#include "fsgeom.h"
 
 
 #define TERABYTES(count, blog) ((uint64_t)(count) << (40 - (blog)))
@@ -51,8 +39,7 @@ unsigned int          sectorsize;
  * maximum array size needed to hold them automatically.
  */
 enum {
-       B_LOG = 0,
-       B_SIZE,
+       B_SIZE = 0,
        B_MAX_OPTS,
 };
 
@@ -66,7 +53,6 @@ enum {
        D_AGSIZE,
        D_SU,
        D_SW,
-       D_SECTLOG,
        D_SECTSIZE,
        D_NOALIGN,
        D_RTINHERIT,
@@ -78,7 +64,6 @@ enum {
 
 enum {
        I_ALIGN = 0,
-       I_LOG,
        I_MAXPCT,
        I_PERBLOCK,
        I_SIZE,
@@ -96,7 +81,6 @@ enum {
        L_SUNIT,
        L_SU,
        L_DEV,
-       L_SECTLOG,
        L_SECTSIZE,
        L_FILE,
        L_NAME,
@@ -105,8 +89,7 @@ enum {
 };
 
 enum {
-       N_LOG = 0,
-       N_SIZE,
+       N_SIZE = 0,
        N_VERSION,
        N_FTYPE,
        N_MAX_OPTS,
@@ -123,9 +106,7 @@ enum {
 };
 
 enum {
-       S_LOG = 0,
-       S_SECTLOG,
-       S_SIZE,
+       S_SIZE = 0,
        S_SECTSIZE,
        S_MAX_OPTS,
 };
@@ -230,25 +211,23 @@ struct opt_params {
        }               subopt_params[MAX_SUBOPTS];
 };
 
+/*
+ * The two dimensional conflict array requires some initialisations to know
+ * about tables that haven't yet been defined. Work around this ordering
+ * issue with extern definitions here.
+ */
+extern struct opt_params sopts;
+
 struct opt_params bopts = {
        .name = 'b',
        .subopts = {
-               [B_LOG] = "log",
                [B_SIZE] = "size",
        },
        .subopt_params = {
-               { .index = B_LOG,
-                 .conflicts = { { &bopts, B_SIZE },
-                                { NULL, LAST_CONFLICT } },
-                 .minval = XFS_MIN_BLOCKSIZE_LOG,
-                 .maxval = XFS_MAX_BLOCKSIZE_LOG,
-                 .defaultval = SUBOPT_NEEDS_VAL,
-               },
                { .index = B_SIZE,
                  .convert = true,
                  .is_power_2 = true,
-                 .conflicts = { { &bopts, B_LOG },
-                                { NULL, LAST_CONFLICT } },
+                 .conflicts = { { NULL, LAST_CONFLICT } },
                  .minval = XFS_MIN_BLOCKSIZE,
                  .maxval = XFS_MAX_BLOCKSIZE,
                  .defaultval = SUBOPT_NEEDS_VAL,
@@ -268,7 +247,6 @@ struct opt_params dopts = {
                [D_AGSIZE] = "agsize",
                [D_SU] = "su",
                [D_SW] = "sw",
-               [D_SECTLOG] = "sectlog",
                [D_SECTSIZE] = "sectsize",
                [D_NOALIGN] = "noalign",
                [D_RTINHERIT] = "rtinherit",
@@ -346,15 +324,9 @@ struct opt_params dopts = {
                  .maxval = UINT_MAX,
                  .defaultval = SUBOPT_NEEDS_VAL,
                },
-               { .index = D_SECTLOG,
-                 .conflicts = { { &dopts, D_SECTSIZE },
-                                { NULL, LAST_CONFLICT } },
-                 .minval = XFS_MIN_SECTORSIZE_LOG,
-                 .maxval = XFS_MAX_SECTORSIZE_LOG,
-                 .defaultval = SUBOPT_NEEDS_VAL,
-               },
                { .index = D_SECTSIZE,
-                 .conflicts = { { &dopts, D_SECTLOG },
+                 .conflicts = { { &sopts, S_SIZE },
+                                { &sopts, S_SECTSIZE },
                                 { NULL, LAST_CONFLICT } },
                  .convert = true,
                  .is_power_2 = true,
@@ -404,7 +376,6 @@ struct opt_params iopts = {
        .name = 'i',
        .subopts = {
                [I_ALIGN] = "align",
-               [I_LOG] = "log",
                [I_MAXPCT] = "maxpct",
                [I_PERBLOCK] = "perblock",
                [I_SIZE] = "size",
@@ -419,14 +390,6 @@ struct opt_params iopts = {
                  .maxval = 1,
                  .defaultval = 1,
                },
-               { .index = I_LOG,
-                 .conflicts = { { &iopts, I_PERBLOCK },
-                                { &iopts, I_SIZE },
-                                { NULL, LAST_CONFLICT } },
-                 .minval = XFS_DINODE_MIN_LOG,
-                 .maxval = XFS_DINODE_MAX_LOG,
-                 .defaultval = SUBOPT_NEEDS_VAL,
-               },
                { .index = I_MAXPCT,
                  .conflicts = { { NULL, LAST_CONFLICT } },
                  .minval = 0,
@@ -434,8 +397,7 @@ struct opt_params iopts = {
                  .defaultval = SUBOPT_NEEDS_VAL,
                },
                { .index = I_PERBLOCK,
-                 .conflicts = { { &iopts, I_LOG },
-                                { &iopts, I_SIZE },
+                 .conflicts = { { &iopts, I_SIZE },
                                 { NULL, LAST_CONFLICT } },
                  .is_power_2 = true,
                  .minval = XFS_MIN_INODE_PERBLOCK,
@@ -444,7 +406,6 @@ struct opt_params iopts = {
                },
                { .index = I_SIZE,
                  .conflicts = { { &iopts, I_PERBLOCK },
-                                { &iopts, I_LOG },
                                 { NULL, LAST_CONFLICT } },
                  .is_power_2 = true,
                  .minval = XFS_DINODE_MIN_SIZE,
@@ -482,7 +443,6 @@ struct opt_params lopts = {
                [L_SUNIT] = "sunit",
                [L_SU] = "su",
                [L_DEV] = "logdev",
-               [L_SECTLOG] = "sectlog",
                [L_SECTSIZE] = "sectsize",
                [L_FILE] = "file",
                [L_NAME] = "name",
@@ -499,7 +459,6 @@ struct opt_params lopts = {
                { .index = L_INTERNAL,
                  .conflicts = { { &lopts, L_FILE },
                                 { &lopts, L_DEV },
-                                { &lopts, L_SECTLOG },
                                 { &lopts, L_SECTSIZE },
                                 { NULL, LAST_CONFLICT } },
                  .minval = 0,
@@ -536,21 +495,13 @@ struct opt_params lopts = {
                },
                { .index = L_DEV,
                  .conflicts = { { &lopts, L_AGNUM },
+                                { &lopts, L_NAME },
                                 { &lopts, L_INTERNAL },
                                 { NULL, LAST_CONFLICT } },
                  .defaultval = SUBOPT_NEEDS_VAL,
                },
-               { .index = L_SECTLOG,
-                 .conflicts = { { &lopts, L_SECTSIZE },
-                                { &lopts, L_INTERNAL },
-                                { NULL, LAST_CONFLICT } },
-                 .minval = XFS_MIN_SECTORSIZE_LOG,
-                 .maxval = XFS_MAX_SECTORSIZE_LOG,
-                 .defaultval = SUBOPT_NEEDS_VAL,
-               },
                { .index = L_SECTSIZE,
-                 .conflicts = { { &lopts, L_SECTLOG },
-                                { &lopts, L_INTERNAL },
+                 .conflicts = { { &lopts, L_INTERNAL },
                                 { NULL, LAST_CONFLICT } },
                  .convert = true,
                  .is_power_2 = true,
@@ -567,6 +518,7 @@ struct opt_params lopts = {
                },
                { .index = L_NAME,
                  .conflicts = { { &lopts, L_AGNUM },
+                                { &lopts, L_DEV },
                                 { &lopts, L_INTERNAL },
                                 { NULL, LAST_CONFLICT } },
                  .defaultval = SUBOPT_NEEDS_VAL,
@@ -583,22 +535,13 @@ struct opt_params lopts = {
 struct opt_params nopts = {
        .name = 'n',
        .subopts = {
-               [N_LOG] = "log",
                [N_SIZE] = "size",
                [N_VERSION] = "version",
                [N_FTYPE] = "ftype",
        },
        .subopt_params = {
-               { .index = N_LOG,
-                 .conflicts = { { &nopts, N_SIZE },
-                                { NULL, LAST_CONFLICT } },
-                 .minval = XFS_MIN_REC_DIRSIZE,
-                 .maxval = XFS_MAX_BLOCKSIZE_LOG,
-                 .defaultval = SUBOPT_NEEDS_VAL,
-               },
                { .index = N_SIZE,
-                 .conflicts = { { &nopts, N_LOG },
-                                { NULL, LAST_CONFLICT } },
+                 .conflicts = { { NULL, LAST_CONFLICT } },
                  .convert = true,
                  .is_power_2 = true,
                  .minval = 1 << XFS_MIN_REC_DIRSIZE,
@@ -646,7 +589,8 @@ struct opt_params ropts = {
                  .defaultval = SUBOPT_NEEDS_VAL,
                },
                { .index = R_DEV,
-                 .conflicts = { { NULL, LAST_CONFLICT } },
+                 .conflicts = { { &ropts, R_NAME },
+                                { NULL, LAST_CONFLICT } },
                  .defaultval = SUBOPT_NEEDS_VAL,
                },
                { .index = R_FILE,
@@ -656,7 +600,8 @@ struct opt_params ropts = {
                  .conflicts = { { NULL, LAST_CONFLICT } },
                },
                { .index = R_NAME,
-                 .conflicts = { { NULL, LAST_CONFLICT } },
+                 .conflicts = { { &ropts, R_DEV },
+                                { NULL, LAST_CONFLICT } },
                  .defaultval = SUBOPT_NEEDS_VAL,
                },
                { .index = R_NOALIGN,
@@ -671,31 +616,13 @@ struct opt_params ropts = {
 struct opt_params sopts = {
        .name = 's',
        .subopts = {
-               [S_LOG] = "log",
-               [S_SECTLOG] = "sectlog",
                [S_SIZE] = "size",
                [S_SECTSIZE] = "sectsize",
        },
        .subopt_params = {
-               { .index = S_LOG,
-                 .conflicts = { { &sopts, S_SIZE },
-                                { &sopts, S_SECTSIZE },
-                                { NULL, LAST_CONFLICT } },
-                 .minval = XFS_MIN_SECTORSIZE_LOG,
-                 .maxval = XFS_MAX_SECTORSIZE_LOG,
-                 .defaultval = SUBOPT_NEEDS_VAL,
-               },
-               { .index = S_SECTLOG,
-                 .conflicts = { { &sopts, S_SIZE },
-                                { &sopts, S_SECTSIZE },
-                                { NULL, LAST_CONFLICT } },
-                 .minval = XFS_MIN_SECTORSIZE_LOG,
-                 .maxval = XFS_MAX_SECTORSIZE_LOG,
-                 .defaultval = SUBOPT_NEEDS_VAL,
-               },
                { .index = S_SIZE,
-                 .conflicts = { { &sopts, S_LOG },
-                                { &sopts, S_SECTLOG },
+                 .conflicts = { { &sopts, S_SECTSIZE },
+                                { &dopts, D_SECTSIZE },
                                 { NULL, LAST_CONFLICT } },
                  .convert = true,
                  .is_power_2 = true,
@@ -704,8 +631,8 @@ struct opt_params sopts = {
                  .defaultval = SUBOPT_NEEDS_VAL,
                },
                { .index = S_SECTSIZE,
-                 .conflicts = { { &sopts, S_LOG },
-                                { &sopts, S_SECTLOG },
+                 .conflicts = { { &sopts, S_SIZE },
+                                { &dopts, D_SECTSIZE },
                                 { NULL, LAST_CONFLICT } },
                  .convert = true,
                  .is_power_2 = true,
@@ -832,7 +759,6 @@ struct cli_params {
 
        /* parameters where 0 is not a valid value */
        int64_t agcount;
-       int     dirblocklog;
        int     inodesize;
        int     inopblock;
        int     imaxpct;
@@ -926,25 +852,24 @@ static void __attribute__((noreturn))
 usage( void )
 {
        fprintf(stderr, _("Usage: %s\n\
-/* blocksize */                [-b log=n|size=num]\n\
+/* blocksize */                [-b size=num]\n\
 /* metadata */         [-m crc=0|1,finobt=0|1,uuid=xxx,rmapbt=0|1,reflink=0|1]\n\
 /* data subvol */      [-d agcount=n,agsize=n,file,name=xxx,size=num,\n\
                            (sunit=value,swidth=value|su=num,sw=num|noalign),\n\
-                           sectlog=n|sectsize=num\n\
+                           sectsize=num\n\
 /* force overwrite */  [-f]\n\
 /* inode size */       [-i log=n|perblock=n|size=num,maxpct=n,attr=0|1|2,\n\
                            projid32bit=0|1,sparse=0|1]\n\
 /* no discard */       [-K]\n\
 /* log subvol */       [-l agnum=n,internal,size=num,logdev=xxx,version=n\n\
-                           sunit=value|su=num,sectlog=n|sectsize=num,\n\
-                           lazy-count=0|1]\n\
+                           sunit=value|su=num,sectsize=num,lazy-count=0|1]\n\
 /* label */            [-L label (maximum 12 characters)]\n\
-/* naming */           [-n log=n|size=num,version=2|ci,ftype=0|1]\n\
+/* naming */           [-n size=num,version=2|ci,ftype=0|1]\n\
 /* no-op info only */  [-N]\n\
 /* prototype file */   [-p fname]\n\
 /* quiet */            [-q]\n\
 /* realtime subvol */  [-r extsize=num,size=num,rtdev=xxx]\n\
-/* sectorsize */       [-s log=n|size=num]\n\
+/* sectorsize */       [-s size=num]\n\
 /* version */          [-V]\n\
                        devicename\n\
 <devicename> is required unless -d name=xxx is given.\n\
@@ -963,8 +888,8 @@ conflict(
        int                     conflict)
 {
        fprintf(stderr, _("Cannot specify both -%c %s and -%c %s\n"),
-                       opts->name, opts->subopts[option],
-                       con_opts->name, con_opts->subopts[conflict]);
+                       con_opts->name, con_opts->subopts[conflict],
+                       opts->name, opts->subopts[option]);
        usage();
 }
 
@@ -974,7 +899,7 @@ illegal(
        const char      *value,
        const char      *opt)
 {
-       fprintf(stderr, _("Illegal value %s for -%s option\n"), value, opt);
+       fprintf(stderr, _("Invalid value %s for -%s option\n"), value, opt);
        usage();
 }
 
@@ -1330,9 +1255,9 @@ illegal_option(
        const char              *reason)
 {
        fprintf(stderr,
-               _("Illegal value %s for -%c %s option. %s\n"),
+               _("Invalid value %s for -%c %s option. %s\n"),
                value, opts->name, opts->subopts[index],
-               reason ? reason : "");
+               reason);
        usage();
 }
 
@@ -1423,18 +1348,20 @@ getnum(
 
                c = strtoll(str, &str_end, 0);
                if (c == 0 && str_end == str)
-                       illegal_option(str, opts, index, NULL);
+                       illegal_option(str, opts, index,
+                                       _("Value not recognized as number."));
                if (*str_end != '\0')
-                       illegal_option(str, opts, index, NULL);
+                       illegal_option(str, opts, index,
+                                       _("Unit suffixes are not allowed."));
        }
 
        /* Validity check the result. */
        if (c < sp->minval)
-               illegal_option(str, opts, index, _("value is too small"));
+               illegal_option(str, opts, index, _("Value is too small."));
        else if (c > sp->maxval)
-               illegal_option(str, opts, index, _("value is too large"));
+               illegal_option(str, opts, index, _("Value is too large."));
        if (sp->is_power_2 && !ispow2(c))
-               illegal_option(str, opts, index, _("value must be a power of 2"));
+               illegal_option(str, opts, index, _("Value must be a power of 2."));
        return c;
 }
 
@@ -1465,15 +1392,9 @@ block_opts_parser(
        char                    *value,
        struct cli_params       *cli)
 {
-       int                     blocklog;
-
        switch (subopt) {
-       case B_LOG:
-               blocklog = getnum(value, opts, B_LOG);
-               cli->blocksize = 1 << blocklog;
-               break;
        case B_SIZE:
-               cli->blocksize = getnum(value, opts, B_SIZE);
+               cli->blocksize = getnum(value, opts, subopt);
                break;
        default:
                return -EINVAL;
@@ -1488,64 +1409,54 @@ data_opts_parser(
        char                    *value,
        struct cli_params       *cli)
 {
-       int                     sectorlog;
-
        switch (subopt) {
        case D_AGCOUNT:
-               cli->agcount = getnum(value, opts, D_AGCOUNT);
+               cli->agcount = getnum(value, opts, subopt);
                break;
        case D_AGSIZE:
-               cli->agsize = getstr(value, opts, D_AGSIZE);
+               cli->agsize = getstr(value, opts, subopt);
                break;
        case D_FILE:
-               cli->xi->disfile = getnum(value, opts, D_FILE);
+               cli->xi->disfile = getnum(value, opts, subopt);
                break;
        case D_NAME:
-               cli->xi->dname = getstr(value, opts, D_NAME);
+               cli->xi->dname = getstr(value, opts, subopt);
                break;
        case D_SIZE:
-               cli->dsize = getstr(value, opts, D_SIZE);
+               cli->dsize = getstr(value, opts, subopt);
                break;
        case D_SUNIT:
-               cli->dsunit = getnum(value, opts, D_SUNIT);
+               cli->dsunit = getnum(value, opts, subopt);
                break;
        case D_SWIDTH:
-               cli->dswidth = getnum(value, opts, D_SWIDTH);
+               cli->dswidth = getnum(value, opts, subopt);
                break;
        case D_SU:
-               cli->dsu = getstr(value, opts, D_SU);
+               cli->dsu = getstr(value, opts, subopt);
                break;
        case D_SW:
-               cli->dsw = getnum(value, opts, D_SW);
+               cli->dsw = getnum(value, opts, subopt);
                break;
        case D_NOALIGN:
-               cli->sb_feat.nodalign = getnum(value, opts, D_NOALIGN);
-               break;
-       case D_SECTLOG:
-               if (cli->sectorsize)
-                       conflict(opts, D_SECTSIZE, opts, D_SECTLOG);
-               sectorlog = getnum(value, opts, D_SECTLOG);
-               cli->sectorsize = 1 << sectorlog;
+               cli->sb_feat.nodalign = getnum(value, opts, subopt);
                break;
        case D_SECTSIZE:
-               if (cli->sectorsize)
-                       conflict(opts, D_SECTSIZE, opts, D_SECTLOG);
-               cli->sectorsize = getnum(value, opts, D_SECTSIZE);
+               cli->sectorsize = getnum(value, opts, subopt);
                break;
        case D_RTINHERIT:
-               if (getnum(value, opts, D_RTINHERIT))
+               if (getnum(value, opts, subopt))
                        cli->fsx.fsx_xflags |= XFS_DIFLAG_RTINHERIT;
                break;
        case D_PROJINHERIT:
-               cli->fsx.fsx_projid = getnum(value, opts, D_PROJINHERIT);
+               cli->fsx.fsx_projid = getnum(value, opts, subopt);
                cli->fsx.fsx_xflags |= XFS_DIFLAG_PROJINHERIT;
                break;
        case D_EXTSZINHERIT:
-               cli->fsx.fsx_extsize = getnum(value, opts, D_EXTSZINHERIT);
+               cli->fsx.fsx_extsize = getnum(value, opts, subopt);
                cli->fsx.fsx_xflags |= XFS_DIFLAG_EXTSZINHERIT;
                break;
        case D_COWEXTSIZE:
-               cli->fsx.fsx_cowextsize = getnum(value, opts, D_COWEXTSIZE);
+               cli->fsx.fsx_cowextsize = getnum(value, opts, subopt);
                cli->fsx.fsx_xflags |= FS_XFLAG_COWEXTSIZE;
                break;
        default:
@@ -1561,33 +1472,27 @@ inode_opts_parser(
        char                    *value,
        struct cli_params       *cli)
 {
-       int                     inodelog;
-
        switch (subopt) {
        case I_ALIGN:
-               cli->sb_feat.inode_align = getnum(value, opts, I_ALIGN);
-               break;
-       case I_LOG:
-               inodelog = getnum(value, opts, I_LOG);
-               cli->inodesize = 1 << inodelog;
+               cli->sb_feat.inode_align = getnum(value, opts, subopt);
                break;
        case I_MAXPCT:
-               cli->imaxpct = getnum(value, opts, I_MAXPCT);
+               cli->imaxpct = getnum(value, opts, subopt);
                break;
        case I_PERBLOCK:
-               cli->inopblock = getnum(value, opts, I_PERBLOCK);
+               cli->inopblock = getnum(value, opts, subopt);
                break;
        case I_SIZE:
-               cli->inodesize = getnum(value, opts, I_SIZE);
+               cli->inodesize = getnum(value, opts, subopt);
                break;
        case I_ATTR:
-               cli->sb_feat.attr_version = getnum(value, opts, I_ATTR);
+               cli->sb_feat.attr_version = getnum(value, opts, subopt);
                break;
        case I_PROJID32BIT:
-               cli->sb_feat.projid32bit = getnum(value, opts, I_PROJID32BIT);
+               cli->sb_feat.projid32bit = getnum(value, opts, subopt);
                break;
        case I_SPINODES:
-               cli->sb_feat.spinodes = getnum(value, opts, I_SPINODES);
+               cli->sb_feat.spinodes = getnum(value, opts, subopt);
                break;
        default:
                return -EINVAL;
@@ -1602,44 +1507,38 @@ log_opts_parser(
        char                    *value,
        struct cli_params       *cli)
 {
-       int                     lsectorlog;
-
        switch (subopt) {
        case L_AGNUM:
-               cli->logagno = getnum(value, opts, L_AGNUM);
+               cli->logagno = getnum(value, opts, subopt);
                break;
        case L_FILE:
-               cli->xi->lisfile = getnum(value, opts, L_FILE);
+               cli->xi->lisfile = getnum(value, opts, subopt);
                break;
        case L_INTERNAL:
-               cli->loginternal = getnum(value, opts, L_INTERNAL);
+               cli->loginternal = getnum(value, opts, subopt);
                break;
        case L_SU:
-               cli->lsu = getstr(value, opts, L_SU);
+               cli->lsu = getstr(value, opts, subopt);
                break;
        case L_SUNIT:
-               cli->lsunit = getnum(value, opts, L_SUNIT);
+               cli->lsunit = getnum(value, opts, subopt);
                break;
        case L_NAME:
        case L_DEV:
-               cli->xi->logname = getstr(value, opts, L_NAME);
+               cli->xi->logname = getstr(value, opts, subopt);
                cli->loginternal = 0;
                break;
        case L_VERSION:
-               cli->sb_feat.log_version = getnum(value, opts, L_VERSION);
+               cli->sb_feat.log_version = getnum(value, opts, subopt);
                break;
        case L_SIZE:
-               cli->logsize = getstr(value, opts, L_SIZE);
-               break;
-       case L_SECTLOG:
-               lsectorlog = getnum(value, opts, L_SECTLOG);
-               cli->lsectorsize = 1 << lsectorlog;
+               cli->logsize = getstr(value, opts, subopt);
                break;
        case L_SECTSIZE:
-               cli->lsectorsize = getnum(value, opts, L_SECTSIZE);
+               cli->lsectorsize = getnum(value, opts, subopt);
                break;
        case L_LAZYSBCNTR:
-               cli->sb_feat.lazy_sb_counters = getnum(value, opts, L_LAZYSBCNTR);
+               cli->sb_feat.lazy_sb_counters = getnum(value, opts, subopt);
                break;
        default:
                return -EINVAL;
@@ -1656,24 +1555,24 @@ meta_opts_parser(
 {
        switch (subopt) {
        case M_CRC:
-               cli->sb_feat.crcs_enabled = getnum(value, opts, M_CRC);
+               cli->sb_feat.crcs_enabled = getnum(value, opts, subopt);
                if (cli->sb_feat.crcs_enabled)
                        cli->sb_feat.dirftype = true;
                break;
        case M_FINOBT:
-               cli->sb_feat.finobt = getnum(value, opts, M_FINOBT);
+               cli->sb_feat.finobt = getnum(value, opts, subopt);
                break;
        case M_UUID:
                if (!value || *value == '\0')
-                       reqval('m', opts->subopts, M_UUID);
+                       reqval('m', opts->subopts, subopt);
                if (platform_uuid_parse(value, &cli->uuid))
                        illegal(value, "m uuid");
                break;
        case M_RMAPBT:
-               cli->sb_feat.rmapbt = getnum(value, opts, M_RMAPBT);
+               cli->sb_feat.rmapbt = getnum(value, opts, subopt);
                break;
        case M_REFLINK:
-               cli->sb_feat.reflink = getnum(value, opts, M_REFLINK);
+               cli->sb_feat.reflink = getnum(value, opts, subopt);
                break;
        default:
                return -EINVAL;
@@ -1689,23 +1588,20 @@ naming_opts_parser(
        struct cli_params       *cli)
 {
        switch (subopt) {
-       case N_LOG:
-               cli->dirblocklog = getnum(value, opts, N_LOG);
-               break;
        case N_SIZE:
-               cli->dirblocksize = getstr(value, opts, N_SIZE);
+               cli->dirblocksize = getstr(value, opts, subopt);
                break;
        case N_VERSION:
-               value = getstr(value, &nopts, N_VERSION);
+               value = getstr(value, &nopts, subopt);
                if (!strcasecmp(value, "ci")) {
                        /* ASCII CI mode */
                        cli->sb_feat.nci = true;
                } else {
-                       cli->sb_feat.dir_version = getnum(value, opts, N_VERSION);
+                       cli->sb_feat.dir_version = getnum(value, opts, subopt);
                }
                break;
        case N_FTYPE:
-               cli->sb_feat.dirftype = getnum(value, opts, N_FTYPE);
+               cli->sb_feat.dirftype = getnum(value, opts, subopt);
                break;
        default:
                return -EINVAL;
@@ -1722,20 +1618,20 @@ rtdev_opts_parser(
 {
        switch (subopt) {
        case R_EXTSIZE:
-               cli->rtextsize = getstr(value, opts, R_EXTSIZE);
+               cli->rtextsize = getstr(value, opts, subopt);
                break;
        case R_FILE:
-               cli->xi->risfile = getnum(value, opts, R_FILE);
+               cli->xi->risfile = getnum(value, opts, subopt);
                break;
        case R_NAME:
        case R_DEV:
-               cli->xi->rtname = getstr(value, opts, R_NAME);
+               cli->xi->rtname = getstr(value, opts, subopt);
                break;
        case R_SIZE:
-               cli->rtsize = getstr(value, opts, R_SIZE);
+               cli->rtsize = getstr(value, opts, subopt);
                break;
        case R_NOALIGN:
-               cli->sb_feat.nortalign = getnum(value, opts, R_NOALIGN);
+               cli->sb_feat.nortalign = getnum(value, opts, subopt);
                break;
        default:
                return -EINVAL;
@@ -1750,22 +1646,10 @@ sector_opts_parser(
        char                    *value,
        struct cli_params       *cli)
 {
-       int                     sectorlog;
-
        switch (subopt) {
-       case S_LOG:
-       case S_SECTLOG:
-               if (cli->sectorsize)
-                       conflict(opts, S_SECTSIZE, opts, S_SECTLOG);
-               sectorlog = getnum(value, opts, S_SECTLOG);
-               cli->sectorsize = 1 << sectorlog;
-               cli->lsectorsize = cli->sectorsize;
-               break;
        case S_SIZE:
        case S_SECTSIZE:
-               if (cli->sectorsize)
-                       conflict(opts, S_SECTSIZE, opts, S_SECTLOG);
-               cli->sectorsize = getnum(value, opts, S_SECTSIZE);
+               cli->sectorsize = getnum(value, opts, subopt);
                cli->lsectorsize = cli->sectorsize;
                break;
        default:
@@ -2043,28 +1927,28 @@ _("Minimum inode size for CRCs is %d bytes\n"),
                /* inodes always aligned */
                if (!cli->sb_feat.inode_align) {
                        fprintf(stderr,
-_("Inodes always aligned for CRC enabled filesytems\n"));
+_("Inodes always aligned for CRC enabled filesystems\n"));
                        usage();
                }
 
                /* lazy sb counters always on */
                if (!cli->sb_feat.lazy_sb_counters) {
                        fprintf(stderr,
-_("Lazy superblock counted always enabled for CRC enabled filesytems\n"));
+_("Lazy superblock counters always enabled for CRC enabled filesystems\n"));
                        usage();
                }
 
                /* version 2 logs always on */
                if (cli->sb_feat.log_version != 2) {
                        fprintf(stderr,
-_("V2 logs always enabled for CRC enabled filesytems\n"));
+_("V2 logs always enabled for CRC enabled filesystems\n"));
                        usage();
                }
 
                /* attr2 always on */
                if (cli->sb_feat.attr_version != 2) {
                        fprintf(stderr,
-_("V2 attribute format always enabled on CRC enabled filesytems\n"));
+_("V2 attribute format always enabled on CRC enabled filesystems\n"));
                        usage();
                }
 
@@ -2072,14 +1956,14 @@ _("V2 attribute format always enabled on CRC enabled filesytems\n"));
                /* attr2 always on */
                if (!cli->sb_feat.projid32bit) {
                        fprintf(stderr,
-_("32 bit Project IDs always enabled on CRC enabled filesytems\n"));
+_("32 bit Project IDs always enabled on CRC enabled filesystems\n"));
                        usage();
                }
 
                /* ftype always on */
                if (!cli->sb_feat.dirftype) {
                        fprintf(stderr,
-_("Directory ftype field always enabled on CRC enabled filesytems\n"));
+_("Directory ftype field always enabled on CRC enabled filesystems\n"));
                        usage();
                }
 
@@ -2100,7 +1984,7 @@ _("finobt not supported without CRC support\n"));
                }
                cli->sb_feat.finobt = false;
 
-               if (cli->sb_feat.spinodes) {
+               if (cli->sb_feat.spinodes && cli_opt_set(&iopts, I_SPINODES)) {
                        fprintf(stderr,
 _("sparse inodes not supported without CRC support\n"));
                        usage();
@@ -2129,6 +2013,13 @@ _("cowextsize not supported without reflink support\n"));
                usage();
        }
 
+       if (cli->sb_feat.reflink && cli->xi->rtname) {
+               fprintf(stderr,
+_("reflink not supported with realtime devices\n"));
+               usage();
+               cli->sb_feat.reflink = false;
+       }
+
        if (cli->sb_feat.rmapbt && cli->xi->rtname) {
                fprintf(stderr,
 _("rmapbt not supported with realtime devices\n"));
@@ -2152,8 +2043,6 @@ validate_dirblocksize(
 
        if (cli->dirblocksize)
                cfg->dirblocksize = getnum(cli->dirblocksize, &nopts, N_SIZE);
-       if (cli->dirblocklog)
-               cfg->dirblocksize = 1 << cli->dirblocklog;
 
        if (cfg->dirblocksize) {
                if (cfg->dirblocksize < cfg->blocksize ||
@@ -2208,7 +2097,7 @@ validate_inodesize(
                int     maxsz;
 
                fprintf(stderr, _("illegal inode size %d\n"), cfg->inodesize);
-               maxsz = MIN(cfg->blocksize / XFS_MIN_INODE_PERBLOCK,
+               maxsz = min(cfg->blocksize / XFS_MIN_INODE_PERBLOCK,
                            XFS_DINODE_MAX_SIZE);
                if (XFS_DINODE_MIN_SIZE == maxsz)
                        fprintf(stderr,
@@ -2319,6 +2208,7 @@ calc_stripe_factors(
        struct cli_params       *cli,
        struct fs_topology      *ft)
 {
+       long long int   big_dswidth;
        int             dsunit = 0;
        int             dswidth = 0;
        int             lsunit = 0;
@@ -2338,7 +2228,7 @@ calc_stripe_factors(
                dsw = cli->dsw;
 
        /* data sunit/swidth options */
-       if ((dsunit && !dswidth) || (!dsunit && dswidth)) {
+       if (cli_opt_set(&dopts, D_SUNIT) != cli_opt_set(&dopts, D_SWIDTH)) {
                fprintf(stderr,
 _("both data sunit and data swidth options must be specified\n"));
                usage();
@@ -2346,7 +2236,7 @@ _("both data sunit and data swidth options must be specified\n"));
 
        /* convert dsu/dsw to dsunit/dswidth and use them from now on */
        if (dsu || dsw) {
-               if ((dsu && !dsw) || (!dsu && dsw)) {
+               if (cli_opt_set(&dopts, D_SU) != cli_opt_set(&dopts, D_SW)) {
                        fprintf(stderr,
 _("both data su and data sw options must be specified\n"));
                        usage();
@@ -2359,10 +2249,18 @@ _("data su must be a multiple of the sector size (%d)\n"), cfg->sectorsize);
                }
 
                dsunit  = (int)BTOBBT(dsu);
-               dswidth = dsunit * dsw;
+               big_dswidth = (long long int)dsunit * dsw;
+               if (big_dswidth > INT_MAX) {
+                       fprintf(stderr,
+_("data stripe width (%lld) is too large of a multiple of the data stripe unit (%d)\n"),
+                               big_dswidth, dsunit);
+                       usage();
+               }
+               dswidth = big_dswidth;
        }
 
-       if (dsunit && (dswidth % dsunit != 0)) {
+       if ((dsunit && !dswidth) || (!dsunit && dswidth) ||
+           (dsunit && (dswidth % dsunit != 0))) {
                fprintf(stderr,
 _("data stripe width (%d) must be a multiple of the data stripe unit (%d)\n"),
                        dswidth, dsunit);
@@ -2383,11 +2281,20 @@ _("data stripe width (%d) must be a multiple of the data stripe unit (%d)\n"),
 
        /* if no stripe config set, use the device default */
        if (!dsunit) {
-               dsunit = ft->dsunit;
-               dswidth = ft->dswidth;
-               use_dev = true;
+               /* Ignore nonsense from device.  XXX add more validation */
+               if (ft->dsunit && ft->dswidth == 0) {
+                       fprintf(stderr,
+_("%s: Volume reports stripe unit of %d bytes and stripe width of 0, ignoring.\n"),
+                               progname, BBTOB(ft->dsunit));
+                       ft->dsunit = 0;
+                       ft->dswidth = 0;
+               } else {
+                       dsunit = ft->dsunit;
+                       dswidth = ft->dswidth;
+                       use_dev = true;
+               }
        } else {
-               /* check and warn is alignment is sub-optimal */
+               /* check and warn if user-specified alignment is sub-optimal */
                if (ft->dsunit && ft->dsunit != dsunit) {
                        fprintf(stderr,
 _("%s: Specified data stripe unit %d is not the same as the volume stripe unit %d\n"),
@@ -2508,10 +2415,10 @@ open_devices(
         * So, we reduce the size (in basic blocks) to a perfect
         * multiple of the sector size, or 1024, whichever is larger.
         */
-       sector_mask = (uint64_t)-1 << (MAX(cfg->sectorlog, 10) - BBSHIFT);
+       sector_mask = (uint64_t)-1 << (max(cfg->sectorlog, 10) - BBSHIFT);
        xi->dsize &= sector_mask;
        xi->rtsize &= sector_mask;
-       xi->logBBsize &= (uint64_t)-1 << (MAX(cfg->lsectorlog, 10) - BBSHIFT);
+       xi->logBBsize &= (uint64_t)-1 << (max(cfg->lsectorlog, 10) - BBSHIFT);
 
 
        if (!discard)
@@ -3095,12 +3002,12 @@ calculate_log_size(
        libxfs_umount(&mount);
 
        ASSERT(min_logblocks);
-       min_logblocks = MAX(XFS_MIN_LOG_BLOCKS, min_logblocks);
+       min_logblocks = max(XFS_MIN_LOG_BLOCKS, min_logblocks);
 
        /* if we have lots of blocks, check against XFS_MIN_LOG_BYTES, too */
        if (!cli->logsize &&
            cfg->dblocks >= (1024*1024*1024) >> cfg->blocklog)
-               min_logblocks = MAX(min_logblocks,
+               min_logblocks = max(min_logblocks,
                                    XFS_MIN_LOG_BYTES >> cfg->blocklog);
 
        /*
@@ -3136,7 +3043,7 @@ _("external log device %lld too small, must be at least %lld blocks\n"),
                         * XFS_MIN_LOG_BYTES for filesystems smaller than 16G if
                         * at all possible, ramping up to 128MB at 256GB.
                         */
-                       cfg->logblocks = MIN(XFS_MIN_LOG_BYTES >> cfg->blocklog,
+                       cfg->logblocks = min(XFS_MIN_LOG_BYTES >> cfg->blocklog,
                                        min_logblocks * XFS_DFL_LOG_FACTOR);
                } else {
                        /*
@@ -3150,7 +3057,7 @@ _("external log device %lld too small, must be at least %lld blocks\n"),
                }
 
                /* Ensure the chosen size meets minimum log size requirements */
-               cfg->logblocks = MAX(min_logblocks, cfg->logblocks);
+               cfg->logblocks = max(min_logblocks, cfg->logblocks);
 
                /*
                 * Make sure the log fits wholly within an AG
@@ -3162,11 +3069,11 @@ _("external log device %lld too small, must be at least %lld blocks\n"),
                 * opened to decide what is the valid maximum size of a log in
                 * an AG.
                 */
-               cfg->logblocks = MIN(cfg->logblocks,
+               cfg->logblocks = min(cfg->logblocks,
                                     libxfs_alloc_ag_max_usable(mp) - 1);
 
                /* and now clamp the size to the maximum supported size */
-               cfg->logblocks = MIN(cfg->logblocks, XFS_MAX_LOG_BLOCKS);
+               cfg->logblocks = min(cfg->logblocks, XFS_MAX_LOG_BLOCKS);
                if ((cfg->logblocks << cfg->blocklog) > XFS_MAX_LOG_BYTES)
                        cfg->logblocks = XFS_MAX_LOG_BYTES >> cfg->blocklog;
 
@@ -3263,40 +3170,6 @@ initialise_mount(
        mp->m_sectbb_log = sbp->sb_sectlog - BBSHIFT;
 }
 
-static void
-print_mkfs_cfg(
-       struct mkfs_params      *cfg,
-       char                    *dfile,
-       char                    *logfile,
-       char                    *rtfile)
-{
-       struct sb_feat_args     *fp = &cfg->sb_feat;
-
-       printf(_(
-"meta-data=%-22s isize=%-6d agcount=%lld, agsize=%lld blks\n"
-"         =%-22s sectsz=%-5u attr=%u, projid32bit=%u\n"
-"         =%-22s crc=%-8u finobt=%u, sparse=%u, rmapbt=%u, reflink=%u\n"
-"data     =%-22s bsize=%-6u blocks=%llu, imaxpct=%u\n"
-"         =%-22s sunit=%-6u swidth=%u blks\n"
-"naming   =version %-14u bsize=%-6u ascii-ci=%d ftype=%d\n"
-"log      =%-22s bsize=%-6d blocks=%lld, version=%d\n"
-"         =%-22s sectsz=%-5u sunit=%d blks, lazy-count=%d\n"
-"realtime =%-22s extsz=%-6d blocks=%lld, rtextents=%lld\n"),
-               dfile, cfg->inodesize, (long long)cfg->agcount,
-                       (long long)cfg->agsize,
-               "", cfg->sectorsize, fp->attr_version, fp->projid32bit,
-               "", fp->crcs_enabled, fp->finobt, fp->spinodes, fp->rmapbt,
-                       fp->reflink,
-               "", cfg->blocksize, (long long)cfg->dblocks, cfg->imaxpct,
-               "", cfg->dsunit, cfg->dswidth,
-               fp->dir_version, cfg->dirblocksize, fp->nci, fp->dirftype,
-               logfile, cfg->blocksize, (long long)cfg->logblocks,
-                       fp->log_version,
-               "", cfg->lsectorsize, cfg->lsunit, fp->lazy_sb_counters,
-               rtfile, (int)cfg->rtextblocks << cfg->blocklog,
-                       (long long)cfg->rtblocks, (long long)cfg->rtextents);
-}
-
 /*
  * Format everything from the generated config into the superblock that
  * will be used to initialise the on-disk superblock. This is the in-memory
@@ -3390,7 +3263,7 @@ prepare_devices(
         */
        buf = libxfs_getbuf(mp->m_ddev_targp, (xi->dsize - whack_blks),
                            whack_blks);
-       memset(XFS_BUF_PTR(buf), 0, WHACK_SIZE);
+       memset(buf->b_addr, 0, WHACK_SIZE);
        libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
        libxfs_purgebuf(buf);
 
@@ -3401,15 +3274,15 @@ prepare_devices(
         * ext[2,3] and reiserfs (64k) - and hopefully all else.
         */
        buf = libxfs_getbuf(mp->m_ddev_targp, 0, whack_blks);
-       memset(XFS_BUF_PTR(buf), 0, WHACK_SIZE);
+       memset(buf->b_addr, 0, WHACK_SIZE);
        libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
        libxfs_purgebuf(buf);
 
        /* OK, now write the superblock... */
        buf = libxfs_getbuf(mp->m_ddev_targp, XFS_SB_DADDR, XFS_FSS_TO_BB(mp, 1));
        buf->b_ops = &xfs_sb_buf_ops;
-       memset(XFS_BUF_PTR(buf), 0, cfg->sectorsize);
-       libxfs_sb_to_disk((void *)XFS_BUF_PTR(buf), sbp);
+       memset(buf->b_addr, 0, cfg->sectorsize);
+       libxfs_sb_to_disk(buf->b_addr, sbp);
        libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
        libxfs_purgebuf(buf);
 
@@ -3429,7 +3302,7 @@ prepare_devices(
                buf = libxfs_getbuf(mp->m_rtdev_targp,
                                    XFS_FSB_TO_BB(mp, cfg->rtblocks - 1LL),
                                    BTOBB(cfg->blocksize));
-               memset(XFS_BUF_PTR(buf), 0, cfg->blocksize);
+               memset(buf->b_addr, 0, cfg->blocksize);
                libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
                libxfs_purgebuf(buf);
        }
@@ -3473,8 +3346,8 @@ initialise_ag_headers(
                        XFS_AG_DADDR(mp, agno, XFS_SB_DADDR),
                        XFS_FSS_TO_BB(mp, 1));
        buf->b_ops = &xfs_sb_buf_ops;
-       memset(XFS_BUF_PTR(buf), 0, cfg->sectorsize);
-       libxfs_sb_to_disk((void *)XFS_BUF_PTR(buf), sbp);
+       memset(buf->b_addr, 0, cfg->sectorsize);
+       libxfs_sb_to_disk(buf->b_addr, sbp);
        libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
 
        /*
@@ -3512,7 +3385,7 @@ initialise_ag_headers(
        }
 
        agf->agf_flfirst = 0;
-       agf->agf_fllast = cpu_to_be32(XFS_AGFL_SIZE(mp) - 1);
+       agf->agf_fllast = cpu_to_be32(libxfs_agfl_size(mp) - 1);
        agf->agf_flcount = 0;
        agblocks = (xfs_agblock_t)(agsize - libxfs_prealloc_blocks(mp));
        agf->agf_freeblks = cpu_to_be32(agblocks);
@@ -3544,7 +3417,7 @@ initialise_ag_headers(
                agfl->agfl_magicnum = cpu_to_be32(XFS_AGFL_MAGIC);
                agfl->agfl_seqno = cpu_to_be32(agno);
                platform_uuid_copy(&agfl->agfl_uuid, &sbp->sb_uuid);
-               for (bucket = 0; bucket < XFS_AGFL_SIZE(mp); bucket++)
+               for (bucket = 0; bucket < libxfs_agfl_size(mp); bucket++)
                        agfl->agfl_bno[bucket] = cpu_to_be32(NULLAGBLOCK);
        }
 
@@ -3804,7 +3677,7 @@ initialise_ag_freespace(
        struct xfs_trans_res tres = {0};
        int                     c;
 
-       c = libxfs_trans_alloc(mp, &tres, worst_freelist, 0, 0, &tp);
+       c = -libxfs_trans_alloc(mp, &tres, worst_freelist, 0, 0, &tp);
        if (c)
                res_failed(c);
 
@@ -3902,7 +3775,7 @@ main(
                        .crcs_enabled = true,
                        .dirftype = true,
                        .finobt = true,
-                       .spinodes = false,
+                       .spinodes = true,
                        .rmapbt = false,
                        .reflink = false,
                        .parent_pointers = false,
@@ -4058,12 +3931,26 @@ main(
         */
        calculate_log_size(&cfg, &cli, mp);
 
+       finish_superblock_setup(&cfg, mp, sbp);
+
+       /* Print the intended geometry of the fs. */
        if (!quiet || dry_run) {
-               print_mkfs_cfg(&cfg, dfile, logfile, rtfile);
+               struct xfs_fsop_geom    geo;
+               int                     error;
+
+               error = -libxfs_fs_geometry(sbp, &geo,
+                               XFS_FS_GEOM_MAX_STRUCT_VER);
+               if (error) {
+                       fprintf(stderr,
+       _("%s: failed to generate filesystem geometry\n"),
+                               progname);
+                       exit(1);
+               }
+
+               xfs_report_geom(&geo, dfile, logfile, rtfile);
                if (dry_run)
                        exit(0);
        }
-       finish_superblock_setup(&cfg, mp, sbp);
 
        /*
         * we need the libxfs buffer cache from here on in.
@@ -4136,6 +4023,7 @@ main(
        if (xi.logdev && xi.logdev != xi.ddev)
                libxfs_device_close(xi.logdev);
        libxfs_device_close(xi.ddev);
+       libxfs_destroy();
 
        return 0;
 }