Re: [PATCH 3/3] utils: Deprecate inexact fractional suffix sizes

2021-02-05 Thread Daniel P . Berrangé
On Fri, Feb 05, 2021 at 08:28:31AM -0600, Eric Blake wrote:
> On 2/5/21 5:10 AM, Daniel P. Berrangé wrote:
> > On Thu, Feb 04, 2021 at 01:07:08PM -0600, Eric Blake wrote:
> >> The value '1.1k' is inexact; 1126.4 bytes is not possible, so we
> >> happen to truncate it to 1126.  Our use of fractional sizes is
> >> intended for convenience, but when a user specifies a fraction that is
> >> not a clean translation to binary, truncating/rounding behind their
> >> backs can cause confusion.  Better is to deprecate inexact values,
> >> which still leaves '1.5k' as valid, but alerts the user to spell out
> >> their values as a precise byte number in cases where they are
> >> currently being rounded.
> > 
> > I don't think we should be deprecating this, as I think it makes
> > it very user hostile.  Users who require exact answers, won't be
> > using fractional syntax in the first place. IOW, by using fractional
> > syntax you've decided that approximation is acceptable. Given that,
> > I should not have to worry about whether or not the fraction I'm
> > using is exact or truncated. It is horrible usability to say that
> > "1.1k" is invalid, while "1.5k" is valid - both are valid from my
> > POV as a user of this.
> > 
> > 
> > 
> >> Note that values like '0.1G' in the testsuite need adjustment as a
> >> result.
> >>
> >> Sadly, since qemu_strtosz() does not have an Err** parameter, we
> >> pollute to stderr.
> > 
> > This is only an warning, so setting an Err ** would not be appropriate
> > right now.
> > 
> > None the less we should add an Err **, because many of the callers
> > want an Err ** object populated, or use error_report().
> 
> That is more effort.  What's the consensus - is it important enough that
> I should spend that effort getting rid of technical debt by adding
> versions of qemu_strto* that take Err** at this point in time?

To be clear, I'm not requesting that you make it use Err** right now.

I just raise it as an idea for future technical debt removal.

Regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|




Re: [PATCH 3/3] utils: Deprecate inexact fractional suffix sizes

2021-02-05 Thread Eric Blake
On 2/5/21 5:10 AM, Daniel P. Berrangé wrote:
> On Thu, Feb 04, 2021 at 01:07:08PM -0600, Eric Blake wrote:
>> The value '1.1k' is inexact; 1126.4 bytes is not possible, so we
>> happen to truncate it to 1126.  Our use of fractional sizes is
>> intended for convenience, but when a user specifies a fraction that is
>> not a clean translation to binary, truncating/rounding behind their
>> backs can cause confusion.  Better is to deprecate inexact values,
>> which still leaves '1.5k' as valid, but alerts the user to spell out
>> their values as a precise byte number in cases where they are
>> currently being rounded.
> 
> I don't think we should be deprecating this, as I think it makes
> it very user hostile.  Users who require exact answers, won't be
> using fractional syntax in the first place. IOW, by using fractional
> syntax you've decided that approximation is acceptable. Given that,
> I should not have to worry about whether or not the fraction I'm
> using is exact or truncated. It is horrible usability to say that
> "1.1k" is invalid, while "1.5k" is valid - both are valid from my
> POV as a user of this.
> 
> 
> 
>> Note that values like '0.1G' in the testsuite need adjustment as a
>> result.
>>
>> Sadly, since qemu_strtosz() does not have an Err** parameter, we
>> pollute to stderr.
> 
> This is only an warning, so setting an Err ** would not be appropriate
> right now.
> 
> None the less we should add an Err **, because many of the callers
> want an Err ** object populated, or use error_report().

That is more effort.  What's the consensus - is it important enough that
I should spend that effort getting rid of technical debt by adding
versions of qemu_strto* that take Err** at this point in time?

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3226
Virtualization:  qemu.org | libvirt.org




Re: [PATCH 3/3] utils: Deprecate inexact fractional suffix sizes

2021-02-05 Thread Eric Blake
On 2/5/21 4:34 AM, Richard W.M. Jones wrote:
> On Thu, Feb 04, 2021 at 01:07:08PM -0600, Eric Blake wrote:
>> The value '1.1k' is inexact; 1126.4 bytes is not possible, so we
>> happen to truncate it to 1126.  Our use of fractional sizes is
>> intended for convenience, but when a user specifies a fraction that is
>> not a clean translation to binary, truncating/rounding behind their
>> backs can cause confusion.  Better is to deprecate inexact values,
>> which still leaves '1.5k' as valid, but alerts the user to spell out
>> their values as a precise byte number in cases where they are
>> currently being rounded.
>>
>> Note that values like '0.1G' in the testsuite need adjustment as a
>> result.
>>
>> Sadly, since qemu_strtosz() does not have an Err** parameter, we
>> pollute to stderr.
> 
> Does "deprecate" mean there's a plan to eventually remove this?  If so
> I think it should say that (in docs/system/deprecated.rst I think).

Yes (well, if we agree to the patch; Dan has already voiced concern that
we may not want 3/3 after all).  And that's why I posted a followup
message mentioning that I failed to commit that docs/ change before
sending my v1.  It will be in v2.

> 
> I think it would be better to remove this now or in the future since
> it's a trap for users.

It's borderline - Markus has expressed a desire to remove inexact
fractions, while Dan has expressed the desire that user convenience is
important (as long as we are clear that non-fractional values are ALWAYS
exact, and that the use of a fraction is for convenience at which point
you KNOW you are risking rounding, then allowing both 1.1M and 1.5M
instead of only one of the two is nicer).

I submitted this patch because of IRC discussion, but if it is up to
just me, I'd keep 2/3 but drop 3/3 (that is, I'm happy to deprecate
0x4000M, but not happy to deprecate 0.1G, but rather merely posted the
patch to see what the fallout is because the question had been asked on
IRC).

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3226
Virtualization:  qemu.org | libvirt.org




Re: [PATCH 3/3] utils: Deprecate inexact fractional suffix sizes

2021-02-05 Thread Daniel P . Berrangé
On Thu, Feb 04, 2021 at 01:07:08PM -0600, Eric Blake wrote:
> The value '1.1k' is inexact; 1126.4 bytes is not possible, so we
> happen to truncate it to 1126.  Our use of fractional sizes is
> intended for convenience, but when a user specifies a fraction that is
> not a clean translation to binary, truncating/rounding behind their
> backs can cause confusion.  Better is to deprecate inexact values,
> which still leaves '1.5k' as valid, but alerts the user to spell out
> their values as a precise byte number in cases where they are
> currently being rounded.

I don't think we should be deprecating this, as I think it makes
it very user hostile.  Users who require exact answers, won't be
using fractional syntax in the first place. IOW, by using fractional
syntax you've decided that approximation is acceptable. Given that,
I should not have to worry about whether or not the fraction I'm
using is exact or truncated. It is horrible usability to say that
"1.1k" is invalid, while "1.5k" is valid - both are valid from my
POV as a user of this.



> Note that values like '0.1G' in the testsuite need adjustment as a
> result.
> 
> Sadly, since qemu_strtosz() does not have an Err** parameter, we
> pollute to stderr.

This is only an warning, so setting an Err ** would not be appropriate
right now.

None the less we should add an Err **, because many of the callers
want an Err ** object populated, or use error_report().

> 
> Signed-off-by: Eric Blake 
> ---
>  tests/test-cutils.c| 4 ++--
>  tests/test-keyval.c| 4 ++--
>  tests/test-qemu-opts.c | 4 ++--
>  util/cutils.c  | 4 
>  4 files changed, 10 insertions(+), 6 deletions(-)
> 
> diff --git a/tests/test-cutils.c b/tests/test-cutils.c
> index 0c2c89d6f113..ad51fb1baa51 100644
> --- a/tests/test-cutils.c
> +++ b/tests/test-cutils.c
> @@ -2095,14 +2095,14 @@ static void test_qemu_strtosz_units(void)
> 
>  static void test_qemu_strtosz_float(void)
>  {
> -const char *str = "12.345M";
> +const char *str = "12.125M";
>  int err;
>  const char *endptr;
>  uint64_t res = 0xbaadf00d;
> 
>  err = qemu_strtosz(str, &endptr, &res);
>  g_assert_cmpint(err, ==, 0);
> -g_assert_cmpint(res, ==, 12.345 * MiB);
> +g_assert_cmpint(res, ==, 12.125 * MiB);
>  g_assert(endptr == str + 7);
>  }
> 
> diff --git a/tests/test-keyval.c b/tests/test-keyval.c
> index 13be763650b2..c951ac54cd23 100644
> --- a/tests/test-keyval.c
> +++ b/tests/test-keyval.c
> @@ -522,7 +522,7 @@ static void test_keyval_visit_size(void)
>  visit_free(v);
> 
>  /* Suffixes */
> -qdict = keyval_parse("sz1=8b,sz2=1.5k,sz3=2M,sz4=0.1G,sz5=16777215T",
> +qdict = keyval_parse("sz1=8b,sz2=1.5k,sz3=2M,sz4=0.125G,sz5=16777215T",
>   NULL, NULL, &error_abort);
>  v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
>  qobject_unref(qdict);
> @@ -534,7 +534,7 @@ static void test_keyval_visit_size(void)
>  visit_type_size(v, "sz3", &sz, &error_abort);
>  g_assert_cmphex(sz, ==, 2 * MiB);
>  visit_type_size(v, "sz4", &sz, &error_abort);
> -g_assert_cmphex(sz, ==, GiB / 10);
> +g_assert_cmphex(sz, ==, GiB / 8);
>  visit_type_size(v, "sz5", &sz, &error_abort);
>  g_assert_cmphex(sz, ==, 16777215ULL * TiB);
>  visit_check_struct(v, &error_abort);
> diff --git a/tests/test-qemu-opts.c b/tests/test-qemu-opts.c
> index f79b698e6715..6a1ea1d01c4f 100644
> --- a/tests/test-qemu-opts.c
> +++ b/tests/test-qemu-opts.c
> @@ -717,10 +717,10 @@ static void test_opts_parse_size(void)
>  g_assert_cmphex(qemu_opt_get_size(opts, "size1", 0), ==, 8);
>  g_assert_cmphex(qemu_opt_get_size(opts, "size2", 0), ==, 1536);
>  g_assert_cmphex(qemu_opt_get_size(opts, "size3", 0), ==, 2 * MiB);
> -opts = qemu_opts_parse(&opts_list_02, "size1=0.1G,size2=16777215T",
> +opts = qemu_opts_parse(&opts_list_02, "size1=0.125G,size2=16777215T",
> false, &error_abort);
>  g_assert_cmpuint(opts_count(opts), ==, 2);
> -g_assert_cmphex(qemu_opt_get_size(opts, "size1", 0), ==, GiB / 10);
> +g_assert_cmphex(qemu_opt_get_size(opts, "size1", 0), ==, GiB / 8);
>  g_assert_cmphex(qemu_opt_get_size(opts, "size2", 0), ==, 16777215ULL * 
> TiB);
> 
>  /* Beyond limit with suffix */
> diff --git a/util/cutils.c b/util/cutils.c
> index 75190565cbb5..5ec6101ae778 100644
> --- a/util/cutils.c
> +++ b/util/cutils.c
> @@ -327,6 +327,10 @@ static int do_strtosz(const char *nptr, const char **end,
>  retval = -ERANGE;
>  goto out;
>  }
> +if (mul_required && fraction * mul != (uint64_t) (fraction * mul)) {
> +fprintf(stderr, "Using a fractional size that is not an exact byte "
> +"multiple is deprecated: %s\n", nptr);
> +}
>  *result = val * mul + (uint64_t) (fraction * mul);
>  retval = 0;
> 
> -- 
> 2.30.0
> 

Regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https

Re: [PATCH 3/3] utils: Deprecate inexact fractional suffix sizes

2021-02-05 Thread Vladimir Sementsov-Ogievskiy

04.02.2021 22:07, Eric Blake wrote:

The value '1.1k' is inexact; 1126.4 bytes is not possible, so we
happen to truncate it to 1126.  Our use of fractional sizes is
intended for convenience, but when a user specifies a fraction that is
not a clean translation to binary, truncating/rounding behind their
backs can cause confusion.  Better is to deprecate inexact values,
which still leaves '1.5k' as valid, but alerts the user to spell out
their values as a precise byte number in cases where they are
currently being rounded.

Note that values like '0.1G' in the testsuite need adjustment as a
result.



Honestly, I don't agree with the reasoning. User shouldn't expect something extremely 
precise when he (is it correct use "he" here, or what is the right word?) 
specify fractional size. I doubt that someone use fractional sizes for production.

Also, this will break almost everything except for 0.5.. I don't think such 
deprecation will force people to change their habits to use 0.125 instead of 
0.1. Simpler is to move to integrals and don't care.

So, in this way we can just deprecate fractional sizes at all and don't care with them 
anymore. Or allow only "0.5" fraction as the only exclusion :)


Sadly, since qemu_strtosz() does not have an Err** parameter, we
pollute to stderr.

Signed-off-by: Eric Blake 
---
  tests/test-cutils.c| 4 ++--
  tests/test-keyval.c| 4 ++--
  tests/test-qemu-opts.c | 4 ++--
  util/cutils.c  | 4 
  4 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/tests/test-cutils.c b/tests/test-cutils.c
index 0c2c89d6f113..ad51fb1baa51 100644
--- a/tests/test-cutils.c
+++ b/tests/test-cutils.c
@@ -2095,14 +2095,14 @@ static void test_qemu_strtosz_units(void)

  static void test_qemu_strtosz_float(void)
  {
-const char *str = "12.345M";
+const char *str = "12.125M";
  int err;
  const char *endptr;
  uint64_t res = 0xbaadf00d;

  err = qemu_strtosz(str, &endptr, &res);
  g_assert_cmpint(err, ==, 0);
-g_assert_cmpint(res, ==, 12.345 * MiB);
+g_assert_cmpint(res, ==, 12.125 * MiB);
  g_assert(endptr == str + 7);
  }

diff --git a/tests/test-keyval.c b/tests/test-keyval.c
index 13be763650b2..c951ac54cd23 100644
--- a/tests/test-keyval.c
+++ b/tests/test-keyval.c
@@ -522,7 +522,7 @@ static void test_keyval_visit_size(void)
  visit_free(v);

  /* Suffixes */
-qdict = keyval_parse("sz1=8b,sz2=1.5k,sz3=2M,sz4=0.1G,sz5=16777215T",
+qdict = keyval_parse("sz1=8b,sz2=1.5k,sz3=2M,sz4=0.125G,sz5=16777215T",
   NULL, NULL, &error_abort);
  v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
  qobject_unref(qdict);
@@ -534,7 +534,7 @@ static void test_keyval_visit_size(void)
  visit_type_size(v, "sz3", &sz, &error_abort);
  g_assert_cmphex(sz, ==, 2 * MiB);
  visit_type_size(v, "sz4", &sz, &error_abort);
-g_assert_cmphex(sz, ==, GiB / 10);
+g_assert_cmphex(sz, ==, GiB / 8);
  visit_type_size(v, "sz5", &sz, &error_abort);
  g_assert_cmphex(sz, ==, 16777215ULL * TiB);
  visit_check_struct(v, &error_abort);
diff --git a/tests/test-qemu-opts.c b/tests/test-qemu-opts.c
index f79b698e6715..6a1ea1d01c4f 100644
--- a/tests/test-qemu-opts.c
+++ b/tests/test-qemu-opts.c
@@ -717,10 +717,10 @@ static void test_opts_parse_size(void)
  g_assert_cmphex(qemu_opt_get_size(opts, "size1", 0), ==, 8);
  g_assert_cmphex(qemu_opt_get_size(opts, "size2", 0), ==, 1536);
  g_assert_cmphex(qemu_opt_get_size(opts, "size3", 0), ==, 2 * MiB);
-opts = qemu_opts_parse(&opts_list_02, "size1=0.1G,size2=16777215T",
+opts = qemu_opts_parse(&opts_list_02, "size1=0.125G,size2=16777215T",
 false, &error_abort);
  g_assert_cmpuint(opts_count(opts), ==, 2);
-g_assert_cmphex(qemu_opt_get_size(opts, "size1", 0), ==, GiB / 10);
+g_assert_cmphex(qemu_opt_get_size(opts, "size1", 0), ==, GiB / 8);
  g_assert_cmphex(qemu_opt_get_size(opts, "size2", 0), ==, 16777215ULL * 
TiB);

  /* Beyond limit with suffix */
diff --git a/util/cutils.c b/util/cutils.c
index 75190565cbb5..5ec6101ae778 100644
--- a/util/cutils.c
+++ b/util/cutils.c
@@ -327,6 +327,10 @@ static int do_strtosz(const char *nptr, const char **end,
  retval = -ERANGE;
  goto out;
  }
+if (mul_required && fraction * mul != (uint64_t) (fraction * mul)) {
+fprintf(stderr, "Using a fractional size that is not an exact byte "
+"multiple is deprecated: %s\n", nptr);
+}
  *result = val * mul + (uint64_t) (fraction * mul);
  retval = 0;




--
Best regards,
Vladimir



Re: [PATCH 3/3] utils: Deprecate inexact fractional suffix sizes

2021-02-05 Thread Richard W.M. Jones
On Thu, Feb 04, 2021 at 01:07:08PM -0600, Eric Blake wrote:
> The value '1.1k' is inexact; 1126.4 bytes is not possible, so we
> happen to truncate it to 1126.  Our use of fractional sizes is
> intended for convenience, but when a user specifies a fraction that is
> not a clean translation to binary, truncating/rounding behind their
> backs can cause confusion.  Better is to deprecate inexact values,
> which still leaves '1.5k' as valid, but alerts the user to spell out
> their values as a precise byte number in cases where they are
> currently being rounded.
> 
> Note that values like '0.1G' in the testsuite need adjustment as a
> result.
> 
> Sadly, since qemu_strtosz() does not have an Err** parameter, we
> pollute to stderr.

Does "deprecate" mean there's a plan to eventually remove this?  If so
I think it should say that (in docs/system/deprecated.rst I think).

I think it would be better to remove this now or in the future since
it's a trap for users.

Rich.

> Signed-off-by: Eric Blake 
> ---
>  tests/test-cutils.c| 4 ++--
>  tests/test-keyval.c| 4 ++--
>  tests/test-qemu-opts.c | 4 ++--
>  util/cutils.c  | 4 
>  4 files changed, 10 insertions(+), 6 deletions(-)
> 
> diff --git a/tests/test-cutils.c b/tests/test-cutils.c
> index 0c2c89d6f113..ad51fb1baa51 100644
> --- a/tests/test-cutils.c
> +++ b/tests/test-cutils.c
> @@ -2095,14 +2095,14 @@ static void test_qemu_strtosz_units(void)
> 
>  static void test_qemu_strtosz_float(void)
>  {
> -const char *str = "12.345M";
> +const char *str = "12.125M";
>  int err;
>  const char *endptr;
>  uint64_t res = 0xbaadf00d;
> 
>  err = qemu_strtosz(str, &endptr, &res);
>  g_assert_cmpint(err, ==, 0);
> -g_assert_cmpint(res, ==, 12.345 * MiB);
> +g_assert_cmpint(res, ==, 12.125 * MiB);
>  g_assert(endptr == str + 7);
>  }
> 
> diff --git a/tests/test-keyval.c b/tests/test-keyval.c
> index 13be763650b2..c951ac54cd23 100644
> --- a/tests/test-keyval.c
> +++ b/tests/test-keyval.c
> @@ -522,7 +522,7 @@ static void test_keyval_visit_size(void)
>  visit_free(v);
> 
>  /* Suffixes */
> -qdict = keyval_parse("sz1=8b,sz2=1.5k,sz3=2M,sz4=0.1G,sz5=16777215T",
> +qdict = keyval_parse("sz1=8b,sz2=1.5k,sz3=2M,sz4=0.125G,sz5=16777215T",
>   NULL, NULL, &error_abort);
>  v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
>  qobject_unref(qdict);
> @@ -534,7 +534,7 @@ static void test_keyval_visit_size(void)
>  visit_type_size(v, "sz3", &sz, &error_abort);
>  g_assert_cmphex(sz, ==, 2 * MiB);
>  visit_type_size(v, "sz4", &sz, &error_abort);
> -g_assert_cmphex(sz, ==, GiB / 10);
> +g_assert_cmphex(sz, ==, GiB / 8);
>  visit_type_size(v, "sz5", &sz, &error_abort);
>  g_assert_cmphex(sz, ==, 16777215ULL * TiB);
>  visit_check_struct(v, &error_abort);
> diff --git a/tests/test-qemu-opts.c b/tests/test-qemu-opts.c
> index f79b698e6715..6a1ea1d01c4f 100644
> --- a/tests/test-qemu-opts.c
> +++ b/tests/test-qemu-opts.c
> @@ -717,10 +717,10 @@ static void test_opts_parse_size(void)
>  g_assert_cmphex(qemu_opt_get_size(opts, "size1", 0), ==, 8);
>  g_assert_cmphex(qemu_opt_get_size(opts, "size2", 0), ==, 1536);
>  g_assert_cmphex(qemu_opt_get_size(opts, "size3", 0), ==, 2 * MiB);
> -opts = qemu_opts_parse(&opts_list_02, "size1=0.1G,size2=16777215T",
> +opts = qemu_opts_parse(&opts_list_02, "size1=0.125G,size2=16777215T",
> false, &error_abort);
>  g_assert_cmpuint(opts_count(opts), ==, 2);
> -g_assert_cmphex(qemu_opt_get_size(opts, "size1", 0), ==, GiB / 10);
> +g_assert_cmphex(qemu_opt_get_size(opts, "size1", 0), ==, GiB / 8);
>  g_assert_cmphex(qemu_opt_get_size(opts, "size2", 0), ==, 16777215ULL * 
> TiB);
> 
>  /* Beyond limit with suffix */
> diff --git a/util/cutils.c b/util/cutils.c
> index 75190565cbb5..5ec6101ae778 100644
> --- a/util/cutils.c
> +++ b/util/cutils.c
> @@ -327,6 +327,10 @@ static int do_strtosz(const char *nptr, const char **end,
>  retval = -ERANGE;
>  goto out;
>  }
> +if (mul_required && fraction * mul != (uint64_t) (fraction * mul)) {
> +fprintf(stderr, "Using a fractional size that is not an exact byte "
> +"multiple is deprecated: %s\n", nptr);
> +}
>  *result = val * mul + (uint64_t) (fraction * mul);
>  retval = 0;
> 
> -- 
> 2.30.0

-- 
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
Read my programming and virtualization blog: http://rwmj.wordpress.com
Fedora Windows cross-compiler. Compile Windows programs, test, and
build Windows installers. Over 100 libraries supported.
http://fedoraproject.org/wiki/MinGW




Re: [PATCH 3/3] utils: Deprecate inexact fractional suffix sizes

2021-02-04 Thread Eric Blake
On 2/4/21 1:07 PM, Eric Blake wrote:
> The value '1.1k' is inexact; 1126.4 bytes is not possible, so we
> happen to truncate it to 1126.  Our use of fractional sizes is
> intended for convenience, but when a user specifies a fraction that is
> not a clean translation to binary, truncating/rounding behind their
> backs can cause confusion.  Better is to deprecate inexact values,
> which still leaves '1.5k' as valid, but alerts the user to spell out
> their values as a precise byte number in cases where they are
> currently being rounded.

And I promptly forgot to save my changes in my editor.  Consider this
squashed in:

diff --git i/docs/system/deprecated.rst w/docs/system/deprecated.rst
index c404c3926e6f..8e5e05a10642 100644
--- i/docs/system/deprecated.rst
+++ w/docs/system/deprecated.rst
@@ -154,6 +154,15 @@ Input parameters that take a size value should only
use a size suffix
 the value is hexadecimal.  That is, '0x20M' is deprecated, and should
 be written either as '32M' or as '0x200'.

+inexact sizes via scaled fractions (since 6.0)
+''
+
+Input parameters that take a size value should only use a fractional
+size (such as '1.5M') that will result in an exact byte value.  The
+use of inexact values (such as '1.1M') that require truncation or
+rounding is deprecated, and you should instead consider writing your
+unusual size in bytes (here, '1153433' or '1153434' as desired).
+
 QEMU Machine Protocol (QMP) commands
 



-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3226
Virtualization:  qemu.org | libvirt.org




[PATCH 3/3] utils: Deprecate inexact fractional suffix sizes

2021-02-04 Thread Eric Blake
The value '1.1k' is inexact; 1126.4 bytes is not possible, so we
happen to truncate it to 1126.  Our use of fractional sizes is
intended for convenience, but when a user specifies a fraction that is
not a clean translation to binary, truncating/rounding behind their
backs can cause confusion.  Better is to deprecate inexact values,
which still leaves '1.5k' as valid, but alerts the user to spell out
their values as a precise byte number in cases where they are
currently being rounded.

Note that values like '0.1G' in the testsuite need adjustment as a
result.

Sadly, since qemu_strtosz() does not have an Err** parameter, we
pollute to stderr.

Signed-off-by: Eric Blake 
---
 tests/test-cutils.c| 4 ++--
 tests/test-keyval.c| 4 ++--
 tests/test-qemu-opts.c | 4 ++--
 util/cutils.c  | 4 
 4 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/tests/test-cutils.c b/tests/test-cutils.c
index 0c2c89d6f113..ad51fb1baa51 100644
--- a/tests/test-cutils.c
+++ b/tests/test-cutils.c
@@ -2095,14 +2095,14 @@ static void test_qemu_strtosz_units(void)

 static void test_qemu_strtosz_float(void)
 {
-const char *str = "12.345M";
+const char *str = "12.125M";
 int err;
 const char *endptr;
 uint64_t res = 0xbaadf00d;

 err = qemu_strtosz(str, &endptr, &res);
 g_assert_cmpint(err, ==, 0);
-g_assert_cmpint(res, ==, 12.345 * MiB);
+g_assert_cmpint(res, ==, 12.125 * MiB);
 g_assert(endptr == str + 7);
 }

diff --git a/tests/test-keyval.c b/tests/test-keyval.c
index 13be763650b2..c951ac54cd23 100644
--- a/tests/test-keyval.c
+++ b/tests/test-keyval.c
@@ -522,7 +522,7 @@ static void test_keyval_visit_size(void)
 visit_free(v);

 /* Suffixes */
-qdict = keyval_parse("sz1=8b,sz2=1.5k,sz3=2M,sz4=0.1G,sz5=16777215T",
+qdict = keyval_parse("sz1=8b,sz2=1.5k,sz3=2M,sz4=0.125G,sz5=16777215T",
  NULL, NULL, &error_abort);
 v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
 qobject_unref(qdict);
@@ -534,7 +534,7 @@ static void test_keyval_visit_size(void)
 visit_type_size(v, "sz3", &sz, &error_abort);
 g_assert_cmphex(sz, ==, 2 * MiB);
 visit_type_size(v, "sz4", &sz, &error_abort);
-g_assert_cmphex(sz, ==, GiB / 10);
+g_assert_cmphex(sz, ==, GiB / 8);
 visit_type_size(v, "sz5", &sz, &error_abort);
 g_assert_cmphex(sz, ==, 16777215ULL * TiB);
 visit_check_struct(v, &error_abort);
diff --git a/tests/test-qemu-opts.c b/tests/test-qemu-opts.c
index f79b698e6715..6a1ea1d01c4f 100644
--- a/tests/test-qemu-opts.c
+++ b/tests/test-qemu-opts.c
@@ -717,10 +717,10 @@ static void test_opts_parse_size(void)
 g_assert_cmphex(qemu_opt_get_size(opts, "size1", 0), ==, 8);
 g_assert_cmphex(qemu_opt_get_size(opts, "size2", 0), ==, 1536);
 g_assert_cmphex(qemu_opt_get_size(opts, "size3", 0), ==, 2 * MiB);
-opts = qemu_opts_parse(&opts_list_02, "size1=0.1G,size2=16777215T",
+opts = qemu_opts_parse(&opts_list_02, "size1=0.125G,size2=16777215T",
false, &error_abort);
 g_assert_cmpuint(opts_count(opts), ==, 2);
-g_assert_cmphex(qemu_opt_get_size(opts, "size1", 0), ==, GiB / 10);
+g_assert_cmphex(qemu_opt_get_size(opts, "size1", 0), ==, GiB / 8);
 g_assert_cmphex(qemu_opt_get_size(opts, "size2", 0), ==, 16777215ULL * 
TiB);

 /* Beyond limit with suffix */
diff --git a/util/cutils.c b/util/cutils.c
index 75190565cbb5..5ec6101ae778 100644
--- a/util/cutils.c
+++ b/util/cutils.c
@@ -327,6 +327,10 @@ static int do_strtosz(const char *nptr, const char **end,
 retval = -ERANGE;
 goto out;
 }
+if (mul_required && fraction * mul != (uint64_t) (fraction * mul)) {
+fprintf(stderr, "Using a fractional size that is not an exact byte "
+"multiple is deprecated: %s\n", nptr);
+}
 *result = val * mul + (uint64_t) (fraction * mul);
 retval = 0;

-- 
2.30.0