From: Dave Chinner <dchinner@xxxxxxxxxx> 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@xxxxxxxxxx> --- mkfs/xfs_mkfs.c | 330 ++++++++++++++++++++++++++++++-------------------------- 1 file changed, 180 insertions(+), 150 deletions(-) diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c index 7595e378ad44..fe380d2b388d 100644 --- a/mkfs/xfs_mkfs.c +++ b/mkfs/xfs_mkfs.c @@ -896,74 +896,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, @@ -2377,6 +2309,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 /* set default log stripe unit if not set on CLI */ + lsu = cfg->blocksize; + + 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, @@ -3015,11 +3119,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; @@ -3040,11 +3141,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; @@ -3130,14 +3228,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)); @@ -3168,18 +3266,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; @@ -3202,13 +3288,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) || @@ -3297,6 +3376,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; @@ -3316,16 +3396,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; /* @@ -3453,29 +3530,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. @@ -3614,30 +3668,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, -- 2.13.3 -- To unsubscribe from this list: send the line "unsubscribe linux-xfs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html