Role(master or peer) controls how the domain behaves on migration. For more details about migration with ivshmem, see https://git.qemu.org/?p=qemu.git;a=blob_plain;f=docs/system/ivshmem.rst;hb=HEAD It's a optional attribute in libvirt, and qemu will choose default role for ivshmem device if the user is not specified. With device property 'role', the value can be 'master' or 'peer'. - 'master' (means 'master=on' in qemu), the guest will copy the shared memory on migration to the destination host. - 'peer' (means 'master=off' in qemu), the migration is disabled. Signed-off-by: Martin Kletzander <mkletzan@xxxxxxxxxx> Signed-off-by: Yang Hang <yanghang44@xxxxxxxxxx> Signed-off-by: Wang Xin <wangxinxin.wang@xxxxxxxxxx> diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index f3a639b972..1a7308cb00 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -9141,7 +9141,7 @@ qemu-kvm -net nic,model=? /dev/null <pre> ... <devices> - <shmem name='my_shmem0'> + <shmem name='my_shmem0' role='peer'> <model type='ivshmem-plain'/> <size unit='M'>4</size> </shmem> @@ -9162,6 +9162,17 @@ qemu-kvm -net nic,model=? /dev/null <code>name</code> to identify the shared memory. This attribute cannot be directory specific to <code>.</code> or <code>..</code> as well as it cannot involve path separator <code>/</code>. + The optional <code>role</code> (<span class="since">since 6.6.0</span>) + 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 + <code>model</code> type <code>ivshmem-plain</code> and + <code>ivshmem-doorbell</code>. </dd> <dt><code>model</code></dt> <dd> diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index a810f569c6..09d4ad3e96 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -4417,6 +4417,14 @@ <param name="pattern">[^/]*</param> </data> </attribute> + <optional> + <attribute name="role"> + <choice> + <value>master</value> + <value>peer</value> + </choice> + </attribute> + </optional> <interleave> <optional> <element name="model"> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 8d328819af..bede53d5aa 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, "", @@ -15354,6 +15361,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; @@ -18573,6 +18593,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; @@ -23752,6 +23775,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 " @@ -27402,8 +27434,12 @@ virDomainShmemDefFormat(virBufferPtr buf, virDomainShmemDefPtr def, unsigned int flags) { - virBufferEscapeString(buf, "<shmem name='%s'>\n", def->name); + virBufferEscapeString(buf, "<shmem name='%s'", def->name); + if (def->role) + virBufferEscapeString(buf, " role='%s'", + virDomainShmemRoleTypeToString(def->role)); + virBufferAddLit(buf, ">\n"); virBufferAdjustIndent(buf, 2); virBufferAsprintf(buf, "<model type='%s'/>\n", diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 241149af24..855c144ddb 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1771,10 +1771,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; @@ -3624,6 +3633,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 73b72c9e10..3f28943575 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..e588b74c2f 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_PEER) { + virReportError(VIR_ERR_OPERATION_INVALID, + _("shmem device '%s' with role='%s', " + "cannot be migrated"), + shmem->name, + virDomainShmemRoleTypeToString(shmem->role)); + 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 @@ -<shmem name='shmem0'> +<shmem name='shmem0' role='peer'> <model type='ivshmem-plain'/> <size unit='M'>4</size> <alias name='shmem0'/> 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 @@ -<shmem name='shmem0'> +<shmem name='shmem0' role='peer'> <model type='ivshmem-plain'/> </shmem> 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 @@ <alias name='input1'/> </input> <memballoon model='none'/> - <shmem name='shmem0'> + <shmem name='shmem0' role='peer'> <model type='ivshmem-plain'/> <size unit='M'>4</size> <alias name='shmem0'/> 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 @@ <alias name='input1'/> </input> <memballoon model='none'/> - <shmem name='shmem0'> + <shmem name='shmem0' role='peer'> <model type='ivshmem-plain'/> <size unit='M'>4</size> <alias name='shmem0'/> 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 @@ <shmem name='shmem0'> <model type='ivshmem-plain'/> </shmem> - <shmem name='shmem1'> + <shmem name='shmem1' role='peer'> <model type='ivshmem-plain'/> <size unit='M'>128</size> </shmem> - <shmem name='shmem2'> + <shmem name='shmem2' role='master'> <model type='ivshmem-plain'/> <size unit='M'>256</size> <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> 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 @@ <size unit='M'>4</size> <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> </shmem> - <shmem name='shmem1'> + <shmem name='shmem1' role='peer'> <model type='ivshmem-plain'/> <size unit='M'>128</size> <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/> </shmem> - <shmem name='shmem2'> + <shmem name='shmem2' role='master'> <model type='ivshmem-plain'/> <size unit='M'>256</size> <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index c17e3303b0..6cb2718767 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); -- 2.23.0