From: Peter Xu <peterx@redhat.com>
To: "Philippe Mathieu-Daudé" <philmd@linaro.org>
Cc: Peter Maydell <peter.maydell@linaro.org>,
Fabiano Rosas <farosas@suse.de>,
Gerd Hoffmann <kraxel@redhat.com>,
qemu-devel@nongnu.org, qemu-block@nongnu.org,
Hanna Reitz <hreitz@redhat.com>, Kevin Wolf <kwolf@redhat.com>
Subject: Re: [PATCH v2 2/2] hw/pflash: implement update buffer for block writes
Date: Wed, 17 Jan 2024 15:52:24 +0800 [thread overview]
Message-ID: <ZaeHOCHTs0-ivm4j@x1n> (raw)
In-Reply-To: <4b7fe91d-9e96-4de4-af6f-c9be81c43ab1@linaro.org>
On Tue, Jan 16, 2024 at 05:08:28PM +0100, Philippe Mathieu-Daudé wrote:
> On 12/1/24 17:54, Peter Maydell wrote:
> > On Mon, 8 Jan 2024 at 13:06, Philippe Mathieu-Daudé <philmd@linaro.org> wrote:
> > >
> > > Hi Gerd,
> > >
> > > On 8/1/24 13:53, Philippe Mathieu-Daudé wrote:
> > > > From: Gerd Hoffmann <kraxel@redhat.com>
> > > >
> > > > Add an update buffer where all block updates are staged.
> > > > Flush or discard updates properly, so we should never see
> > > > half-completed block writes in pflash storage.
> > > >
> > > > Drop a bunch of FIXME comments ;)
> > > >
> > > > Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
> > > > Message-ID: <20240105135855.268064-3-kraxel@redhat.com>
> > > > Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
> > > > ---
> > > > hw/block/pflash_cfi01.c | 106 ++++++++++++++++++++++++++++++----------
> > > > 1 file changed, 80 insertions(+), 26 deletions(-)
>
>
> > > > +static const VMStateDescription vmstate_pflash_blk_write = {
> > > > + .name = "pflash_cfi01_blk_write",
> > > > + .version_id = 1,
> > > > + .minimum_version_id = 1,
> > > > + .needed = pflash_blk_write_state_needed,
> > > > + .fields = (const VMStateField[]) {
> > > > + VMSTATE_VBUFFER_UINT32(blk_bytes, PFlashCFI01, 0, NULL, writeblock_size),
> > >
> > > I don't get the difference with VMSTATE_VBUFFER_ALLOC_UINT32() which
> > > sets VMS_ALLOC. In this case pflash_cfi01_realize() does the alloc so
> > > we don't need VMS_ALLOC?
> >
> > Yes, that's the idea. A VMS_ALLOC vmstate type means "this
> > block of memory is dynamically sized at runtime, so when the
> > migration code is doing inbound migration it needs to
> > allocate a buffer of the right size first (based on some
> > state struct field we've already migrated) and then put the
> > incoming data into it". VMS_VBUFFER means "the size of the buffer
> > isn't a compile-time constant, so we need to fish it out of
> > some other state struct field". So:
> >
> > VMSTATE_VBUFFER_UINT32: we need to migrate (a pointer to) an array
> > of uint32_t; the size of that is in some other struct field,
> > but it's a runtime constant and we can assume the memory has
> > already been allocated
> >
> > VMSTATE_VBUFFER_ALLOC_UINT32: we need to migrate an array
> > of uint32_t of variable size dependent on the inbound migration
> > data, and so the migration code must allocate it
>
> Thanks Peter!
>
> Do you mind if we commit your explanation as is? As:
Any attempt to provide more documents there for the macros would be nice if
anyone would like to post a patch. Though some comments below for this
specific one.
>
> -- >8 --
> diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
> index 294d2d8486..5c6f6c5c32 100644
> --- a/include/migration/vmstate.h
> +++ b/include/migration/vmstate.h
> @@ -573,4 +573,6 @@ extern const VMStateInfo vmstate_info_qlist;
>
> -/* a variable length array (i.e. _type *_field) but we know the
> - * length
> +/**
> + * VMSTATE_STRUCT_VARRAY_POINTER_KNOWN:
> + *
> + * A variable length array (i.e. _type *_field) but we know the length.
> */
> @@ -678,2 +680,10 @@ extern const VMStateInfo vmstate_info_qlist;
>
> +/**
> + * VMSTATE_VBUFFER_UINT32:
> + *
> + * We need to migrate (a pointer to) an array of uint32_t; the size of
IIUC it's not an array of uint32_t, but a buffer with dynamic size. the
"uint32_t" is trying to describe the type of the size field, afaict. Same
issue for below one.
For example, comparing VMSTATE_VBUFFER_UINT32 vs VMSTATE_VBUFFER, we should
see the only difference is:
.size_offset = vmstate_offset_value(_state, _field_size, int32_t),\
vs:
.size_offset = vmstate_offset_value(_state, _field_size, uint32_t),\
I think it checks the size field to match that type.
Interestingly, when I look at the code to use the size, it looks like a bug
to me, where we always parse the size field to be int32_t..
static int vmstate_size(void *opaque, const VMStateField *field)
{
int size = field->size;
if (field->flags & VMS_VBUFFER) {
size = *(int32_t *)(opaque + field->size_offset); <----------- see here..
if (field->flags & VMS_MULTIPLY) {
size *= field->size;
}
}
return size;
}
I think it'll start to crash things when bit32 start to be used. And I had
a feeling that this is overlooked in the commit a19cbfb346 ("spice: add qxl
device") where VMSTATE_VBUFFER_UINT32 is introduced.
I don't have a good way to trivially fix it because we don't remember that
type of size in vmsd. However a simple solution could be that we convert
all existing VMSTATE_VBUFFER() (potentially, VMSTATE_PARTIAL_VBUFFER users;
there seems to have only 1 caller..) to always use uint32_t. I don't think
it's wise to try using a signed for size anyway, and it should be
compatible change as we doubled the size.
I'll hold a bit to see whether there's some comment, then I can try to post
a patch.
> + * that is in some other struct field, but it's a runtime constant and
> + * we can assume the memory has already been allocated.
> +*/
> +
> #define VMSTATE_VBUFFER_UINT32(_field, _state, _version, _test,
> _field_size) { \
> @@ -688,2 +698,9 @@ extern const VMStateInfo vmstate_info_qlist;
>
> +/**
> + * VMSTATE_VBUFFER_ALLOC_UINT32:
> + *
> + * We need to migrate an array of uint32_t of variable size dependent
> + * on the inbound migration data, and so the migration code must
> + * allocate it.
> +*/
> #define VMSTATE_VBUFFER_ALLOC_UINT32(_field, _state, _version, \
> ---
>
--
Peter Xu
next prev parent reply other threads:[~2024-01-17 7:52 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-01-08 12:53 [PATCH v2 0/2] hw/pflash: implement update buffer for block writes Philippe Mathieu-Daudé
2024-01-08 12:53 ` [PATCH v2 1/2] hw/block/pflash_cfi01: Use the LD/ST API in pflash_data_read/write Philippe Mathieu-Daudé
2024-01-08 12:53 ` [PATCH v2 2/2] hw/pflash: implement update buffer for block writes Philippe Mathieu-Daudé
2024-01-08 13:05 ` Philippe Mathieu-Daudé
2024-01-12 16:54 ` Peter Maydell
2024-01-16 16:08 ` Philippe Mathieu-Daudé
2024-01-16 16:09 ` Peter Maydell
2024-01-17 7:52 ` Peter Xu [this message]
2024-01-09 21:40 ` Richard Henderson
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=ZaeHOCHTs0-ivm4j@x1n \
--to=peterx@redhat.com \
--cc=farosas@suse.de \
--cc=hreitz@redhat.com \
--cc=kraxel@redhat.com \
--cc=kwolf@redhat.com \
--cc=peter.maydell@linaro.org \
--cc=philmd@linaro.org \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
/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;
as well as URLs for NNTP newsgroup(s).