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;h...
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(a)redhat.com>
Signed-off-by: Yang Hang <yanghang44(a)huawei.com>
Signed-off-by: Wang Xin <wangxinxin.wang(a)huawei.com>
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