From e387011a32e0ad66bdcad810cf4751768e69a89a Mon Sep 17 00:00:00 2001 From: Anthony Liguori Date: Mon, 14 Nov 2011 15:09:44 -0600 Subject: [PATCH] ivshmem: use migration blockers to prevent live migration in peer mode (v2) Now when you try to migrate with ivshmem, you get a proper QMP error: (qemu) migrate tcp:localhost:1025 Migration is disabled when using feature 'peer mode' in device 'ivshmem' (qemu) Signed-off-by: Anthony Liguori --- hw/ivshmem.c | 12 +++++++++++- qerror.c | 4 ++++ qerror.h | 3 +++ savevm.c | 25 ------------------------- 4 files changed, 18 insertions(+), 26 deletions(-) diff --git a/hw/ivshmem.c b/hw/ivshmem.c index 242fbea..a3a0e98 100644 --- a/hw/ivshmem.c +++ b/hw/ivshmem.c @@ -18,6 +18,8 @@ #include "pci.h" #include "msix.h" #include "kvm.h" +#include "migration.h" +#include "qerror.h" #include #include @@ -78,6 +80,8 @@ typedef struct IVShmemState { uint32_t features; EventfdEntry *eventfd_table; + Error *migration_blocker; + char * shmobj; char * sizearg; char * role; @@ -646,7 +650,8 @@ static int pci_ivshmem_init(PCIDevice *dev) } if (s->role_val == IVSHMEM_PEER) { - register_device_unmigratable(&s->dev.qdev, "ivshmem", s); + error_set(&s->migration_blocker, QERR_DEVICE_FEATURE_BLOCKS_MIGRATION, "ivshmem", "peer mode"); + migrate_add_blocker(s->migration_blocker); } pci_conf = s->dev.config; @@ -741,6 +746,11 @@ static int pci_ivshmem_uninit(PCIDevice *dev) { IVShmemState *s = DO_UPCAST(IVShmemState, dev, dev); + if (s->migration_blocker) { + migrate_del_blocker(s->migration_blocker); + error_free(s->migration_blocker); + } + memory_region_destroy(&s->ivshmem_mmio); memory_region_del_subregion(&s->bar, &s->ivshmem); memory_region_destroy(&s->ivshmem); diff --git a/qerror.c b/qerror.c index 4b48b39..8e30e2d 100644 --- a/qerror.c +++ b/qerror.c @@ -73,6 +73,10 @@ static const QErrorStringTable qerror_table[] = { .desc = "Device '%(device)' is in use", }, { + .error_fmt = QERR_DEVICE_FEATURE_BLOCKS_MIGRATION, + .desc = "Migration is disabled when using feature '%(feature)' in device '%(device)'", + }, + { .error_fmt = QERR_DEVICE_LOCKED, .desc = "Device '%(device)' is locked", }, diff --git a/qerror.h b/qerror.h index d4bfcfd..7e2eebf 100644 --- a/qerror.h +++ b/qerror.h @@ -72,6 +72,9 @@ QError *qobject_to_qerror(const QObject *obj); #define QERR_DEVICE_IN_USE \ "{ 'class': 'DeviceInUse', 'data': { 'device': %s } }" +#define QERR_DEVICE_FEATURE_BLOCKS_MIGRATION \ + "{ 'class': 'DeviceFeatureBlocksMigration', 'data': { 'device': %s, 'feature': %s } }" + #define QERR_DEVICE_LOCKED \ "{ 'class': 'DeviceLocked', 'data': { 'device': %s } }" diff --git a/savevm.c b/savevm.c index bee16c0..f53cd4c 100644 --- a/savevm.c +++ b/savevm.c @@ -1255,31 +1255,6 @@ void unregister_savevm(DeviceState *dev, const char *idstr, void *opaque) } } -/* mark a device as not to be migrated, that is the device should be - unplugged before migration */ -void register_device_unmigratable(DeviceState *dev, const char *idstr, - void *opaque) -{ - SaveStateEntry *se; - char id[256] = ""; - - if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) { - char *path = dev->parent_bus->info->get_dev_path(dev); - if (path) { - pstrcpy(id, sizeof(id), path); - pstrcat(id, sizeof(id), "/"); - g_free(path); - } - } - pstrcat(id, sizeof(id), idstr); - - QTAILQ_FOREACH(se, &savevm_handlers, entry) { - if (strcmp(se->idstr, id) == 0 && se->opaque == opaque) { - se->no_migrate = 1; - } - } -} - int vmstate_register_with_alias_id(DeviceState *dev, int instance_id, const VMStateDescription *vmsd, void *opaque, int alias_id, -- 2.7.4