[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] migration regression in xen-4.11 and qemu-2.11 and qcow2
Am Thu, 10 May 2018 09:03:30 -0700 (PDT) schrieb Stefano Stabellini <sstabellini@xxxxxxxxxx>: > You could add a property to vmstate_xen_platform of xen_platform.c, but > you need to pay attention to legacy compatibility. Inevitably, there > will be older versions that do not have the new vmstate_xen_platform > field or do not set it properly. Doing the unplug on the other side works if it is done from blk_connect. At the point xen_platform_post_load is called, qemu is still in the middle of initializing. Doing it from there causes weird failures. Any idea what the proper place is to call platform_do_unplug? Olaf --- a/hw/block/xen_disk.c +++ b/hw/block/xen_disk.c @@ -31,6 +31,7 @@ #include "qapi/error.h" #include "qapi/qmp/qdict.h" #include "qapi/qmp/qstring.h" +#include "qemu/error-report.h" /* ------------------------------------------------------------- */ @@ -1074,6 +1075,9 @@ static int blk_connect(struct XenDevice unsigned int i; uint32_t *domids; + error_report("%s", __func__); + xen_unplug_after_migration(); + /* read-only ? */ if (blkdev->directiosafe) { qflags = BDRV_O_NOCACHE | BDRV_O_NATIVE_AIO; --- a/hw/i386/xen/xen_platform.c +++ b/hw/i386/xen/xen_platform.c @@ -62,6 +62,7 @@ typedef struct PCIXenPlatformState { uint8_t flags; /* used only for version_id == 2 */ int drivers_blacklisted; uint16_t driver_product_version; + uint32_t unplug_val; /* Log from guest drivers */ char log_buffer[4096]; @@ -132,8 +133,13 @@ static void del_nic_peer(NICState *nic, qemu_del_net_client(nc->peer); } +static bool pci_unplug_nics_done; static void pci_unplug_nics(PCIBus *bus) { + error_report("%s", __func__); + if (pci_unplug_nics_done) + return; + pci_unplug_nics_done = true; qemu_foreach_nic(del_nic_peer, NULL); pci_for_each_device(bus, 0, unplug_nic, NULL); } @@ -170,30 +176,43 @@ static void unplug_disks(PCIBus *b, PCID } } +static bool pci_unplug_disks_done; static void pci_unplug_disks(PCIBus *bus, uint32_t flags) { + error_report("%s", __func__); + if (pci_unplug_disks_done) + return; + pci_unplug_disks_done = true; pci_for_each_device(bus, 0, unplug_disks, &flags); } +static void platform_do_unplug(PCIXenPlatformState *s, uint32_t val) +{ + PCIDevice *pci_dev = PCI_DEVICE(s); + + error_report("%s %x", __func__, val); + /* Unplug devices. See comment above flag definitions */ + if (val & (UNPLUG_IDE_SCSI_DISKS | UNPLUG_AUX_IDE_DISKS | + UNPLUG_NVME_DISKS)) { + DPRINTF("unplug disks\n"); + pci_unplug_disks(pci_dev->bus, val); + } + if (val & UNPLUG_ALL_NICS) { + DPRINTF("unplug nics\n"); + pci_unplug_nics(pci_dev->bus); + } +} + static void platform_fixed_ioport_writew(void *opaque, uint32_t addr, uint32_t val) { PCIXenPlatformState *s = opaque; + error_report("%s %x %x", __func__, addr, val); switch (addr) { - case 0: { - PCIDevice *pci_dev = PCI_DEVICE(s); - /* Unplug devices. See comment above flag definitions */ - if (val & (UNPLUG_IDE_SCSI_DISKS | UNPLUG_AUX_IDE_DISKS | - UNPLUG_NVME_DISKS)) { - DPRINTF("unplug disks\n"); - pci_unplug_disks(pci_dev->bus, val); - } - if (val & UNPLUG_ALL_NICS) { - DPRINTF("unplug nics\n"); - pci_unplug_nics(pci_dev->bus); - } + case 0: + s->unplug_val |= val; + platform_do_unplug(s, val); break; - } case 2: switch (val) { case 1: @@ -332,8 +351,20 @@ static const MemoryRegionOps platform_fi .endianness = DEVICE_LITTLE_ENDIAN, }; +static void *PCIXenPlatformState_for_unplug_after_migration; +void xen_unplug_after_migration(void) +{ + PCIXenPlatformState *s = PCIXenPlatformState_for_unplug_after_migration; + error_report("%s", __func__); + if (s) + platform_do_unplug(s, s->unplug_val); + PCIXenPlatformState_for_unplug_after_migration = NULL; +} + static void platform_fixed_ioport_init(PCIXenPlatformState* s) { + error_report("%s", __func__); + PCIXenPlatformState_for_unplug_after_migration = s; memory_region_init_io(&s->fixed_io, OBJECT(s), &platform_fixed_io_ops, s, "xen-fixed", 16); memory_region_add_subregion(get_system_io(), XEN_PLATFORM_IOPORT, @@ -356,7 +387,7 @@ static void xen_platform_ioport_writeb(v uint64_t val, unsigned int size) { PCIXenPlatformState *s = opaque; - PCIDevice *pci_dev = PCI_DEVICE(s); + uint32_t unplug_val = 0; switch (addr) { case 0: /* Platform flags */ @@ -372,17 +403,16 @@ static void xen_platform_ioport_writeb(v * If VMDP was to control both disk and LAN it would use 4. * If it controlled just disk or just LAN, it would use 8 below. */ - pci_unplug_disks(pci_dev->bus, UNPLUG_IDE_SCSI_DISKS); - pci_unplug_nics(pci_dev->bus); + unplug_val |= UNPLUG_IDE_SCSI_DISKS | UNPLUG_ALL_NICS; } break; case 8: switch (val) { case 1: - pci_unplug_disks(pci_dev->bus, UNPLUG_IDE_SCSI_DISKS); + unplug_val |= UNPLUG_IDE_SCSI_DISKS; break; case 2: - pci_unplug_nics(pci_dev->bus); + unplug_val |= UNPLUG_ALL_NICS; break; default: log_writeb(s, (uint32_t)val); @@ -392,6 +422,10 @@ static void xen_platform_ioport_writeb(v default: break; } + if (unplug_val) { + s->unplug_val |= unplug_val; + platform_do_unplug(s, unplug_val); + } } static const MemoryRegionOps xen_pci_io_ops = { @@ -440,19 +474,23 @@ static int xen_platform_post_load(void * { PCIXenPlatformState *s = opaque; + error_report("%s %x", __func__, version_id); platform_fixed_ioport_writeb(s, 0, s->flags); + if (0) + platform_do_unplug(s, s->unplug_val); return 0; } static const VMStateDescription vmstate_xen_platform = { .name = "platform", - .version_id = 4, + .version_id = 5, .minimum_version_id = 4, .post_load = xen_platform_post_load, .fields = (VMStateField[]) { VMSTATE_PCI_DEVICE(parent_obj, PCIXenPlatformState), VMSTATE_UINT8(flags, PCIXenPlatformState), + VMSTATE_UINT32(unplug_val, PCIXenPlatformState), VMSTATE_END_OF_LIST() } }; @@ -468,6 +506,8 @@ static void xen_platform_realize(PCIDevi return; } + error_report("%s", __func__); + pci_conf = dev->config; pci_set_word(pci_conf + PCI_COMMAND, PCI_COMMAND_IO | PCI_COMMAND_MEMORY); --- a/include/migration/vmstate.h +++ b/include/migration/vmstate.h @@ -29,6 +29,7 @@ #include "migration/qjson.h" +extern void xen_unplug_after_migration(void); typedef struct VMStateInfo VMStateInfo; typedef struct VMStateDescription VMStateDescription; typedef struct VMStateField VMStateField; --- a/migration/savevm.c +++ b/migration/savevm.c @@ -2265,6 +2265,7 @@ void qmp_xen_save_devices_state(const ch int saved_vm_running; int ret; + error_report("%s %s %x %x", __func__, filename, has_live, live); if (!has_live) { /* live default to true so old version of Xen tool stack can have a * successfull live migration */ @@ -2284,6 +2285,7 @@ void qmp_xen_save_devices_state(const ch object_unref(OBJECT(ioc)); ret = qemu_save_device_state(f); qemu_fclose(f); + error_report("%s %x", __func__, ret); if (ret < 0) { error_setg(errp, QERR_IO_ERROR); } else { @@ -2293,6 +2295,7 @@ void qmp_xen_save_devices_state(const ch * So call bdrv_inactivate_all (release locks) here to let the other * side of the migration take controle of the images. */ + error_report("%s %x saved_vm_running %x", __func__, live, saved_vm_running); if (live && !saved_vm_running) { ret = bdrv_inactivate_all(); if (ret) { --- a/hw/i386/xen/xen-hvm.c +++ b/hw/i386/xen/xen-hvm.c @@ -1240,6 +1240,7 @@ void xen_hvm_init(PCMachineState *pcms, evtchn_port_t bufioreq_evtchn; XenIOState *state; + error_report("%s", __func__); state = g_malloc0(sizeof (XenIOState)); state->xce_handle = xenevtchn_open(NULL, 0); --- a/hw/xen/xen_backend.c +++ b/hw/xen/xen_backend.c @@ -588,6 +588,7 @@ int xen_be_register(const char *type, st void xen_be_register_common(void) { + error_report("%s", __func__); xen_set_dynamic_sysbus(); xen_be_register("console", &xen_console_ops); --- a/hw/xenpv/xen_machine_pv.c +++ b/hw/xenpv/xen_machine_pv.c @@ -34,6 +34,7 @@ static void xen_init_pv(MachineState *ma DriveInfo *dinfo; int i; + error_report("%s", __func__); /* Initialize backend core & drivers */ if (xen_be_init() != 0) { fprintf(stderr, "%s: xen backend core setup failed\n", __FUNCTION__); --- a/util/osdep.c +++ b/util/osdep.c @@ -338,6 +338,7 @@ int qemu_open(const char *name, int flag qemu_set_cloexec(ret); } #endif + error_report("%s %d = %s", __func__, ret, name); #ifdef O_DIRECT if (ret == -1 && errno == EINVAL && (flags & O_DIRECT)) { @@ -353,6 +354,7 @@ int qemu_close(int fd) { int64_t fdset_id; + error_report("%s %d", __func__, fd); /* Close fd that was dup'd from an fdset */ fdset_id = monitor_fdset_dup_fd_find(fd); if (fdset_id != -1) { --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -87,6 +87,7 @@ static void pc_init1(MachineState *machi MemoryRegion *rom_memory; ram_addr_t lowmem; + error_report("%s e", __func__); /* * Calculate ram split, for memory below and above 4G. It's a bit * complicated for backward compatibility reasons ... @@ -302,6 +303,7 @@ static void pc_init1(MachineState *machi nvdimm_init_acpi_state(&pcms->acpi_nvdimm_state, system_io, pcms->fw_cfg, OBJECT(pcms)); } + error_report("%s l", __func__); } /* Looking for a pc_compat_2_4() function? It doesn't exist. Attachment:
pgp7OA4b3thFQ.pgp _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |