From: Markus Armbruster <armbru@redhat.com>
To: Fiona Ebner <f.ebner@proxmox.com>
Cc: qemu-devel@nongnu.org, qemu-block@nongnu.org,
eblake@redhat.com, hreitz@redhat.com, kwolf@redhat.com,
vsementsov@yandex-team.ru, jsnow@redhat.com
Subject: Re: [PATCH 1/2] copy-before-write: allow specifying minimum cluster size
Date: Tue, 14 May 2024 14:09:34 +0200 [thread overview]
Message-ID: <87plto1toh.fsf@pond.sub.org> (raw)
In-Reply-To: <1acd096c-5ec9-411d-b06e-cd64fb898852@proxmox.com> (Fiona Ebner's message of "Mon, 13 May 2024 15:24:28 +0200")
Fiona Ebner <f.ebner@proxmox.com> writes:
> Am 26.03.24 um 10:06 schrieb Markus Armbruster:
>>> @@ -365,7 +368,13 @@ BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
>>>
>>> GLOBAL_STATE_CODE();
>>>
>>> - cluster_size = block_copy_calculate_cluster_size(target->bs, errp);
>>> + if (min_cluster_size && !is_power_of_2(min_cluster_size)) {
>>
>> min_cluster_size is int64_t, is_power_of_2() takes uint64_t. Bad if
>> min_cluster_size is negative. Could this happen?
>
> No, because it comes in as a uint32_t via the QAPI (the internal caller
> added by patch 2/2 from the backup code also gets the value via QAPI and
> there uint32_t is used too).
Good.
Is there a practical way to tweak the types so it's more obvious?
>>> + error_setg(errp, "min-cluster-size needs to be a power of 2");
>>> + return NULL;
>>> + }
>>> +
>>> + cluster_size = block_copy_calculate_cluster_size(target->bs,
>>> + min_cluster_size, errp);
>>> if (cluster_size < 0) {
>>> return NULL;
>>> }
>
> ---snip---
>
>>> diff --git a/qapi/block-core.json b/qapi/block-core.json
>>> index 0a72c590a8..85c8f88f6e 100644
>>> --- a/qapi/block-core.json
>>> +++ b/qapi/block-core.json
>>> @@ -4625,12 +4625,18 @@
>>> # @on-cbw-error parameter will decide how this failure is handled.
>>> # Default 0. (Since 7.1)
>>> #
>>> +# @min-cluster-size: Minimum size of blocks used by copy-before-write
>>> +# operations. Has to be a power of 2. No effect if smaller than
>>> +# the maximum of the target's cluster size and 64 KiB. Default 0.
>>> +# (Since 9.0)
>>> +#
>>> # Since: 6.2
>>> ##
>>> { 'struct': 'BlockdevOptionsCbw',
>>> 'base': 'BlockdevOptionsGenericFormat',
>>> 'data': { 'target': 'BlockdevRef', '*bitmap': 'BlockDirtyBitmap',
>>> - '*on-cbw-error': 'OnCbwError', '*cbw-timeout': 'uint32' } }
>>> + '*on-cbw-error': 'OnCbwError', '*cbw-timeout': 'uint32',
>>> + '*min-cluster-size': 'uint32' } }
>>
>> Elsewhere in the schema, we use either 'int' or 'size' for cluster-size.
>> Why the difference?
>
> The motivation was to disallow negative values up front and have it work
> with block_copy_calculate_cluster_size(), whose result is an int64_t.
Let's see whether I understand.
cbw_open() passes the new member @min-cluster-size to
block_copy_state_new().
block_copy_state_new() checks it, and passes it on to
block_copy_calculate_cluster_size(). This is the C code shown above.
block_copy_calculate_cluster_size() uses it like
return MAX(min_cluster_size, BLOCK_COPY_CLUSTER_SIZE_DEFAULT);
and
return MAX(min_cluster_size,
MAX(BLOCK_COPY_CLUSTER_SIZE_DEFAULT, bdi.cluster_size));
BLOCK_COPY_CLUSTER_SIZE_DEFAULT and bdi.cluster_size are int. The
return type is int64_t.
Correct?
I don't like mixing signed and unsigned in MAX() like this. Figuring
out whether it's safe takes a C language lawyer. I'd rather avoid such
subtle code. Can we please compute these maxima entirely in the
destination type int64_t?
> If
> I go with 'int', I'll have to add a check to disallow negative values.
> If I go with 'size', I'll have to add a check for to disallow too large
> values.
>
> Which approach should I go with?
For me, reducing the need for manual checking is important, but
cleanliness of the external interface trumps it. I'd use 'size'.
Not the first time I see friction between QAPI 'size' or 'uint64' and
the block layer's use of int64_t.
The block layer likes to use int64_t even when the value must not be
negative. There are good reasons for that.
Perhaps a QAPI type for "non-negative int64_t" could be useful. Weird,
but useful.
next prev parent reply other threads:[~2024-05-14 12:10 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-03-08 15:51 [PATCH 0/2] backup: allow specifying minimum cluster size Fiona Ebner
2024-03-08 15:51 ` [PATCH 1/2] copy-before-write: " Fiona Ebner
2024-03-26 9:06 ` Markus Armbruster
2024-05-13 13:24 ` Fiona Ebner
2024-05-14 12:09 ` Markus Armbruster [this message]
2024-03-29 10:10 ` Vladimir Sementsov-Ogievskiy
2024-03-08 15:51 ` [PATCH 2/2] backup: add minimum cluster size to performance options Fiona Ebner
2024-03-29 10:15 ` Vladimir Sementsov-Ogievskiy
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=87plto1toh.fsf@pond.sub.org \
--to=armbru@redhat.com \
--cc=eblake@redhat.com \
--cc=f.ebner@proxmox.com \
--cc=hreitz@redhat.com \
--cc=jsnow@redhat.com \
--cc=kwolf@redhat.com \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=vsementsov@yandex-team.ru \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.