diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 6b67a09bb3..3fc41801a4 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -9142,7 +9142,7 @@ qemu-kvm -net nic,model=? /dev/null
 ...
 <devices>
-  <shmem name='my_shmem0'>
+  <shmem name='my_shmem0' role='peer'>
     <model type='ivshmem-plain'/>
     <size unit='M'>4</size>
   </shmem>
@@ -9163,6 +9163,17 @@ qemu-kvm -net nic,model=? /dev/null
       name to identify the shared memory. This attribute cannot
       be directory specific to . or .. as well as
       it cannot involve path separator /.
+      The optional role (since 6.6.0)
+      attribute specifies the shared memory is migratable or not. The value can
+      be either "master" or "peer", the former will mean that upon migration,
+      the data in the shared memory is migrated with the domain. There should
+      be only one "master" per shared memory object. Migration with "peer" role
+      is disabled. If migration of such domain is required, the shmem device
+      needs to be unplugged before migration and plugged in at the destination
+      upon successful migration. If the role not specified, the hypervisor
+      default is used. This attribute is currently available only for
+      model type ivshmem-plain and
+      ivshmem-doorbell.
     
     
model
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 8cbbd7e6e9..c196a97511 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -4422,6 +4422,14 @@ [^/]* + + + + master + peer + + + diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 1179a27a00..4a47dc8d0a 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -1325,6 +1325,13 @@ VIR_ENUM_IMPL(virDomainShmemModel, "ivshmem-doorbell", ); +VIR_ENUM_IMPL(virDomainShmemRole, + VIR_DOMAIN_SHMEM_ROLE_LAST, + "default", + "master", + "peer", +); + VIR_ENUM_IMPL(virDomainLaunchSecurity, VIR_DOMAIN_LAUNCH_SECURITY_LAST, "", @@ -15366,6 +15373,19 @@ virDomainShmemDefParseXML(virDomainXMLOptionPtr xmlopt, goto cleanup; } + if (def->model != VIR_DOMAIN_SHMEM_MODEL_IVSHMEM) { + tmp = virXMLPropString(node, "role"); + if (tmp) { + if ((def->role = virDomainShmemRoleTypeFromString(tmp)) <= 0) { + virReportError(VIR_ERR_XML_ERROR, + _("Unknown shmem role type '%s'"), tmp); + goto cleanup; + } + + VIR_FREE(tmp); + } + } + if (virParseScaledValue("./size[1]", NULL, ctxt, &def->size, 1, ULLONG_MAX, false) < 0) goto cleanup; @@ -18585,6 +18605,9 @@ virDomainShmemDefEquals(virDomainShmemDefPtr src, if (src->model != dst->model) return false; + if (src->role != dst->role) + return false; + if (src->server.enabled != dst->server.enabled) return false; @@ -23771,6 +23794,15 @@ virDomainShmemDefCheckABIStability(virDomainShmemDefPtr src, return false; } + if (src->role != dst->role) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Target shared memory role '%s' does not match " + "source role '%s'"), + virDomainShmemRoleTypeToString(dst->role), + virDomainShmemRoleTypeToString(src->role)); + return false; + } + if (src->model != dst->model) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Target shared memory model '%s' does not match " @@ -27423,8 +27455,12 @@ virDomainShmemDefFormat(virBufferPtr buf, virDomainShmemDefPtr def, unsigned int flags) { - virBufferEscapeString(buf, "\n", def->name); + virBufferEscapeString(buf, "name); + if (def->role) + virBufferEscapeString(buf, " role='%s'", + virDomainShmemRoleTypeToString(def->role)); + virBufferAddLit(buf, ">\n"); virBufferAdjustIndent(buf, 2); virBufferAsprintf(buf, "\n", diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 6e9da298b4..011bf66cb4 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1772,10 +1772,19 @@ typedef enum { VIR_DOMAIN_SHMEM_MODEL_LAST } virDomainShmemModel; +typedef enum { + VIR_DOMAIN_SHMEM_ROLE_DEFAULT, + VIR_DOMAIN_SHMEM_ROLE_MASTER, + VIR_DOMAIN_SHMEM_ROLE_PEER, + + VIR_DOMAIN_SHMEM_ROLE_LAST +} virDomainShmemRole; + struct _virDomainShmemDef { char *name; unsigned long long size; int model; /* enum virDomainShmemModel */ + int role; /* enum virDomainShmemRole */ struct { bool enabled; virDomainChrSourceDef chr; @@ -3625,6 +3634,7 @@ VIR_ENUM_DECL(virDomainMemoryAllocation); VIR_ENUM_DECL(virDomainIOMMUModel); VIR_ENUM_DECL(virDomainVsockModel); VIR_ENUM_DECL(virDomainShmemModel); +VIR_ENUM_DECL(virDomainShmemRole); VIR_ENUM_DECL(virDomainLaunchSecurity); /* from libvirt.h */ VIR_ENUM_DECL(virDomainState); diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index eea31a736d..bdc1563300 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -597,6 +597,8 @@ virDomainShmemDefInsert; virDomainShmemDefRemove; virDomainShmemModelTypeFromString; virDomainShmemModelTypeToString; +virDomainShmemRoleTypeFromString; +virDomainShmemRoleTypeToString; virDomainShutdownReasonTypeFromString; virDomainShutdownReasonTypeToString; virDomainShutoffReasonTypeFromString; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 839c93bfb4..0655d8359d 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -8539,11 +8539,24 @@ qemuBuildShmemDevStr(virDomainDefPtr def, virBufferAdd(&buf, virDomainShmemModelTypeToString(shmem->model), -1); virBufferAsprintf(&buf, ",id=%s", shmem->info.alias); - if (shmem->server.enabled) + if (shmem->server.enabled) { virBufferAsprintf(&buf, ",chardev=char%s", shmem->info.alias); - else + } else { virBufferAsprintf(&buf, ",memdev=shmmem-%s", shmem->info.alias); + switch ((virDomainShmemRole) shmem->role) { + case VIR_DOMAIN_SHMEM_ROLE_MASTER: + virBufferAddLit(&buf, ",master=on"); + break; + case VIR_DOMAIN_SHMEM_ROLE_PEER: + virBufferAddLit(&buf, ",master=off"); + break; + case VIR_DOMAIN_SHMEM_ROLE_DEFAULT: + case VIR_DOMAIN_SHMEM_ROLE_LAST: + break; + } + } + if (shmem->msi.vectors) virBufferAsprintf(&buf, ",vectors=%u", shmem->msi.vectors); if (shmem->msi.ioeventfd) { diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 2c7bf349c3..0f2f92b211 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -1261,10 +1261,22 @@ qemuMigrationSrcIsAllowed(virQEMUDriverPtr driver, } } - if (vm->def->nshmems) { - virReportError(VIR_ERR_OPERATION_INVALID, "%s", - _("migration with shmem device is not supported")); - return false; + for (i = 0; i < vm->def->nshmems; i++) { + virDomainShmemDefPtr shmem = vm->def->shmems[i]; + + if (shmem->model == VIR_DOMAIN_SHMEM_MODEL_IVSHMEM) { + virReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("migration with legacy shmem device is not supported")); + return false; + } + if (shmem->role != VIR_DOMAIN_SHMEM_ROLE_MASTER) { + virReportError(VIR_ERR_OPERATION_INVALID, + _("shmem device '%s' cannot be migrated, " + "only shmem with role='%s' can be migrated"), + shmem->name, + virDomainShmemRoleTypeToString(VIR_DOMAIN_SHMEM_ROLE_MASTER)); + return false; + } } for (i = 0; i < vm->def->nnets; i++) { diff --git a/tests/qemuhotplugtestdevices/qemuhotplug-ivshmem-plain-detach.xml b/tests/qemuhotplugtestdevices/qemuhotplug-ivshmem-plain-detach.xml index 68f592fb21..338017aa28 100644 --- a/tests/qemuhotplugtestdevices/qemuhotplug-ivshmem-plain-detach.xml +++ b/tests/qemuhotplugtestdevices/qemuhotplug-ivshmem-plain-detach.xml @@ -1,4 +1,4 @@ - + 4 diff --git a/tests/qemuhotplugtestdevices/qemuhotplug-ivshmem-plain.xml b/tests/qemuhotplugtestdevices/qemuhotplug-ivshmem-plain.xml index 6bd96ff167..780e49de23 100644 --- a/tests/qemuhotplugtestdevices/qemuhotplug-ivshmem-plain.xml +++ b/tests/qemuhotplugtestdevices/qemuhotplug-ivshmem-plain.xml @@ -1,3 +1,3 @@ - + diff --git a/tests/qemuhotplugtestdomains/qemuhotplug-base-live+ivshmem-doorbell.xml b/tests/qemuhotplugtestdomains/qemuhotplug-base-live+ivshmem-doorbell.xml index a6930bfa69..8013264989 100644 --- a/tests/qemuhotplugtestdomains/qemuhotplug-base-live+ivshmem-doorbell.xml +++ b/tests/qemuhotplugtestdomains/qemuhotplug-base-live+ivshmem-doorbell.xml @@ -45,7 +45,7 @@ - + 4 diff --git a/tests/qemuhotplugtestdomains/qemuhotplug-base-live+ivshmem-plain.xml b/tests/qemuhotplugtestdomains/qemuhotplug-base-live+ivshmem-plain.xml index 757b6b0980..0490310760 100644 --- a/tests/qemuhotplugtestdomains/qemuhotplug-base-live+ivshmem-plain.xml +++ b/tests/qemuhotplugtestdomains/qemuhotplug-base-live+ivshmem-plain.xml @@ -45,7 +45,7 @@ - + 4 diff --git a/tests/qemuxml2argvdata/shmem-plain-doorbell.args b/tests/qemuxml2argvdata/shmem-plain-doorbell.args index 6ed86b7448..93d089c27a 100644 --- a/tests/qemuxml2argvdata/shmem-plain-doorbell.args +++ b/tests/qemuxml2argvdata/shmem-plain-doorbell.args @@ -30,10 +30,12 @@ size=4194304,share=yes \ -device ivshmem-plain,id=shmem0,memdev=shmmem-shmem0,bus=pci.0,addr=0x3 \ -object memory-backend-file,id=shmmem-shmem1,mem-path=/dev/shm/shmem1,\ size=134217728,share=yes \ --device ivshmem-plain,id=shmem1,memdev=shmmem-shmem1,bus=pci.0,addr=0x5 \ +-device ivshmem-plain,id=shmem1,memdev=shmmem-shmem1,master=off,bus=pci.0,\ +addr=0x5 \ -object memory-backend-file,id=shmmem-shmem2,mem-path=/dev/shm/shmem2,\ size=268435456,share=yes \ --device ivshmem-plain,id=shmem2,memdev=shmmem-shmem2,bus=pci.0,addr=0x4 \ +-device ivshmem-plain,id=shmem2,memdev=shmmem-shmem2,master=on,bus=pci.0,\ +addr=0x4 \ -device ivshmem-doorbell,id=shmem3,chardev=charshmem3,ioeventfd=on,bus=pci.0,\ addr=0x6 \ -chardev socket,id=charshmem3,path=/var/lib/libvirt/shmem-shmem3-sock \ diff --git a/tests/qemuxml2argvdata/shmem-plain-doorbell.xml b/tests/qemuxml2argvdata/shmem-plain-doorbell.xml index e248d637a5..7c76e0fbba 100644 --- a/tests/qemuxml2argvdata/shmem-plain-doorbell.xml +++ b/tests/qemuxml2argvdata/shmem-plain-doorbell.xml @@ -22,11 +22,11 @@ - + 128 - + 256
diff --git a/tests/qemuxml2xmloutdata/shmem-plain-doorbell.xml b/tests/qemuxml2xmloutdata/shmem-plain-doorbell.xml index c5dd0f4598..64c0a7d753 100644 --- a/tests/qemuxml2xmloutdata/shmem-plain-doorbell.xml +++ b/tests/qemuxml2xmloutdata/shmem-plain-doorbell.xml @@ -26,12 +26,12 @@ 4
- + 128
- + 256
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 74b6959408..a07e2b7553 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -1135,7 +1135,8 @@ mymain(void) DO_TEST("tap-vhost", NONE); DO_TEST("tap-vhost-incorrect", NONE); DO_TEST("shmem", NONE); - DO_TEST("shmem-plain-doorbell", NONE); + DO_TEST("shmem-plain-doorbell", + QEMU_CAPS_DEVICE_IVSHMEM_PLAIN, QEMU_CAPS_DEVICE_IVSHMEM_DOORBELL); DO_TEST("smbios", NONE); DO_TEST("smbios-multiple-type2", NONE); DO_TEST("smbios-type-fwcfg", NONE);