]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
mkfs: rework stripe calculations
authorDave Chinner <dchinner@redhat.com>
Wed, 6 Dec 2017 23:14:27 +0000 (17:14 -0600)
committerEric Sandeen <sandeen@redhat.com>
Wed, 6 Dec 2017 23:14:27 +0000 (17:14 -0600)
The data and log stripe calculations a spaghettied all over the mkfs
code. This patch pulls all of the different chunks of code together
into calc_stripe_factors() and removes all the redundant/repeated
checks and calculations that are made.

Signed-Off-By: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
mkfs/xfs_mkfs.c

index 2ca8c32d8670eb1f77b1db17c83f0f7b923d2392..fa7bb4825ff6fdd495684cb3741ec82498fa483d 100644 (file)
@@ -907,74 +907,6 @@ struct mkfs_default_params {
  */
 #define WHACK_SIZE (128 * 1024)
 
-/*
- * Convert lsu to lsunit for 512 bytes blocks and check validity of the values.
- */
-static void
-calc_stripe_factors(
-       int             dsu,
-       int             dsw,
-       int             dsectsz,
-       int             lsu,
-       int             lsectsz,
-       int             *dsunit,
-       int             *dswidth,
-       int             *lsunit)
-{
-       /* Handle data sunit/swidth options */
-       if ((*dsunit && !*dswidth) || (!*dsunit && *dswidth)) {
-               fprintf(stderr,
-                       _("both data sunit and data swidth options "
-                       "must be specified\n"));
-               usage();
-       }
-
-       if (dsu || dsw) {
-               if ((dsu && !dsw) || (!dsu && dsw)) {
-                       fprintf(stderr,
-                               _("both data su and data sw options "
-                               "must be specified\n"));
-                       usage();
-               }
-
-               if (dsu % dsectsz) {
-                       fprintf(stderr,
-                               _("data su must be a multiple of the "
-                               "sector size (%d)\n"), dsectsz);
-                       usage();
-               }
-
-               *dsunit  = (int)BTOBBT(dsu);
-               *dswidth = *dsunit * dsw;
-       }
-
-       if (*dsunit && (*dswidth % *dsunit != 0)) {
-               fprintf(stderr,
-                       _("data stripe width (%d) must be a multiple of the "
-                       "data stripe unit (%d)\n"), *dswidth, *dsunit);
-               usage();
-       }
-
-       /* Handle log sunit options */
-
-       if (lsu)
-               *lsunit = (int)BTOBBT(lsu);
-
-       /* verify if lsu/lsunit is a multiple block size */
-       if (lsu % blocksize != 0) {
-               fprintf(stderr,
-_("log stripe unit (%d) must be a multiple of the block size (%d)\n"),
-               lsu, blocksize);
-               exit(1);
-       }
-       if ((BBTOB(*lsunit) % blocksize != 0)) {
-               fprintf(stderr,
-_("log stripe unit (%d) must be a multiple of the block size (%d)\n"),
-               BBTOB(*lsunit), blocksize);
-               exit(1);
-       }
-}
-
 static void
 check_device_type(
        const char      *name,
@@ -2400,6 +2332,178 @@ validate_rtextsize(
        ASSERT(cfg->rtextblocks);
 }
 
+/*
+ * Validate the configured stripe geometry, or is none is specified, pull
+ * the configuration from the underlying device.
+ *
+ * CLI parameters come in as different units, go out as filesystem blocks.
+ */
+static void
+calc_stripe_factors(
+       struct mkfs_params      *cfg,
+       struct cli_params       *cli,
+       struct fs_topology      *ft)
+{
+       int             dsunit = 0;
+       int             dswidth = 0;
+       int             lsunit = 0;
+       int             dsu = 0;
+       int             dsw = 0;
+       int             lsu = 0;
+       bool            use_dev = false;
+
+       if (cli_opt_set(&dopts, D_SUNIT))
+               dsunit = cli->dsunit;
+       if (cli_opt_set(&dopts, D_SWIDTH))
+               dswidth = cli->dswidth;
+
+       if (cli_opt_set(&dopts, D_SU))
+               dsu = getnum(cli->dsu, &dopts, D_SU);
+       if (cli_opt_set(&dopts, D_SW))
+               dsw = cli->dsw;
+
+       /* data sunit/swidth options */
+       if ((dsunit && !dswidth) || (!dsunit && dswidth)) {
+               fprintf(stderr,
+_("both data sunit and data swidth options must be specified\n"));
+               usage();
+       }
+
+       /* convert dsu/dsw to dsunit/dswidth and use them from now on */
+       if (dsu || dsw) {
+               if ((dsu && !dsw) || (!dsu && dsw)) {
+                       fprintf(stderr,
+_("both data su and data sw options must be specified\n"));
+                       usage();
+               }
+
+               if (dsu % cfg->sectorsize) {
+                       fprintf(stderr,
+_("data su must be a multiple of the sector size (%d)\n"), cfg->sectorsize);
+                       usage();
+               }
+
+               dsunit  = (int)BTOBBT(dsu);
+               dswidth = dsunit * dsw;
+       }
+
+       if (dsunit && (dswidth % dsunit != 0)) {
+               fprintf(stderr,
+_("data stripe width (%d) must be a multiple of the data stripe unit (%d)\n"),
+                       dswidth, dsunit);
+               usage();
+       }
+
+       /* If sunit & swidth were manually specified as 0, same as noalign */
+       if ((cli_opt_set(&dopts, D_SUNIT) || cli_opt_set(&dopts, D_SU)) &&
+           !dsunit && !dswidth)
+               cfg->sb_feat.nodalign = true;
+
+       /* if we are not using alignment, don't apply device defaults */
+       if (cfg->sb_feat.nodalign) {
+               cfg->dsunit = 0;
+               cfg->dswidth = 0;
+               goto check_lsunit;
+       }
+
+       /* if no stripe config set, use the device default */
+       if (!dsunit) {
+               dsunit = ft->dsunit;
+               dswidth = ft->dswidth;
+               use_dev = true;
+       } else {
+               /* check and warn is 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"),
+                               progname, dsunit, ft->dsunit);
+               }
+               if (ft->dswidth && ft->dswidth != dswidth) {
+                       fprintf(stderr,
+_("%s: Specified data stripe width %d is not the same as the volume stripe width %d\n"),
+                               progname, dswidth, ft->dswidth);
+               }
+       }
+
+       /*
+        * now we have our stripe config, check it's a multiple of block
+        * size.
+        */
+       if ((BBTOB(dsunit) % cfg->blocksize) ||
+           (BBTOB(dswidth) % cfg->blocksize)) {
+               /*
+                * If we are using device defaults, just clear them and we're
+                * good to go. Otherwise bail out with an error.
+                */
+               if (!use_dev) {
+                       fprintf(stderr,
+_("%s: Stripe unit(%d) or stripe width(%d) is not a multiple of the block size(%d)\n"),
+                               progname, BBTOB(dsunit), BBTOB(dswidth),
+                               cfg->blocksize);
+                       exit(1);
+               }
+               dsunit = 0;
+               dswidth = 0;
+               cfg->sb_feat.nodalign = true;
+       }
+
+       /* convert from 512 byte blocks to fs blocksize */
+       cfg->dsunit = DTOBT(dsunit, cfg->blocklog);
+       cfg->dswidth = DTOBT(dswidth, cfg->blocklog);
+
+check_lsunit:
+       /* log sunit options */
+       if (cli_opt_set(&lopts, L_SUNIT))
+               lsunit = cli->lsunit;
+       else if (cli_opt_set(&lopts, L_SU))
+               lsu = getnum(cli->lsu, &lopts, L_SU);
+       else if (cfg->lsectorsize > XLOG_HEADER_SIZE)
+               lsu = cfg->blocksize; /* lsunit matches filesystem block size */
+
+       if (lsu) {
+               /* verify if lsu is a multiple block size */
+               if (lsu % cfg->blocksize != 0) {
+                       fprintf(stderr,
+       _("log stripe unit (%d) must be a multiple of the block size (%d)\n"),
+                               lsu, cfg->blocksize);
+                       usage();
+               }
+               lsunit = (int)BTOBBT(lsu);
+       }
+       if (BBTOB(lsunit) % cfg->blocksize != 0) {
+               fprintf(stderr,
+_("log stripe unit (%d) must be a multiple of the block size (%d)\n"),
+                       BBTOB(lsunit), cfg->blocksize);
+               usage();
+       }
+
+       /*
+        * check that log sunit is modulo fsblksize or default it to dsunit.
+        */
+       if (lsunit) {
+               /* convert from 512 byte blocks to fs blocks */
+               cfg->lsunit = DTOBT(lsunit, cfg->blocklog);
+       } else if (cfg->sb_feat.log_version == 2 &&
+                  cfg->loginternal && cfg->dsunit) {
+               /* lsunit and dsunit now in fs blocks */
+               cfg->lsunit = cfg->dsunit;
+       }
+
+       if (cfg->sb_feat.log_version == 2 &&
+           cfg->lsunit * cfg->blocksize > 256 * 1024) {
+               /* Warn only if specified on commandline */
+               if (cli->lsu || cli->lsunit != -1) {
+                       fprintf(stderr,
+_("log stripe unit (%d bytes) is too large (maximum is 256KiB)\n"
+  "log stripe unit adjusted to 32KiB\n"),
+                               (cfg->lsunit * cfg->blocksize));
+               }
+               /* XXX: 64k block size? */
+               cfg->lsunit = (32 * 1024) / cfg->blocksize;
+       }
+
+}
+
 static void
 print_mkfs_cfg(
        struct mkfs_params      *cfg,
@@ -3044,11 +3148,8 @@ main(
        int                     dirblocklog;
        int                     dirblocksize;
        char                    *dsize;
-       int                     dsu;
-       int                     dsw;
        int                     dsunit;
        int                     dswidth;
-       int                     dsflag;
        int                     force_overwrite;
        struct fsxattr          fsx;
        int                     imaxpct;
@@ -3069,11 +3170,8 @@ main(
        xfs_fsblock_t           logstart;
        int                     lvflag;
        int                     lsflag;
-       int                     lsuflag;
-       int                     lsunitflag;
        int                     lsectorlog;
        int                     lsectorsize;
-       int                     lsu;
        int                     lsunit;
        int                     min_logblocks;
        xfs_mount_t             *mp;
@@ -3159,14 +3257,14 @@ main(
 
        agsize = daflag = dasize = dblocks = 0;
        imflag = 0;
-       liflag = laflag = lsflag = lsuflag = lsunitflag = ldflag = lvflag = 0;
+       liflag = laflag = lsflag = ldflag = lvflag = 0;
        loginternal = 1;
        logagno = logblocks = rtblocks = rtextblocks = 0;
        imaxpct = inodelog = inopblock = isize = 0;
        dfile = logfile = rtfile = NULL;
        dsize = logsize = rtsize = protofile = NULL;
-       dsu = dsw = dsunit = dswidth = lalign = lsu = lsunit = 0;
-       dsflag = nodsflag = 0;
+       dsunit = dswidth = lalign = lsunit = 0;
+       nodsflag = 0;
        force_overwrite = 0;
        worst_freelist = 0;
        memset(&fsx, 0, sizeof(fsx));
@@ -3197,18 +3295,6 @@ main(
                        }
                        daflag = cli_opt_set(&dopts, D_AGCOUNT);
 
-                       dsunit = cli.dsunit;
-                       dswidth = cli.dswidth;
-                       dsw = cli.dsw;
-                       if (cli_opt_set(&dopts, D_SU)) {
-                               dsu = getnum(cli.dsu, &dopts, D_SU);
-                               dsflag = 1;
-                       }
-                       dsflag |= cli_opt_set(&dopts, D_SW) ||
-                                 cli_opt_set(&dopts, D_SUNIT) ||
-                                 cli_opt_set(&dopts, D_SWIDTH);
-                       nodsflag = cli_opt_set(&dopts, D_NOALIGN);
-
                        fsx.fsx_xflags |= cli.fsx.fsx_xflags;
                        fsx.fsx_projid = cli.fsx.fsx_projid;
                        fsx.fsx_extsize = cli.fsx.fsx_extsize;
@@ -3231,13 +3317,6 @@ main(
                        logfile = xi.logname;
                        logsize = cli.logsize;
 
-                       lsunit = cli.lsunit;
-                       lsunitflag = cli_opt_set(&lopts, L_SUNIT);
-                       if (cli_opt_set(&lopts, L_SU)) {
-                               lsu = getnum(cli.lsu, &lopts, L_SU);
-                               lsuflag = 1;
-                       }
-
                        laflag = cli_opt_set(&lopts, L_AGNUM);
                        liflag = cli_opt_set(&lopts, L_INTERNAL);
                        ldflag = cli_opt_set(&lopts, L_NAME) ||
@@ -3326,6 +3405,7 @@ main(
        cfg.rtblocks = calc_dev_size(cli.rtsize, &cfg, &ropts, R_SIZE, "rt");
 
        validate_rtextsize(&cfg, &cli, &ft);
+       calc_stripe_factors(&cfg, &cli, &ft);
 
        /* temp don't break code */
        sectorsize = cfg.sectorsize;
@@ -3345,16 +3425,13 @@ main(
        logblocks = cfg.logblocks;
        rtblocks = cfg.rtblocks;
        rtextblocks = cfg.rtextblocks;
+       dsunit = cfg.dsunit;
+       dswidth = cfg.dswidth;
+       lsunit = cfg.lsunit;
+       nodsflag = cfg.sb_feat.nodalign;
        /* end temp don't break code */
 
 
-       calc_stripe_factors(dsu, dsw, sectorsize, lsu, lsectorsize,
-                               &dsunit, &dswidth, &lsunit);
-
-       /* If sunit & swidth were manually specified as 0, same as noalign */
-       if (dsflag && !dsunit && !dswidth)
-               nodsflag = 1;
-
        xi.setblksize = sectorsize;
 
        /*
@@ -3482,29 +3559,6 @@ reported by the device (%u).\n"),
                nbmblocks = 0;
        }
 
-       if (!nodsflag) {
-               if (dsunit) {
-                       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"),
-                                       progname, dsunit, ft.dsunit);
-                       }
-                       if (ft.dswidth && ft.dswidth != dswidth) {
-                               fprintf(stderr,
-                                       _("%s: Specified data stripe width %d "
-                                       "is not the same as the volume stripe "
-                                       "width %d\n"),
-                                       progname, dswidth, ft.dswidth);
-                       }
-               } else {
-                       dsunit = ft.dsunit;
-                       dswidth = ft.dswidth;
-                       nodsflag = 1;
-               }
-       } /* else dsunit & dswidth can't be set if nodsflag is set */
-
        if (dasize) {           /* User-specified AG size */
                /*
                 * Check specified agsize is a multiple of blocksize.
@@ -3645,30 +3699,6 @@ an AG size that is one stripe unit smaller, for example %llu.\n"),
        if (!imflag)
                imaxpct = calc_default_imaxpct(blocklog, dblocks);
 
-       /*
-        * check that log sunit is modulo fsblksize or default it to dsunit.
-        */
-
-       if (lsunit) {
-               /* convert from 512 byte blocks to fs blocks */
-               lsunit = DTOBT(lsunit, blocklog);
-       } else if (sb_feat.log_version == 2 && loginternal && dsunit) {
-               /* lsunit and dsunit now in fs blocks */
-               lsunit = dsunit;
-       }
-
-       if (sb_feat.log_version == 2 && (lsunit * blocksize) > 256 * 1024) {
-               /* Warn only if specified on commandline */
-               if (lsuflag || lsunitflag) {
-                       fprintf(stderr,
-       _("log stripe unit (%d bytes) is too large (maximum is 256KiB)\n"),
-                               (lsunit * blocksize));
-                       fprintf(stderr,
-       _("log stripe unit adjusted to 32KiB\n"));
-               }
-               lsunit = (32 * 1024) >> blocklog;
-       }
-
        min_logblocks = max_trans_res(agsize,
                                   sb_feat.crcs_enabled, sb_feat.dir_version,
                                   sectorlog, blocklog, inodelog, dirblocklog,