From: "Darrick J. Wong" <darrick.wong@oracle.com>
To: Gao Xiang <hsiangkao@redhat.com>
Cc: linux-xfs <linux-xfs@vger.kernel.org>, Eric Sandeen <sandeen@redhat.com>
Subject: Re: [PATCH] mkfs.xfs: introduce sunit/swidth validation helper
Date: Mon, 3 Aug 2020 08:26:09 -0700 [thread overview]
Message-ID: <20200803152609.GA67818@magnolia> (raw)
In-Reply-To: <20200803125018.16718-1-hsiangkao@redhat.com>
On Mon, Aug 03, 2020 at 08:50:18PM +0800, Gao Xiang wrote:
> Currently stripe unit/width checking logic is all over xfsprogs.
> So, refactor the same code snippet into a single validation helper
> xfs_validate_stripe_factors(), including:
> - integer overflows of either value
> - sunit and swidth alignment wrt sector size
> - if either sunit or swidth are zero, both should be zero
> - swidth must be a multiple of sunit
>
> Signed-off-by: Gao Xiang <hsiangkao@redhat.com>
> ---
>
> This patch follows Darrick's original suggestion [1], yet I'm
> not sure if I'm doing the right thing or if something is still
> missing (e.g the meaning of six(ish) places)... So post it
> right now...
>
> TBH, especially all these naming and the helper location (whether
> in topology.c)...plus, click a dislike on calc_stripe_factors()
> itself...
>
> (Hopefully hear some advice about this... Thanks!)
>
> [1] https://lore.kernel.org/r/20200515204802.GO6714@magnolia
>
> libfrog/topology.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++
> libfrog/topology.h | 15 ++++++++++++++
> mkfs/xfs_mkfs.c | 48 ++++++++++++++++++++++----------------------
> 3 files changed, 89 insertions(+), 24 deletions(-)
>
> diff --git a/libfrog/topology.c b/libfrog/topology.c
> index b1b470c9..cf56fb03 100644
> --- a/libfrog/topology.c
> +++ b/libfrog/topology.c
> @@ -174,6 +174,41 @@ out:
> return ret;
> }
>
> +enum xfs_stripe_retcode
> +xfs_validate_stripe_factors(
libfrog functions (and enums) should be prefixed with libfrog, not xfs.
LIBFROG_STRIPEVAL_{OK,SUNIT_MISALIGN, etc.}
> + int sectorsize,
> + int *sup,
Errant space between "int" and "*sup".
> + int *swp)
Strange that a validator function has out parameters...
Also, uh, .... full names, please.
int *sunitp,
int *swidthp)
(I'm vaguely wondering why we use signed ints here vs. unsigned, but
that isn't critical...)
> +{
> + int sunit = *sup, swidth = *swp;
> +
> + if (sectorsize) {
> + long long big_swidth;
> +
> + if (sunit % sectorsize)
> + return XFS_STRIPE_RET_SUNIT_MISALIGN;
> +
> + sunit = (int)BTOBBT(sunit);
Hmm. On input, *sup is in units of bytes, but on output it can be in
units of 512b blocks? That is very surprising...
> + big_swidth = (long long)sunit * swidth;
> +
> + if (big_swidth > INT_MAX)
> + return XFS_STRIPE_RET_SWIDTH_OVERFLOW;
> + swidth = big_swidth;
> + }
> + if ((sunit && !swidth) || (!sunit && swidth))
> + return XFS_STRIPE_RET_PARTIAL_VALID;
> +
> + if (sunit > swidth)
> + return XFS_STRIPE_RET_SUNIT_TOO_LARGE;
> +
> + if (sunit && (swidth % sunit))
> + return XFS_STRIPE_RET_SWIDTH_MISALIGN;
> +
> + *sup = sunit;
...especially since in the !sectorsize case we don't change it at all.
> + *swp = swidth;
> + return XFS_STRIPE_RET_OK;
> +}
> +
> static void blkid_get_topology(
> const char *device,
> int *sunit,
> @@ -229,6 +264,21 @@ static void blkid_get_topology(
> */
> *sunit = *sunit >> 9;
> *swidth = *swidth >> 9;
> + switch (xfs_validate_stripe_factors(0, sunit, swidth)) {
> + case XFS_STRIPE_RET_OK:
> + break;
> + case XFS_STRIPE_RET_PARTIAL_VALID:
> + fprintf(stderr,
> +_("%s: Volume reports stripe unit of %d bytes and stripe width of %d bytes, ignoring.\n"),
> + progname, BBTOB(*sunit), BBTOB(*swidth));
Needs a "/* fallthrough */" comment here.
> + default:
Why don't we warn about receiving garbage geometry that produces
MISALIGN or OVERFLOW?
> + /*
> + * if firmware is broken, just give up and set both to zero,
> + * we can't trust information from this device.
> + */
> + *sunit = 0;
> + *swidth = 0;
> + }
>
> if (blkid_topology_get_alignment_offset(tp) != 0) {
> fprintf(stderr,
> diff --git a/libfrog/topology.h b/libfrog/topology.h
> index 6fde868a..e8be26b2 100644
> --- a/libfrog/topology.h
> +++ b/libfrog/topology.h
> @@ -36,4 +36,19 @@ extern int
> check_overwrite(
> const char *device);
>
> +enum xfs_stripe_retcode {
> + XFS_STRIPE_RET_OK = 0,
> + XFS_STRIPE_RET_SUNIT_MISALIGN,
> + XFS_STRIPE_RET_SWIDTH_OVERFLOW,
> + XFS_STRIPE_RET_PARTIAL_VALID,
> + XFS_STRIPE_RET_SUNIT_TOO_LARGE,
> + XFS_STRIPE_RET_SWIDTH_MISALIGN,
> +};
> +
> +enum xfs_stripe_retcode
> +xfs_validate_stripe_factors(
> + int sectorsize,
> + int *sup,
Errant space between "int" and "*sup".
> + int *swp);
> +
> #endif /* __LIBFROG_TOPOLOGY_H__ */
> diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
> index 2e6cd280..a3d6032c 100644
> --- a/mkfs/xfs_mkfs.c
> +++ b/mkfs/xfs_mkfs.c
> @@ -2255,7 +2255,6 @@ 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;
> @@ -2263,6 +2262,7 @@ calc_stripe_factors(
> int dsw = 0;
> int lsu = 0;
> bool use_dev = false;
> + int error;
>
> if (cli_opt_set(&dopts, D_SUNIT))
> dsunit = cli->dsunit;
> @@ -2289,31 +2289,40 @@ _("both data su and data sw options must be specified\n"));
> usage();
> }
>
> - if (dsu % cfg->sectorsize) {
> + dsunit = dsu;
> + dswidth = dsw;
> + error = xfs_validate_stripe_factors(cfg->sectorsize, &dsunit, &dswidth);
I thought this function returned an enum?
> + switch(error) {
> + case XFS_STRIPE_RET_SUNIT_MISALIGN:
> fprintf(stderr,
> _("data su must be a multiple of the sector size (%d)\n"), cfg->sectorsize);
> usage();
> - }
> -
> - dsunit = (int)BTOBBT(dsu);
> - big_dswidth = (long long int)dsunit * dsw;
> - if (big_dswidth > INT_MAX) {
> + break;
> + case XFS_STRIPE_RET_SWIDTH_OVERFLOW:
> fprintf(stderr,
> -_("data stripe width (%lld) is too large of a multiple of the data stripe unit (%d)\n"),
> - big_dswidth, dsunit);
> +_("data stripe width (dsw %d) is too large of a multiple of the data stripe unit (%d)\n"),
Why change this message?
> + dsw, dsunit);
> usage();
> + break;
> }
> - dswidth = big_dswidth;
> + } else {
> + error = xfs_validate_stripe_factors(0, &dsunit, &dswidth);
> }
>
> - if ((dsunit && !dswidth) || (!dsunit && dswidth) ||
> - (dsunit && (dswidth % dsunit != 0))) {
> + if (error == XFS_STRIPE_RET_PARTIAL_VALID ||
> + error == XFS_STRIPE_RET_SWIDTH_MISALIGN) {
> fprintf(stderr,
> _("data stripe width (%d) must be a multiple of the data stripe unit (%d)\n"),
> dswidth, dsunit);
> usage();
> }
>
> + if (error) {
> + fprintf(stderr,
> +_("invalid data stripe unit (%d), width (%d)\n"), dsunit, dswidth);
Invalid how? We know the exact reason, so we should say so.
--D
> + 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)
> @@ -2328,18 +2337,9 @@ _("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) {
> - /* 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;
> - }
> + dsunit = ft->dsunit;
> + dswidth = ft->dswidth;
> + use_dev = true;
> } else {
> /* check and warn if user-specified alignment is sub-optimal */
> if (ft->dsunit && ft->dsunit != dsunit) {
> --
> 2.18.1
>
next prev parent reply other threads:[~2020-08-03 15:28 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-05-15 19:14 [PATCH] mkfs.xfs: sanity check stripe geometry from blkid Eric Sandeen
2020-05-15 20:48 ` Darrick J. Wong
2020-05-15 20:54 ` Eric Sandeen
2020-05-15 21:06 ` Eric Sandeen
2020-05-15 21:10 ` Darrick J. Wong
2020-05-15 21:34 ` Eric Sandeen
2020-08-03 12:50 ` [PATCH] mkfs.xfs: introduce sunit/swidth validation helper Gao Xiang
2020-08-03 15:26 ` Darrick J. Wong [this message]
2020-08-03 15:45 ` Gao Xiang
2020-08-04 16:00 ` [PATCH v2] " Gao Xiang
2020-08-04 19:55 ` Eric Sandeen
2020-08-04 23:43 ` Gao Xiang
2020-08-06 13:03 ` [PATCH v3] " Gao Xiang
2020-09-28 23:18 ` Eric Sandeen
2020-09-29 3:06 ` Gao Xiang
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200803152609.GA67818@magnolia \
--to=darrick.wong@oracle.com \
--cc=hsiangkao@redhat.com \
--cc=linux-xfs@vger.kernel.org \
--cc=sandeen@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox