mirror of https://gitee.com/openkylin/libvirt.git
qemu: add support for shmem-{plain, doorbell} role
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@redhat.com> Signed-off-by: Yang Hang <yanghang44@huawei.com> Signed-off-by: Wang Xin <wangxinxin.wang@huawei.com> Reviewed-by: Martin Kletzander <mkletzan@redhat.com>
This commit is contained in:
parent
77296c807b
commit
493d2769f2
|
@ -9142,7 +9142,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>
|
||||
|
@ -9163,6 +9163,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>
|
||||
|
|
|
@ -4422,6 +4422,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">
|
||||
|
|
|
@ -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, "<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",
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -597,6 +597,8 @@ virDomainShmemDefInsert;
|
|||
virDomainShmemDefRemove;
|
||||
virDomainShmemModelTypeFromString;
|
||||
virDomainShmemModelTypeToString;
|
||||
virDomainShmemRoleTypeFromString;
|
||||
virDomainShmemRoleTypeToString;
|
||||
virDomainShutdownReasonTypeFromString;
|
||||
virDomainShutdownReasonTypeToString;
|
||||
virDomainShutoffReasonTypeFromString;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<shmem name='shmem0'>
|
||||
<shmem name='shmem0' role='peer'>
|
||||
<model type='ivshmem-plain'/>
|
||||
<size unit='M'>4</size>
|
||||
<alias name='shmem0'/>
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
<shmem name='shmem0'>
|
||||
<shmem name='shmem0' role='peer'>
|
||||
<model type='ivshmem-plain'/>
|
||||
</shmem>
|
||||
|
|
|
@ -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'/>
|
||||
|
|
|
@ -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'/>
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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'/>
|
||||
|
|
|
@ -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'/>
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue