[libvirt] [PATCH v2 0/3] Propagate storage errors on migration
by Michal Privoznik
This is practically v2 to:
https://www.redhat.com/archives/libvir-list/2015-January/msg00230.html
The approach is merely the same - listening to BLOCK_JOB_* events
instead of asking on the monitor repeatedly. But the code looks
more polished.
Michal Privoznik (3):
qemuProcessHandleBlockJob: Set disk->mirrorState more often
qemuProcessHandleBlockJob: Take status into account
qemuMigrationDriveMirror: Listen to events
src/qemu/qemu_migration.c | 37 +++++++++++++++++--------------------
src/qemu/qemu_process.c | 36 +++++++++++++++++++++---------------
2 files changed, 38 insertions(+), 35 deletions(-)
--
2.0.5
9 years, 9 months
[libvirt] vm live storage migration with snapshots
by Edward Young
Hi all,
I'm investigating the ways to improve the live migration performance in
libvirt. I have a question about the vm live storage migration. the
platform is libvirt + qemu + kvm
If we want to migrate a running vm with its virtual disk images to another
node.
we can use 'virsh migrate ....' commands.
What if this vm has a number of disk-only external snapshots? In the
current version, how can live migrate this vm?
Is it possible to blockcommit the snapshots to the base image and later
perform the migration, without shutting down the running vm?
Or is it possible to iteratively transfer all the snapshots to the
destination and later live migrate only the latest new data?
Thanks in advance.
Best,
Ed
9 years, 9 months
[libvirt] [PATCH] qemu: fix setting of VM CPU affinity with TCG
by Daniel P. Berrange
If a previous commit I fixed the incorrect handling of vcpu pids
for TCG mode QEMU:
commit b07f3d821dfb11a118ee75ea275fd6ab737d9500
Author: Daniel P. Berrange <berrange(a)redhat.com>
Date: Thu Dec 18 16:34:39 2014 +0000
Don't setup fake CPU pids for old QEMU
The code assumes that def->vcpus == nvcpupids, so when we setup
fake CPU pids for old QEMU with nvcpupids == 1, we cause the
later code to read off the end of the array. This has fun results
like sche_setaffinity(0, ...) which changes libvirtd's own CPU
affinity, or even better sched_setaffinity($RANDOM, ...) which
changes the affinity of a random OS process.
The intent was that this would merely disable the ability to set
per-vCPU affinity. It should still have been possible to set VM
level host CPU affinity.
Unfortunately, when you set <vcpu cpuset='0-1'>4</vcpu>, the XML
parser will internally take this & initialize an entry in the
def->cputune.vcpupin array for every VCPU. IOW this is implicitly
being treated as
<cputune>
<vcpupin cpuset='0-1' vcpu='0'/>
<vcpupin cpuset='0-1' vcpu='1'/>
<vcpupin cpuset='0-1' vcpu='2'/>
<vcpupin cpuset='0-1' vcpu='3'/>
</cputune>
Even more fun, the faked cputune elements are hidden from view when
querying the live XML, because their cpuset mask is the same as the
VM default cpumask.
The upshot was that it was impossible to set VM level CPU affinity.
To fix this we must update qemuProcessSetVcpuAffinities so that it
only reports a fatal error if the per-VCPU cpu mask is different
from the VM level cpu mask.
Signed-off-by: Daniel P. Berrange <berrange(a)redhat.com>
---
src/qemu/qemu_process.c | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index d5df60d..e8c532f 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -2497,9 +2497,18 @@ qemuProcessSetVcpuAffinities(virDomainObjPtr vm)
return 0;
if (priv->vcpupids == NULL) {
- virReportError(VIR_ERR_OPERATION_INVALID,
- "%s", _("cpu affinity is not supported"));
- return -1;
+ /* If any CPU has custom affinity that differs from the
+ * VM default affinity, we must reject it
+ */
+ for (n = 0; n < def->vcpus; n++) {
+ if (!virBitmapEqual(def->cpumask,
+ def->cputune.vcpupin[n]->cpumask)) {
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ "%s", _("cpu affinity is not supported"));
+ return -1;
+ }
+ }
+ return 0;
}
for (n = 0; n < def->vcpus; n++) {
--
2.1.0
9 years, 9 months
[libvirt] [PATCH] bhyvexml2argvmock: change int to size_t for tapfdSize
by Pavel Hrdina
Commit c5b6a4a5 forget to update also this mock function.
Signed-off-by: Pavel Hrdina <phrdina(a)redhat.com>
---
Pushed as build breaker fix (FreeBSD).
tests/bhyvexml2argvmock.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/bhyvexml2argvmock.c b/tests/bhyvexml2argvmock.c
index 0cbea29..41058ca 100644
--- a/tests/bhyvexml2argvmock.c
+++ b/tests/bhyvexml2argvmock.c
@@ -24,7 +24,7 @@ int virNetDevTapCreateInBridgePort(const char *brname ATTRIBUTE_UNUSED,
const unsigned char *vmuuid ATTRIBUTE_UNUSED,
const char *tunpath ATTRIBUTE_UNUSED,
int *tapfd ATTRIBUTE_UNUSED,
- int tapfdSize ATTRIBUTE_UNUSED,
+ size_t tapfdSize ATTRIBUTE_UNUSED,
virNetDevVPortProfilePtr virtPortProfile ATTRIBUTE_UNUSED,
virNetDevVlanPtr virtVlan ATTRIBUTE_UNUSED,
unsigned int fakeflags ATTRIBUTE_UNUSED)
--
2.0.5
9 years, 9 months
[libvirt] [PATCH] domain: include portgroup in interface status xml
by Laine Stump
Prior to commit 7d5bf484747 (first appearing in libvirt 1.2.2), the
status XML of a domain's interface was missing a lot of important
information; mainly it just output the config of the interface, plus
the name of the tap device and qemu device alias. Commit 7d5bf484747
changed the status XML to include many important bits of information
that were required to make network "hook" scripts useful - bandwidth
information, vlan tag, the name of the bridge (or physical device in
the case of macvtap) that the tap/macvtap device was attached to - the
commit log for 7d5bf484747 has a very detailed explanation of the
change. For quick reference - in the example given there, prior to the
change, status XML looked like figure [C]:
<interface type='network'>
<source network='testnet' portgroup='admin'/>
<target dev='macvtap0'/>
<alias name='net0'/>
<address type='pci' domain='0x0000' bus='0x00'
slot='0x03' function='0x0'/>
</interface>
and after the change, it looked like figure [E]:
<interface type='direct'>
<source dev='p4p1_0' mode='bridge'/>
<bandwidth>
<inbound average='1000' peak='5000' burst='1024'/>
<outbound average='128' peak='256' burst='256'/>
</bandwidth>
<target dev='macvtap0'/>
<alias name='net0'/>
<address type='pci' domain='0x0000' bus='0x00'
slot='0x03' function='0x0'/>
</interface>
You'll notice that bandwidth info, physdev, and macvtap mode have been
added, but the network and portgroup names are now missing - I didn't
think that this information was of any use once the needed
bandwidth/vlan/etc config had been pulled from the network/portgroup.
I was wrong.
A few months after that change a user on IRC asked what happened to
portgroup in the status XML and described how he used it (more or less
as a tag to decide what external information to use in a hook script
that was run at startup/migration time - see
http://wiki.libvirt.org/page/OVS_and_PVLANS ). At that time I planned
to make a patch to re-add portgroup, but life intervened as that was
just prior to a transatlantic move involving several weeks of
"vacation". During this time I somehow forgot to make the patch, and
also mistakenly remembered that I *had* made it.
Subsequent to this, as a part of mprivozn's work to add support for
network-specific hooks, I did re-add the output of the network name in
status XML, but once again completely forgot about portgroup. This was
in commit a3609121 (first appearing in libvirt 1.2.11). This made the
status XML from the above example look like this:
<interface type='direct'>
<source network='testnet' dev='p4p1_0' mode='bridge'/>
<bandwidth>
<inbound average='1000' peak='5000' burst='1024'/>
<outbound average='128' peak='256' burst='256'/>
</bandwidth>
<target dev='macvtap0'/>
<alias name='net0'/>
<address type='pci' domain='0x0000' bus='0x00'
slot='0x03' function='0x0'/>
</interface>
*This* patch just adds the portgroup back to the status XML, so the
same example interface will look like this:
<interface type='direct'>
<source network='testnet' portgroup='admin'
dev='p4p1_0' mode='bridge'/>
<bandwidth>
<inbound average='1000' peak='5000' burst='1024'/>
<outbound average='128' peak='256' burst='256'/>
</bandwidth>
<target dev='macvtap0'/>
<alias name='net0'/>
<address type='pci' domain='0x0000' bus='0x00'
slot='0x03' function='0x0'/>
</interface>
The result is that the status XML now contains all information about
how the interface is setup (bandwidth, physical device, tap device,
etc), in addition to pointers to its origin (the network and
portgroup).
---
I had previously asked about this topic here:
https://www.redhat.com/archives/libvir-list/2014-June/msg00416.html
but then forgot to follow up on it...
src/conf/domain_conf.c | 18 +++++++++++-------
1 file changed, 11 insertions(+), 7 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 8600eff..d870bb6 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -17591,14 +17591,18 @@ virDomainActualNetDefContentsFormat(virBufferPtr buf,
if (def->type == VIR_DOMAIN_NET_TYPE_NETWORK && !inSubelement) {
/* When we're putting our output into the <actual>
* subelement rather than the main <interface>, the
- * network name isn't included in the <source> because the
- * main interface element's <source> has the same info
- * already. If we've been called to output directly into
- * the main element's <source> though (the case here -
- * "!inSubElement"), we *do* need to output the network
- * name, because the caller won't have done it).
+ * network name and portgroup don't need to be included in
+ * the <source> here because the main interface element's
+ * <source> has the same info already. If we've been
+ * called to output directly into the main element's
+ * <source> though (the case here - "!inSubElement"), we
+ * *do* need to output network/portgroup, because the
+ * caller won't have done it).
*/
- virBufferEscapeString(buf, " network='%s'", def->data.network.name);
+ virBufferEscapeString(buf, " network='%s'",
+ def->data.network.name);
+ virBufferEscapeString(buf, " portgroup='%s'",
+ def->data.network.portgroup);
}
if (actualType == VIR_DOMAIN_NET_TYPE_BRIDGE ||
actualType == VIR_DOMAIN_NET_TYPE_NETWORK) {
--
2.1.0
9 years, 9 months
[libvirt] [PATCHv2] qemu: fix crash in migrate when migrateuri do not have a scheme
by Luyao Huang
https://bugzilla.redhat.com/show_bug.cgi?id=1191355
When we migrate a vm with migrateuri option with a uri do not
have scheme like this:
# virsh migrate test4 --live qemu+ssh://lhuang/system --migrateuri 127.0.0.1
target libvirtd will crashed because uri->scheme is NULL in
qemuMigrationPrepareDirect this line:
if (STRNEQ(uri->scheme, "tcp") &&
add a value check before this line. Also fix a place like this in
doNativeMigrate.
Signed-off-by: Luyao Huang <lhuang(a)redhat.com>
---
src/qemu/qemu_migration.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 879b1bf..d4ffe6c 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -3281,6 +3281,13 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver,
if (!(uri = qemuMigrationParseURI(uri_in, &well_formed_uri)))
goto cleanup;
+ if (uri->scheme == NULL) {
+ virReportError(VIR_ERR_INVALID_ARG,
+ _("missing scheme in migration URI: %s"),
+ uri_in);
+ goto cleanup;
+ }
+
if (STRNEQ(uri->scheme, "tcp") &&
STRNEQ(uri->scheme, "rdma")) {
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED,
@@ -4083,6 +4090,13 @@ static int doNativeMigrate(virQEMUDriverPtr driver,
if (!(uribits = qemuMigrationParseURI(uri, NULL)))
return -1;
+ if (uribits->scheme == NULL) {
+ virReportError(VIR_ERR_INVALID_ARG,
+ _("missing scheme in migration URI: %s"),
+ uri);
+ goto cleanup;
+ }
+
if (STREQ(uribits->scheme, "rdma")) {
if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_MIGRATE_RDMA)) {
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
--
1.8.3.1
9 years, 9 months
[libvirt] [PATCH] conf: Fix libvirtd crash and memory leak caused by virDomainVcpuPinDel()
by Zhang Bo
The function virDomainVcpuPinDel() used vcpupin_list to stand for
def->cputune.vcpupin, which made the codes more readable.
However, in this function, it will realloc vcpupin_list later.
As the definition of realloc(), it may free vcpupin_list and then
points it to a new-realloced address, but def->cputune.vcpupin doesn't
point to the new address(it's freed however).
Thus,
1) When we refer to the def->cputune.vcpupin afterwards, which was freed
by realloc(), an INVALID READ occurs, and libvirtd may crash.
2) As no one will use vcpupin_list any more, and no one frees it(it's just
alloced by realloc()), memory leak occurs.
Part of the valgrind logs are shown as below:
==1837== Thread 15:
==1837== Invalid read of size 8
==1837== at 0x5367337: virDomainDefFormatInternal (domain_conf.c:18392)
which is : virBufferAsprintf(buf, "<vcpupin vcpu='%u' ",
def->cputune.vcpupin[i]->vcpuid);
==1837== by 0x536966C: virDomainObjFormat (domain_conf.c:18970)
==1837== by 0x5369743: virDomainSaveStatus (domain_conf.c:19166)
==1837== by 0x117B26DC: qemuDomainPinVcpuFlags (qemu_driver.c:4586)
==1837== by 0x53EA313: virDomainPinVcpuFlags (libvirt.c:9803)
==1837== by 0x14CB7D: remoteDispatchDomainPinVcpuFlags (remote_dispatch.h:6762)
==1837== by 0x14CC81: remoteDispatchDomainPinVcpuFlagsHelper (remote_dispatch.h:6740)
==1837== by 0x5464C30: virNetServerProgramDispatchCall (virnetserverprogram.c:437)
==1837== by 0x546507A: virNetServerProgramDispatch (virnetserverprogram.c:307)
==1837== by 0x171B83: virNetServerProcessMsg (virnetserver.c:172)
==1837== by 0x171E6E: virNetServerHandleJob (virnetserver.c:193)
==1837== by 0x5318E78: virThreadPoolWorker (virthreadpool.c:145)
==1837== Address 0x12ea2870 is 0 bytes inside a block of size 16 free'd
==1837== at 0x4C291AC: realloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==1837== by 0x52A3D14: virReallocN (viralloc.c:245)
==1837== by 0x52A3DFB: virShrinkN (viralloc.c:372)
==1837== by 0x52A3F57: virDeleteElementsN (viralloc.c:503)
==1837== by 0x533939E: virDomainVcpuPinDel (domain_conf.c:15405) //doReset为true时才会进到。
==1837== by 0x117B2642: qemuDomainPinVcpuFlags (qemu_driver.c:4573)
==1837== by 0x53EA313: virDomainPinVcpuFlags (libvirt.c:9803)
==1837== by 0x14CB7D: remoteDispatchDomainPinVcpuFlags (remote_dispatch.h:6762)
==1837== by 0x14CC81: remoteDispatchDomainPinVcpuFlagsHelper (remote_dispatch.h:6740)
==1837== by 0x5464C30: virNetServerProgramDispatchCall (virnetserverprogram.c:437)
==1837== by 0x546507A: virNetServerProgramDispatch (virnetserverprogram.c:307)
==1837== by 0x171B83: virNetServerProcessMsg (virnetserver.c:172)
Steps to reproduce the problem:
1) use virDomainPinVcpuFlags() to pin a guest's vcpu to all the pcpus
of the host.
This patch uses def->cputune.vcpupin instead of vcpupin_list to do the
realloc() job, to avoid invalid read or memory leaking.
Signed-off-by: Zhang Bo <oscar.zhangbo(a)huawei.com>
Signed-off-by: Yue Wenyuan <yuewenyuan@huawei.com(a)huawei.com>
---
src/conf/domain_conf.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index f0b715d..e1a3024 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -16276,7 +16276,7 @@ virDomainVcpuPinDel(virDomainDefPtr def, int vcpu)
if (vcpupin_list[n]->vcpuid == vcpu) {
virBitmapFree(vcpupin_list[n]->cpumask);
VIR_FREE(vcpupin_list[n]);
- VIR_DELETE_ELEMENT(vcpupin_list, n, def->cputune.nvcpupin);
+ VIR_DELETE_ELEMENT(def->cputune.vcpupin, n, def->cputune.nvcpupin);
return;
}
}
--
1.7.12.4
9 years, 9 months
[libvirt] [PATCH 0/2] Two fixes for graphics listen
by Laine Stump
These area a followup to Luyao Huang's patch to fix incorrect
reporting from virsh domdisplay:
https://www.redhat.com/archives/libvir-list/2015-February/msg00298.html
While his patch works when the remote libvirtd is 0.9.4 or greater, it
won't work when talking to older libvirt. Also the code as written
isn't what was intended. Patch 1 takes care of that. Patch 2 fixes two
theoretical memory leaks (which never happen in real life, but could
some day if the functions are used differently).
Laine Stump (2):
domain: backfill listen address to parent <graphics> listen attribute
domain: avoid potential memory leak in virDomainGraphicsListenSet*()
src/conf/domain_conf.c | 30 ++++++++++++++++++------------
1 file changed, 18 insertions(+), 12 deletions(-)
--
2.1.0
9 years, 9 months
[libvirt] [PATCH] qemu: do upfront check for vcpupids being null when querying pinning
by Daniel P. Berrange
The qemuDomainHelperGetVcpus attempted to report an error when the
vcpupids info was NULL. Unfortunately earlier code would clamp the
value of 'maxinfo' to 0 when nvcpupids was 0, so the error reporting
would end up being skipped.
This lead to 'virsh vcpuinfo <dom>' just returning an empty list
instead of giving the user a clear error.
---
src/qemu/qemu_driver.c | 47 +++++++++++++++++++++++------------------------
1 file changed, 23 insertions(+), 24 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index e3ca437..cd30d9a 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -1376,6 +1376,12 @@ qemuDomainHelperGetVcpus(virDomainObjPtr vm, virVcpuInfoPtr info, int maxinfo,
if ((hostcpus = nodeGetCPUCount()) < 0)
return -1;
+ if (priv->vcpupids == NULL) {
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ "%s", _("cpu affinity is not supported"));
+ return -1;
+ }
+
maxcpu = maplen * 8;
if (maxcpu > hostcpus)
maxcpu = hostcpus;
@@ -1391,8 +1397,7 @@ qemuDomainHelperGetVcpus(virDomainObjPtr vm, virVcpuInfoPtr info, int maxinfo,
info[i].number = i;
info[i].state = VIR_VCPU_RUNNING;
- if (priv->vcpupids != NULL &&
- qemuGetProcessInfo(&(info[i].cpuTime),
+ if (qemuGetProcessInfo(&(info[i].cpuTime),
&(info[i].cpu),
NULL,
vm->pid,
@@ -1406,28 +1411,22 @@ qemuDomainHelperGetVcpus(virDomainObjPtr vm, virVcpuInfoPtr info, int maxinfo,
if (cpumaps != NULL) {
memset(cpumaps, 0, maplen * maxinfo);
- if (priv->vcpupids != NULL) {
- for (v = 0; v < maxinfo; v++) {
- unsigned char *cpumap = VIR_GET_CPUMAP(cpumaps, maplen, v);
- virBitmapPtr map = NULL;
- unsigned char *tmpmap = NULL;
- int tmpmapLen = 0;
-
- if (virProcessGetAffinity(priv->vcpupids[v],
- &map, maxcpu) < 0)
- return -1;
- virBitmapToData(map, &tmpmap, &tmpmapLen);
- if (tmpmapLen > maplen)
- tmpmapLen = maplen;
- memcpy(cpumap, tmpmap, tmpmapLen);
-
- VIR_FREE(tmpmap);
- virBitmapFree(map);
- }
- } else {
- virReportError(VIR_ERR_OPERATION_INVALID,
- "%s", _("cpu affinity is not available"));
- return -1;
+ for (v = 0; v < maxinfo; v++) {
+ unsigned char *cpumap = VIR_GET_CPUMAP(cpumaps, maplen, v);
+ virBitmapPtr map = NULL;
+ unsigned char *tmpmap = NULL;
+ int tmpmapLen = 0;
+
+ if (virProcessGetAffinity(priv->vcpupids[v],
+ &map, maxcpu) < 0)
+ return -1;
+ virBitmapToData(map, &tmpmap, &tmpmapLen);
+ if (tmpmapLen > maplen)
+ tmpmapLen = maplen;
+ memcpy(cpumap, tmpmap, tmpmapLen);
+
+ VIR_FREE(tmpmap);
+ virBitmapFree(map);
}
}
}
--
2.1.0
9 years, 9 months