[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-ppc] [PATCH 4/5] Migration: migrate ccs_list in spapr state
From: |
David Gibson |
Subject: |
Re: [Qemu-ppc] [PATCH 4/5] Migration: migrate ccs_list in spapr state |
Date: |
Fri, 22 Apr 2016 14:28:45 +1000 |
User-agent: |
Mutt/1.5.24 (2015-08-30) |
On Thu, Apr 21, 2016 at 10:22:10AM -0700, Jianjun Duan wrote:
>
>
> On 04/19/2016 10:14 PM, David Gibson wrote:
> >On Fri, Apr 15, 2016 at 01:33:04PM -0700, Jianjun Duan wrote:
> >>ccs_list in spapr state maintains the device tree related
> >>information on the rtas side for hotplugged devices. In racing
> >>situations between hotplug events and migration operation, a rtas
> >>hotplug event could be migrated from the source guest to target
> >>guest, or the source guest could have not yet finished fetching
> >>the device tree when migration is started, the target will try
> >>to finish fetching the device tree. By migrating ccs_list, the
> >>target can fetch the device tree properly.
> >>
> >>We tracked the size of ccs_list queue, and introduced a dynamic
> >>cache for ccs_list to get around having to create VMSD for the
> >>queue. There also existence tests in place for the newly added
> >>fields in the spapr state VMSD to make sure forward migration
> >>is not broken.
> >>
> >>Signed-off-by: Jianjun Duan <address@hidden>
> >So there's problems here at a couple of levels.
> >
> >1. Even more so that the indicators, this is transitional state, which
> >it would be really nice if we can avoid migrating. At the very least
> >the new state should go into a subsection with an is_needed function
> >which will skip it if we don't have a configure connector in progress.
> >That means we'll be able to backwards migrate as long as we're not in
> >the middle of a hotplug, which won't be possible with this version.
> >
> >Again, if there's some way we can defer or retry the operation instead
> >of migrating the interim state, that would be even better.
> I am not sure why transitional state should not be migrated.
Because every extra piece of state to migrate is something which can
go wrong. Getting migration working properly is a difficult and
fragile process as it is - every extra bit of state we add makes it
harder.
> I think the
> fact that it changes is the reason why it should be migrated. As for
> backward migration, I thought about it, but decided to leave it later
> to beat the time. We can do it later, or do it this time and delayed the
> patches more. I agree that subsection seems to be the solution here.
Leaving backwards migration until later - after you've already
introduced a new stream version - will make implementing it much, much
more difficult.
> >2. Having to copy the list of elements out into an array just for
> >migration is pretty horrible. I'm almost include to suggest we should
> >add list migration into the savevm core rather than this.
> I thought about a general approach of adding something to savevm to
> handle the queue. But the queue used here uses macro and doesn't really
> support polymorphism. And we need to use QTAILQ_FOREACH(var, head, field)
> to access it. It is not easy as we may need to modify the macro definition
> to carry
> type name of the elements of the queue.
>
> Also I am following Alexey's code here ([PATCH qemu v15 07/17] spapr_iommu:
> Migrate full state).
> It was reviewed by you.
Yeah. It's not incorrect, but it's ugly and every extra time I see
it, the impetus to find a better way increases.
> >>---
> >> hw/ppc/spapr.c | 60
> >> ++++++++++++++++++++++++++++++++++++++++++++-
> >> hw/ppc/spapr_rtas.c | 2 ++
> >> include/hw/ppc/spapr.h | 11 +++++++++
> >> include/migration/vmstate.h | 8 +++++-
> >> 4 files changed, 79 insertions(+), 2 deletions(-)
> >>
> >>diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> >>index af4745c..eab95f0 100644
> >>--- a/hw/ppc/spapr.c
> >>+++ b/hw/ppc/spapr.c
> >>@@ -1245,10 +1245,31 @@ static bool spapr_vga_init(PCIBus *pci_bus, Error
> >>**errp)
> >> }
> >> }
> >>+static void spapr_pre_save(void *opaque)
> >>+{
> >>+ sPAPRMachineState *spapr = (sPAPRMachineState *)opaque;
> >>+ sPAPRConfigureConnectorState *ccs;
> >>+ sPAPRConfigureConnectorStateCache *ccs_cache;
> >>+
> >>+ /* Copy ccs_list to ccs_list_cache */
> >>+ spapr->ccs_list_cache = g_new0(sPAPRConfigureConnectorStateCache,
> >>+ spapr->ccs_list_num);
> >>+ ccs_cache = spapr->ccs_list_cache;
> >>+ QTAILQ_FOREACH(ccs, &spapr->ccs_list, next) {
> >>+ ccs_cache->drc_index = ccs->drc_index;
> >>+ ccs_cache->fdt_offset = ccs->fdt_offset;
> >>+ ccs_cache->fdt_depth = ccs->fdt_depth;
> >>+ ccs_cache++;
> >>+ }
> >>+}
> >>+
> >> static int spapr_post_load(void *opaque, int version_id)
> >> {
> >> sPAPRMachineState *spapr = (sPAPRMachineState *)opaque;
> >> int err = 0;
> >>+ sPAPRConfigureConnectorState *ccs;
> >>+ sPAPRConfigureConnectorStateCache *ccs_cache = spapr->ccs_list_cache;
> >>+ int index = 0;
> >> /* In earlier versions, there was no separate qdev for the PAPR
> >> * RTC, so the RTC offset was stored directly in sPAPREnvironment.
> >>@@ -1258,6 +1279,19 @@ static int spapr_post_load(void *opaque, int
> >>version_id)
> >> err = spapr_rtc_import_offset(spapr->rtc, spapr->rtc_offset);
> >> }
> >>+ if (version_id < 4) {
> >>+ return err;
> >>+ }
> >>+ /* Copy ccs_list_cache to ccs_list */
> >>+ for (index = 0; index < spapr->ccs_list_num; index ++) {
> >>+ ccs = g_new0(sPAPRConfigureConnectorState, 1);
> >>+ ccs->drc_index = (ccs_cache + index)->drc_index;
> >>+ ccs->fdt_offset = (ccs_cache + index)->fdt_offset;
> >>+ ccs->fdt_depth = (ccs_cache + index)->fdt_depth;
> >>+ QTAILQ_INSERT_TAIL(&spapr->ccs_list, ccs, next);
> >>+ }
> >>+ g_free(spapr->ccs_list_cache);
> >>+
> >> return err;
> >> }
> >>@@ -1266,10 +1300,28 @@ static bool version_before_3(void *opaque, int
> >>version_id)
> >> return version_id < 3;
> >> }
> >>+static bool version_ge_4(void *opaque, int version_id)
> >>+{
> >>+ return version_id >= 4;
> >>+}
> >>+
> >>+static const VMStateDescription vmstate_spapr_ccs_cache = {
> >>+ .name = "spaprconfigureconnectorstate",
> >>+ .version_id = 1,
> >>+ .minimum_version_id = 1,
> >>+ .fields = (VMStateField[]) {
> >>+ VMSTATE_UINT32(drc_index, sPAPRConfigureConnectorStateCache),
> >>+ VMSTATE_INT32(fdt_offset, sPAPRConfigureConnectorStateCache),
> >>+ VMSTATE_INT32(fdt_depth, sPAPRConfigureConnectorStateCache),
> >>+ VMSTATE_END_OF_LIST()
> >>+ },
> >>+};
> >>+
> >> static const VMStateDescription vmstate_spapr = {
> >> .name = "spapr",
> >>- .version_id = 3,
> >>+ .version_id = 4,
> >> .minimum_version_id = 1,
> >>+ .pre_save = spapr_pre_save,
> >> .post_load = spapr_post_load,
> >> .fields = (VMStateField[]) {
> >> /* used to be @next_irq */
> >>@@ -1279,6 +1331,12 @@ static const VMStateDescription vmstate_spapr = {
> >> VMSTATE_UINT64_TEST(rtc_offset, sPAPRMachineState,
> >> version_before_3),
> >> VMSTATE_PPC_TIMEBASE_V(tb, sPAPRMachineState, 2),
> >>+ /* RTAS state */
> >>+ VMSTATE_INT32_TEST(ccs_list_num, sPAPRMachineState, version_ge_4),
> >You don't generally need to write your own version test functions for
> >specific-version. Instead you can just use VMSTATE_INT32_V.
> I agree. I realized that after the code was posted here.
Ok.
> >>+ VMSTATE_STRUCT_VARRAY_ALLOC_TEST(ccs_list_cache, sPAPRMachineState,
> >>+ version_ge_4, ccs_list_num, 1,
> >>+ vmstate_spapr_ccs_cache,
> >>+
> >>sPAPRConfigureConnectorStateCache),
> >> VMSTATE_END_OF_LIST()
> >> },
> >> };
> >>diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
> >>index f073258..9cfd559 100644
> >>--- a/hw/ppc/spapr_rtas.c
> >>+++ b/hw/ppc/spapr_rtas.c
> >>@@ -70,6 +70,7 @@ static void spapr_ccs_add(sPAPRMachineState *spapr,
> >> {
> >> g_assert(!spapr_ccs_find(spapr, ccs->drc_index));
> >> QTAILQ_INSERT_HEAD(&spapr->ccs_list, ccs, next);
> >>+ spapr->ccs_list_num++;
> >> }
> >> static void spapr_ccs_remove(sPAPRMachineState *spapr,
> >>@@ -77,6 +78,7 @@ static void spapr_ccs_remove(sPAPRMachineState *spapr,
> >> {
> >> QTAILQ_REMOVE(&spapr->ccs_list, ccs, next);
> >> g_free(ccs);
> >>+ spapr->ccs_list_num--;
> >> }
> >> void spapr_ccs_reset_hook(void *opaque)
> >>diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
> >>index 815d5ee..c8be926 100644
> >>--- a/include/hw/ppc/spapr.h
> >>+++ b/include/hw/ppc/spapr.h
> >>@@ -11,6 +11,8 @@ struct VIOsPAPRBus;
> >> struct sPAPRPHBState;
> >> struct sPAPRNVRAM;
> >> typedef struct sPAPRConfigureConnectorState sPAPRConfigureConnectorState;
> >>+typedef struct sPAPRConfigureConnectorStateCache
> >>+ sPAPRConfigureConnectorStateCache;
> >> typedef struct sPAPREventLogEntry sPAPREventLogEntry;
> >> #define HPTE64_V_HPTE_DIRTY 0x0000000000000040ULL
> >>@@ -75,6 +77,9 @@ struct sPAPRMachineState {
> >> /* RTAS state */
> >> QTAILQ_HEAD(, sPAPRConfigureConnectorState) ccs_list;
> >>+ /* Temporary cache for migration purposes */
> >>+ int32_t ccs_list_num;
> >>+ sPAPRConfigureConnectorStateCache *ccs_list_cache;
> >> /*< public >*/
> >> char *kvm_type;
> >>@@ -589,6 +594,12 @@ struct sPAPRConfigureConnectorState {
> >> QTAILQ_ENTRY(sPAPRConfigureConnectorState) next;
> >> };
> >>+struct sPAPRConfigureConnectorStateCache {
> >>+ uint32_t drc_index;
> >>+ int fdt_offset;
> >>+ int fdt_depth;
> >>+};
> >>+
> >> void spapr_ccs_reset_hook(void *opaque);
> >> #define TYPE_SPAPR_RTC "spapr-rtc"
> >>diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
> >>index 1622638..7966979 100644
> >>--- a/include/migration/vmstate.h
> >>+++ b/include/migration/vmstate.h
> >>@@ -549,9 +549,10 @@ extern const VMStateInfo vmstate_info_bitmap;
> >> .offset = offsetof(_state, _field), \
> >> }
> >>-#define VMSTATE_STRUCT_VARRAY_ALLOC(_field, _state, _field_num, _version,
> >>_vmsd, _type) {\
> >>+#define VMSTATE_STRUCT_VARRAY_ALLOC_TEST(_field, _state, _test,
> >>_field_num, _version, _vmsd, _type) { \
> >> .name = (stringify(_field)), \
> >> .version_id = (_version), \
> >>+ .field_exists = (_test), \
> >> .vmsd = &(_vmsd), \
> >> .num_offset = vmstate_offset_value(_state, _field_num, int32_t), \
> >> .size = sizeof(_type), \
> >>@@ -677,6 +678,11 @@ extern const VMStateInfo vmstate_info_bitmap;
> >> VMSTATE_STRUCT_ARRAY_TEST(_field, _state, _num, NULL, _version, \
> >> _vmsd, _type)
> >>+#define VMSTATE_STRUCT_VARRAY_ALLOC(_field, _state, _field_num, _version, \
> >>+ _vmsd, _type) \
> >>+ VMSTATE_STRUCT_VARRAY_ALLOC_TEST(_field, _state, NULL, _field_num, \
> >>+ _version, _vmsd, _type)
> >>+
> >> #define VMSTATE_BUFFER_UNSAFE_INFO(_field, _state, _version, _info,
> >> _size) \
> >> VMSTATE_BUFFER_UNSAFE_INFO_TEST(_field, _state, NULL, _version,
> >> _info, \
> >> _size)
>
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
signature.asc
Description: PGP signature
[Qemu-ppc] [PATCH 1/5] spapr: ensure device trees are always associated with DRC, Jianjun Duan, 2016/04/15
[Qemu-ppc] [PATCH 2/5] Migration: Defined VMStateDescription struct for spapr_drc, Jianjun Duan, 2016/04/15
[Qemu-ppc] [PATCH 5/5] Migration: migrate pending_events of spapr state, Jianjun Duan, 2016/04/15