[libvirt] [PATCH 0/5] qemu: Fix job handling in snapshot code
by Peter Krempa
The snapshot code had some issues with job handling. This is an attempt to do it right.
Jincheng Miao (1):
qemu: snapshot: Acquire job earlier on snapshot revert/delete
Peter Krempa (4):
qemu: Rename DEFAULT_JOB_MASK to QEMU_DEFAULT_JOB_MASK
qemu: snapshot: Fix job handling when creating snapshots
qemu: snapshot: Fix snapshot function header formatting
qemu: snapshot: Simplify error paths
src/qemu/qemu_domain.c | 2 +-
src/qemu/qemu_domain.h | 2 +-
src/qemu/qemu_driver.c | 317 +++++++++++++++++++++-------------------------
src/qemu/qemu_migration.c | 6 +-
4 files changed, 151 insertions(+), 176 deletions(-)
--
2.0.2
10 years, 3 months
Re: [libvirt] [Qemu-devel] IO accounting overhaul
by Markus Armbruster
Cc'ing libvirt following Stefan's lead.
Benoît Canet <benoit.canet(a)irqsave.net> writes:
> Hi,
>
> I collected some items of a cloud provider wishlist regarding I/O accouting.
Feedback from real power-users, lovely!
> In a cloud I/O accouting can have 3 purpose: billing, helping the customers
> and doing metrology to help the cloud provider seeks hidden costs.
>
> I'll cover the two former topic in this mail because they are the most important
> business wize.
>
> 1) prefered place to collect billing IO accounting data:
> --------------------------------------------------------
> For billing purpose the collected data must be as close as possible to what the
> customer would see by using iostats in his vm.
Good point.
> The first conclusion we can draw is that the choice of collecting IO accouting
> data used for billing in the block devices models is right.
Slightly rephrasing: doing I/O accounting in the block device models is
right for billing.
There may be other uses for I/O accounting, with different preferences.
For instance, data on how exactly guest I/O gets translated to host I/O
as it flows through the nodes in the block graph could be useful.
Doesn't diminish the need for accurate billing information, of course.
> 2) what to do with occurences of rare events:
> ---------------------------------------------
>
> Another point is that QEMU developpers agree that they don't know which policy
> to apply to some I/O accounting events.
> Must QEMU discard invalid I/O write IO or account them as done ?
> Must QEMU count a failed read I/O as done ?
>
> When discusting this with a cloud provider the following appears:
> these decisions
> are really specific to each cloud provider and QEMU should not implement them.
Good point, consistent with the old advice to avoid baking policy into
inappropriately low levels of the stack.
> The right thing to do is to add accouting counters to collect these events.
>
> Moreover these rare events are precious troubleshooting data so it's
> an additional
> reason not to toss them.
Another good point.
> 3) list of block I/O accouting metrics wished for billing and helping
> the customers
> -----------------------------------------------------------------------------------
>
> Basic I/O accouting data will end up making the customers bills.
> Extra I/O accouting informations would be a precious help for the cloud provider
> to implement a monitoring panel like Amazon Cloudwatch.
These are the first two from your list of three purposes, i.e. the ones
you promised to cover here.
> Here is the list of counters and statitics I would like to help
> implement in QEMU.
>
> This is the most important part of the mail and the one I would like
> the community
> review the most.
>
> Once this list is settled I would proceed to implement the required
> infrastructure
> in QEMU before using it in the device models.
For context, let me recap how I/O accounting works now.
The BlockDriverState abstract data type (short: BDS) can hold the
following accounting data:
uint64_t nr_bytes[BDRV_MAX_IOTYPE];
uint64_t nr_ops[BDRV_MAX_IOTYPE];
uint64_t total_time_ns[BDRV_MAX_IOTYPE];
uint64_t wr_highest_sector;
where BDRV_MAX_IOTYPE enumerates read, write, flush.
wr_highest_sector is a high watermark updated by the block layer as it
writes sectors.
The other three are *not* touched by the block layer. Instead, the
block layer provides a pair of functions for device models to update
them:
void bdrv_acct_start(BlockDriverState *bs, BlockAcctCookie *cookie,
int64_t bytes, enum BlockAcctType type);
void bdrv_acct_done(BlockDriverState *bs, BlockAcctCookie *cookie);
bdrv_acct_start() initializes cookie for a read, write, or flush
operation of a certain size. The size of a flush is always zero.
bdrv_acct_done() adds the operations to the BDS's accounting data.
total_time_ns is incremented by the time between _start() and _done().
You may call _start() without calling _done(). That's a feature.
Device models use it to avoid accounting some requests.
Device models are not supposed to mess with cookie directly, only
through these two functions.
Some device models implement accounting, some don't. The ones that do
don't agree on how to count invalid guest requests (the ones not passed
to block layer) and failed requests (passed to block layer and failed
there). It's a mess in part caused by us never writing down what
exactly device models are expected to do.
Accounting data is used by "query-blockstats", and nothing else.
Corollary: even though every BDS holds accounting data, only the ones in
"top" BDSes ever get used. This is a common block layer blemish, and
we're working on cleaning it up.
If a device model doesn't implement accounting, query-blockstats lies.
Fortunately, its lies are pretty transparent (everything's zero) as long
as you don't do things like connecting a backend to a device model that
doesn't implement accounting after disconnecting it from a device model
that does. Still, I'd welcome a more honest QMP interface.
For me, this accounting data belongs to the device model, not the BDS.
Naturally, the block device models should use common infrastructure. I
guess they use the block layer only because it's obvious infrastructure
they share. Clumsy design.
> /* volume of data transfered by the IOs */
> read_bytes
> write_bytes
This is nr_bytes[BDRV_ACCT_READ] and nr_bytes[BDRV_ACCT_WRITE].
nr_bytes[BDRV_ACCT_FLUSH] is always zero.
Should this count only actual I/O, i.e. accumulated size of successful
operations?
> /* operation count */
> read_ios
> write_ios
> flush_ios
>
> /* how many invalid IOs the guest submit */
> invalid_read_ios
> invalid_write_ios
> invalid_flush_ios
>
> /* how many io error happened */
> read_ios_error
> write_ios_error
> flush_ios_error
This is nr_ops[BDRV_ACCT_READ], nr_ops[BDRV_ACCT_WRITE],
nr_ops[BDRV_ACCT_FLUSH] split up into successful, invalid and failed.
> /* account the time passed doing IOs */
> total_read_time
> total_write_time
> total_flush_time
This is total_time_ns[BDRV_ACCT_READ], total_time_ns[BDRV_ACCT_WRITE],
total_time_ns[BDRV_ACCT_FLUSH].
I guess this should count both successful and failed I/O. Could throw
in invalid, too, but it's probably too quick to matter.
Please specify the unit clearly. Both total_FOO_time_ns or total_FOO_ns
would work for me.
> /* since when the volume is iddle */
> qvolume_iddleness_time
"idle"
The obvious way to maintain this information with the current could
would be saving the value of get_clock() in bdrv_acct_done().
> /* the following would compute latecies for slices of 1 seconds then toss the
> * result and start a new slice. A weighted sumation of the instant latencies
> * could help to implement this.
> */
> 1s_read_average_latency
> 1s_write_average_latency
> 1s_flush_average_latency
>
> /* the former three numbers could be used to further compute a 1
> minute slice value */
> 1m_read_average_latency
> 1m_write_average_latency
> 1m_flush_average_latency
>
> /* the former three numbers could be used to further compute a 1 hours
> slice value */
> 1h_read_average_latency
> 1h_write_average_latency
> 1h_flush_average_latency
This is something like "what we added to total_FOO_time in the last
completed 1s / 1m / 1h time slice divided by the number of additions".
Just another way to accumulate the same raw data, thus no worries.
> /* 1 second average number of requests in flight */
> 1s_read_queue_depth
> 1s_write_queue_depth
>
> /* 1 minute average number of requests in flight */
> 1m_read_queue_depth
> 1m_write_queue_depth
>
> /* 1 hours average number of requests in flight */
> 1h_read_queue_depth
> 1h_write_queue_depth
I guess this involves counting bdrv_acct_start() and bdrv_acct_done().
The "you need not call bdrv_acct_done()" feature may get in the way.
Solvable.
Permit me a short detour into the other use for I/O accounting I
mentioned: data on how exactly guest I/O gets translated to host I/O as
it flows through the nodes in the block graph. Do you think this would
be pretty much the same data, just collected at different points?
> 4) Making this happen
> -------------------------
>
> Outscale want to make these IO stat happen and gave me the go to do whatever
> grunt is required to do so.
> That said we could collaborate on some part of the work.
Cool!
A quick stab at tasks:
* QMP interface, either a compatible extension of query-blockstats or a
new one.
* Rough idea on how to do the shared infrastructure.
* Implement (can be split up into several tasks if desired)
10 years, 3 months
[libvirt] [PATCH-RFC] qemu: Add network bandwidth setting for ethernet interfaces
by Anirban Chakraborty
ethernet interfaces in libvirt currently do not support bandwidth setting.
For example, following xml file for an interface will not apply these
settings to corresponding qdiscs.
----
<interface type="ethernet">
<mac address="02:36:1d:18:2a:e4"/>
<model type="virtio"/>
<script path=""/>
<target dev="tap361d182a-e4"/>
<bandwidth>
<inbound average="984" peak="1024" burst="64"/>
<outbound average="2000" peak="2048" burst="128"/>
</bandwidth>
</interface>
-----
This patch fixes the behavior. Please review it and if it appears ok,
please apply.
thanks,
Anirban Chakraborty
Signed-off-by: Anirban Chakraborty <abchak(a)juniper.net>
---
src/qemu/qemu_command.c | 5 +++++
src/qemu/qemu_hotplug.c | 3 +++
2 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 2184caa..258c6a7 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -7251,6 +7251,11 @@ qemuBuildInterfaceCommandLine(virCommandPtr cmd,
if (tapfd[0] < 0)
goto cleanup;
}
+ /* Configure network bandwidth for ethernet type network interfaces */
+ if (actualType == VIR_DOMAIN_NET_TYPE_ETHERNET)
+ if (virNetDevBandwidthSet(net->ifname,
+ virDomainNetGetActualBandwidth(net), false) < 0)
+ goto cleanup;
if ((actualType == VIR_DOMAIN_NET_TYPE_NETWORK ||
actualType == VIR_DOMAIN_NET_TYPE_BRIDGE ||
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index a364c52..aeb53c5 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -940,6 +940,9 @@ int qemuDomainAttachNetDevice(virConnectPtr conn,
if (qemuOpenVhostNet(vm->def, net, priv->qemuCaps, vhostfd, &vhostfdSize) < 0)
goto cleanup;
} else if (actualType == VIR_DOMAIN_NET_TYPE_ETHERNET) {
+ if (virNetDevBandwidthSet(net->ifname,
+ virDomainNetGetActualBandwidth(net), false) < 0)
+ goto cleanup;
vhostfdSize = 1;
if (VIR_ALLOC(vhostfd) < 0)
goto cleanup;
--
1.8.2.3
10 years, 3 months
[libvirt] [PATCH v2] maint: update to latest gnulib
by Eric Blake
The usual portability fixes; and this includes a fix that adds
a new syntax check for double semicolons (commit 28de556 fixed
some, but gnulib found a better check).
* .gnulib: Update to latest.
* src/xenconfig/xen_common.c (xenFormatConfigCommon): Fix offender.
Signed-off-by: Eric Blake <eblake(a)redhat.com>
---
v1 was here: https://www.redhat.com/archives/libvir-list/2014-September/msg00230.html
Pushing under the gnulib maintenance rule; v1 was acked, and
all that differs is that gnulib now does the syntax check.
.gnulib | 2 +-
src/xenconfig/xen_common.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/.gnulib b/.gnulib
index 2d28074..9565c3b 160000
--- a/.gnulib
+++ b/.gnulib
@@ -1 +1 @@
-Subproject commit 2d280742a9e30088aa169f53353765d5daafe4c0
+Subproject commit 9565c3be73eb6d76b7b42a21d68d2e00a62abb6d
diff --git a/src/xenconfig/xen_common.c b/src/xenconfig/xen_common.c
index accd25f..bab67de 100644
--- a/src/xenconfig/xen_common.c
+++ b/src/xenconfig/xen_common.c
@@ -2034,7 +2034,7 @@ xenFormatConfigCommon(virConfPtr conf,
return -1;
if (xenFormatCPUFeatures(conf, def, xendConfigVersion) < 0)
- return -1;;
+ return -1;
if (xenFormatCDROM(conf, def, xendConfigVersion) < 0)
return -1;
--
1.9.3
10 years, 3 months
Re: [libvirt] [PATCH] openvz: fixed an config file parsing error
by Hongbin Lu
Resend the email below.
On Mon, Sep 1, 2014 at 8:28 PM, Hongbin Lu <hongbin034(a)gmail.com> wrote:
> The OpenVZ driver reported an error on parsing some OpenVZ config
> parameters (e.g. diskspace). This issue is due to the driver made
> two incorrect assumptions about the value of the parameters:
> 1. Assume paramaeter is just a number (e.g. 1024).
> 2. Assume the number is an integer.
> Actually, an OpenVZ config parameter may consists of a scalar and
> a unit, and the scalar is not necessary an integer (e.g. 2.2G).
> This patch is for fixing this issue.
> ---
> src/openvz/openvz_conf.c | 99
> ++++++++++++++++++++++++++++++++++++++++++++-
> src/openvz/openvz_conf.h | 6 +++
> 2 files changed, 102 insertions(+), 3 deletions(-)
>
> diff --git a/src/openvz/openvz_conf.c b/src/openvz/openvz_conf.c
> index 856c9f5..7dba925 100644
> --- a/src/openvz/openvz_conf.c
> +++ b/src/openvz/openvz_conf.c
> @@ -127,6 +127,42 @@ int openvzExtractVersion(struct openvz_driver *driver)
> }
>
>
> +static int
> +openvzParseParamUnit(char* str, openvzParamUnit *unit)
> +{
> + int len = strlen(str);
> + if (len == 0)
> + return -1;
> +
> + switch (str[len - 1]) {
> + case 'G':
> + case 'g':
> + str[len - 1] = '\0';
> + if (unit != NULL)
> + *unit = OPENVZ_PARAM_UNIT_GIGABYTE;
> + break;
> + case 'M':
> + case 'm':
> + str[len - 1] = '\0';
> + if (unit != NULL)
> + *unit = OPENVZ_PARAM_UNIT_MEGABYTE;
> + break;
> + case 'K':
> + case 'k':
> + str[len - 1] = '\0';
> + if (unit != NULL)
> + *unit = OPENVZ_PARAM_UNIT_KILOBYTE;
> + break;
> + case 'P':
> + case 'p':
> + str[len - 1] = '\0';
> + break;
> + }
> +
> + return 0;
> +}
> +
> +
> /* Parse config values of the form barrier:limit into barrier and limit */
> static int
> openvzParseBarrierLimit(const char* value,
> @@ -146,7 +182,10 @@ openvzParseBarrierLimit(const char* value,
> goto error;
> } else {
> if (barrier != NULL) {
> - if (virStrToLong_ull(token, NULL, 10, barrier))
> + if (openvzParseParamUnit(token, NULL) < 0)
> + goto error;
> +
> + if (virStrToLong_ull(token, NULL, 10, barrier) < 0)
> goto error;
> }
> }
> @@ -155,7 +194,10 @@ openvzParseBarrierLimit(const char* value,
> goto error;
> } else {
> if (limit != NULL) {
> - if (virStrToLong_ull(token, NULL, 10, limit))
> + if (openvzParseParamUnit(token, NULL) < 0)
> + goto error;
> +
> + if (virStrToLong_ull(token, NULL, 10, limit) < 0)
> goto error;
> }
> }
> @@ -166,6 +208,57 @@ openvzParseBarrierLimit(const char* value,
> }
>
>
> +static int
> +openvzParseBarrierLimit2(const char* value,
> + unsigned long long *barrier,
> + unsigned long long *limit,
> + openvzParamUnit targetunit)
> +{
> + char *token;
> + char *saveptr = NULL;
> + char *str;
> + double dbarrier, dlimit;
> + openvzParamUnit unit = OPENVZ_PARAM_UNIT_KILOBYTE;
> + int ret = -1;
> +
> + if (VIR_STRDUP(str, value) < 0)
> + goto error;
> +
> + token = strtok_r(str, ":", &saveptr);
> + if (token == NULL)
> + goto error;
> +
> + if (barrier != NULL) {
> + if (openvzParseParamUnit(token, &unit) < 0)
> + goto error;
> +
> + if (virStrToDouble(token, NULL, &dbarrier) < 0)
> + goto error;
> +
> + *barrier = (unsigned long long)(dbarrier * unit / targetunit);
> + }
> +
> + token = strtok_r(NULL, ":", &saveptr);
> + if (token == NULL)
> + goto error;
> +
> + if (limit != NULL) {
> + if (openvzParseParamUnit(token, &unit) < 0)
> + goto error;
> +
> + if (virStrToDouble(token, NULL, &dlimit) < 0)
> + goto error;
> +
> + *limit = (unsigned long long)(dlimit * unit / targetunit);
> + }
> +
> + ret = 0;
> + error:
> + VIR_FREE(str);
> + return ret;
> +}
> +
> +
> virCapsPtr openvzCapsInit(void)
> {
> virCapsPtr caps;
> @@ -396,7 +489,7 @@ openvzReadFSConf(virDomainDefPtr def,
> param = "DISKSPACE";
> ret = openvzReadVPSConfigParam(veid, param, &temp);
> if (ret > 0) {
> - if (openvzParseBarrierLimit(temp, &barrier, &limit)) {
> + if (openvzParseBarrierLimit2(temp, &barrier, &limit,
> OPENVZ_PARAM_UNIT_KILOBYTE)) {
> virReportError(VIR_ERR_INTERNAL_ERROR,
> _("Could not read '%s' from config for
> container %d"),
> param, veid);
> diff --git a/src/openvz/openvz_conf.h b/src/openvz/openvz_conf.h
> index a7de7d2..788dae9 100644
> --- a/src/openvz/openvz_conf.h
> +++ b/src/openvz/openvz_conf.h
> @@ -41,6 +41,12 @@
>
> # define VZCTL_BRIDGE_MIN_VERSION ((3 * 1000 * 1000) + (0 * 1000) + 22 +
> 1)
>
> +typedef enum {
> + OPENVZ_PARAM_UNIT_KILOBYTE = 1,
> + OPENVZ_PARAM_UNIT_MEGABYTE = 1024,
> + OPENVZ_PARAM_UNIT_GIGABYTE = 1024 * 1024,
> +} openvzParamUnit;
> +
> struct openvz_driver {
> virMutex lock;
>
> --
> 1.7.1
>
>
10 years, 3 months
[libvirt] [PATCH v2 0/2] parallels: use parallels SDK instead of prlctl tool
by Dmitry Guryanov
This patchset begins reworking of parallels driver. We have
published Opensource version of parallels SDK (under LGPL license),
so libvirt can link with it.
Dmitry Guryanov (2):
parallels: build with parallels SDK
parallels: login to parallels SDK
configure.ac | 11 +-
po/POTFILES.in | 1 +
src/Makefile.am | 8 +-
src/parallels/parallels_driver.c | 40 ++++++-
src/parallels/parallels_sdk.c | 234 +++++++++++++++++++++++++++++++++++++++
src/parallels/parallels_sdk.h | 30 +++++
src/parallels/parallels_utils.h | 3 +
7 files changed, 318 insertions(+), 9 deletions(-)
create mode 100644 src/parallels/parallels_sdk.c
create mode 100644 src/parallels/parallels_sdk.h
--
1.9.3
10 years, 3 months
[libvirt] [PATCH V2 1/1] libvirtd crash when defining scsi storage pool
by Pradipta Kr. Banerjee
libvirtd crash when defining scsi storage pool
libvirtd crashes when there is an existing SCSI pool defined
with adapter type as 'scsi_host' and defining a new SCSI pool with adapter
type as 'fc_host' and parent attribute missing or vice versa.
For eg If there is an existing SCSI pool with adapter type as 'scsi_host'
defined using the following XML
<pool type='scsi'>
<name>TEST_SCSI_POOL</name>
<source>
<adapter type='scsi_host' name='scsi_host1'/>
</source>
<target>
<path>/dev/disk/by-path</path>
</target>
</pool>
When defining another SCSI pool with adapter type as 'fc_host' using the
following XML will crash libvirtd
<pool type='scsi'>
<name>TEST_SCSI_FC_POOL</name>
<source>
<adapter type='fc_host' wwnn='1234567890abcdef' wwpn='abcdef1234567890'/>
</source>
<target>
<path>/dev/disk/by-path</path>
</target>
</pool>
Same is true for the reverse case as well where there exists a SCSI pool with
adapter type as 'fc_host' and another SCSI pool is defined with adapter type as
'scsi_host'
This happens because for fc_host 'name' is optional attribute whereas for
scsi_host its mandatory. However the check in libvirt for finding duplicate
storage pools doesn't take that into account while comparing, resulting into
libvirt crashing
This patch fixes the issue. This patch is based on the suggestion from John
Ferlan
Signed-off-by: Pradipta Kr. Banerjee <bpradip(a)in.ibm.com>
---
V2: Incorporate suggestions from John Ferlan
src/conf/storage_conf.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c
index e72a869..d42cde7 100644
--- a/src/conf/storage_conf.c
+++ b/src/conf/storage_conf.c
@@ -2117,6 +2117,8 @@ virStoragePoolSourceFindDuplicate(virStoragePoolObjListPtr pools,
break;
case VIR_STORAGE_POOL_SCSI:
if (pool->def->source.adapter.type ==
+ VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_FC_HOST &&
+ def->source.adapter.type ==
VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_FC_HOST) {
if (STREQ(pool->def->source.adapter.data.fchost.wwnn,
def->source.adapter.data.fchost.wwnn) &&
@@ -2124,6 +2126,8 @@ virStoragePoolSourceFindDuplicate(virStoragePoolObjListPtr pools,
def->source.adapter.data.fchost.wwpn))
matchpool = pool;
} else if (pool->def->source.adapter.type ==
+ VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_SCSI_HOST &&
+ def->source.adapter.type ==
VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_SCSI_HOST) {
if (pool->def->source.adapter.data.scsi_host.name) {
if (STREQ(pool->def->source.adapter.data.scsi_host.name,
--
1.9.3
10 years, 3 months
[libvirt] [PATCHv2] Don't include non-migratable features in host-model
by Ján Tomko
Commit fba6bc4 introduced support for the 'invtsc' feature,
which blocks migration. We should not include it in the
host-model CPU by default, because it's intended to be used
with migration.
https://bugzilla.redhat.com/show_bug.cgi?id=1138221
---
v2: added tests and comment, fixed a typo
src/cpu/cpu_map.xml | 2 +-
src/cpu/cpu_x86.c | 65 ++++++++++++++++++++++--
tests/cputest.c | 1 +
tests/cputestdata/x86-host-invtsc+host-model.xml | 22 ++++++++
tests/cputestdata/x86-host-invtsc.xml | 27 ++++++++++
5 files changed, 111 insertions(+), 6 deletions(-)
create mode 100644 tests/cputestdata/x86-host-invtsc+host-model.xml
create mode 100644 tests/cputestdata/x86-host-invtsc.xml
diff --git a/src/cpu/cpu_map.xml b/src/cpu/cpu_map.xml
index 12987a0..18c7b0d 100644
--- a/src/cpu/cpu_map.xml
+++ b/src/cpu/cpu_map.xml
@@ -328,7 +328,7 @@
</feature>
<!-- Advanced Power Management edx features -->
- <feature name='invtsc'>
+ <feature name='invtsc' migratable='no'>
<cpuid function='0x80000007' edx='0x00000100'/>
</feature>
diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
index af2e08e..7571f16 100644
--- a/src/cpu/cpu_x86.c
+++ b/src/cpu/cpu_x86.c
@@ -89,6 +89,7 @@ struct x86_map {
struct x86_vendor *vendors;
struct x86_feature *features;
struct x86_model *models;
+ struct x86_feature *migrate_blockers;
};
static struct x86_map* virCPUx86Map = NULL;
@@ -592,6 +593,28 @@ x86FeatureFree(struct x86_feature *feature)
static struct x86_feature *
+x86FeatureCopy(const struct x86_feature *src)
+{
+ struct x86_feature *feature;
+
+ if (VIR_ALLOC(feature) < 0)
+ return NULL;
+
+ if (VIR_STRDUP(feature->name, src->name) < 0)
+ goto error;
+
+ if ((feature->data = x86DataCopy(src->data)) == NULL)
+ goto error;
+
+ return feature;
+
+ error:
+ x86FeatureFree(feature);
+ return NULL;
+}
+
+
+static struct x86_feature *
x86FeatureFind(const struct x86_map *map,
const char *name)
{
@@ -677,6 +700,9 @@ x86FeatureLoad(xmlXPathContextPtr ctxt,
int ret = 0;
size_t i;
int n;
+ char *str = NULL;
+ bool migratable = true;
+ struct x86_feature *migrate_blocker = NULL;
if (!(feature = x86FeatureNew()))
goto error;
@@ -694,6 +720,10 @@ x86FeatureLoad(xmlXPathContextPtr ctxt,
goto ignore;
}
+ str = virXPathString("string(@migratable)", ctxt);
+ if (STREQ_NULLABLE(str, "no"))
+ migratable = false;
+
n = virXPathNodeSet("./cpuid", ctxt, &nodes);
if (n < 0)
goto ignore;
@@ -710,6 +740,14 @@ x86FeatureLoad(xmlXPathContextPtr ctxt,
goto error;
}
+ if (!migratable) {
+ if ((migrate_blocker = x86FeatureCopy(feature)) == NULL)
+ goto error;
+
+ migrate_blocker->next = map->migrate_blockers;
+ map->migrate_blockers = migrate_blocker;
+ }
+
if (map->features == NULL) {
map->features = feature;
} else {
@@ -720,6 +758,7 @@ x86FeatureLoad(xmlXPathContextPtr ctxt,
out:
ctxt->node = ctxt_node;
VIR_FREE(nodes);
+ VIR_FREE(str);
return ret;
@@ -728,6 +767,7 @@ x86FeatureLoad(xmlXPathContextPtr ctxt,
ignore:
x86FeatureFree(feature);
+ x86FeatureFree(migrate_blocker);
goto out;
}
@@ -1093,6 +1133,12 @@ x86MapFree(struct x86_map *map)
x86VendorFree(vendor);
}
+ while (map->migrate_blockers != NULL) {
+ struct x86_feature *migrate_blocker = map->migrate_blockers;
+ map->migrate_blockers = migrate_blocker->next;
+ x86FeatureFree(migrate_blocker);
+ }
+
VIR_FREE(map);
}
@@ -2025,16 +2071,15 @@ x86UpdateHostModel(virCPUDefPtr guest,
const virCPUDef *host)
{
virCPUDefPtr oldguest = NULL;
+ const struct x86_map *map;
+ const struct x86_feature *feat;
size_t i;
int ret = -1;
guest->match = VIR_CPU_MATCH_EXACT;
- /* no updates are required */
- if (guest->nfeatures == 0) {
- virCPUDefFreeModel(guest);
- return virCPUDefCopyModel(guest, host, true);
- }
+ if (!(map = virCPUx86GetMap()))
+ goto cleanup;
/* update the host model according to the desired configuration */
if (!(oldguest = virCPUDefCopy(guest)))
@@ -2044,6 +2089,16 @@ x86UpdateHostModel(virCPUDefPtr guest,
if (virCPUDefCopyModel(guest, host, true) < 0)
goto cleanup;
+ /* Remove non-migratable features by default
+ * Note: this only works as long as no CPU model contains non-migratable
+ * features directly */
+ for (i = 0; i < guest->nfeatures; i++) {
+ for (feat = map->migrate_blockers; feat; feat = feat->next) {
+ if (STREQ(feat->name, guest->features[i].name))
+ VIR_DELETE_ELEMENT_INPLACE(guest->features, i, guest->nfeatures);
+ }
+ }
+
for (i = 0; i < oldguest->nfeatures; i++) {
if (virCPUDefUpdateFeature(guest,
oldguest->features[i].name,
diff --git a/tests/cputest.c b/tests/cputest.c
index 94c0ebc..a507576 100644
--- a/tests/cputest.c
+++ b/tests/cputest.c
@@ -599,6 +599,7 @@ mymain(void)
DO_TEST_UPDATE("x86", "host", "host-model", VIR_CPU_COMPARE_IDENTICAL);
DO_TEST_UPDATE("x86", "host", "host-model-nofallback", VIR_CPU_COMPARE_IDENTICAL);
DO_TEST_UPDATE("x86", "host", "host-passthrough", VIR_CPU_COMPARE_IDENTICAL);
+ DO_TEST_UPDATE("x86", "host-invtsc", "host-model", VIR_CPU_COMPARE_SUPERSET);
/* computing baseline CPUs */
DO_TEST_BASELINE("x86", "incompatible-vendors", 0, -1);
diff --git a/tests/cputestdata/x86-host-invtsc+host-model.xml b/tests/cputestdata/x86-host-invtsc+host-model.xml
new file mode 100644
index 0000000..ad1bbf8
--- /dev/null
+++ b/tests/cputestdata/x86-host-invtsc+host-model.xml
@@ -0,0 +1,22 @@
+<cpu mode='host-model' match='exact'>
+ <model fallback='allow'>SandyBridge</model>
+ <vendor>Intel</vendor>
+ <feature policy='require' name='osxsave'/>
+ <feature policy='require' name='pcid'/>
+ <feature policy='require' name='pdcm'/>
+ <feature policy='require' name='xtpr'/>
+ <feature policy='require' name='tm2'/>
+ <feature policy='require' name='est'/>
+ <feature policy='require' name='smx'/>
+ <feature policy='require' name='vmx'/>
+ <feature policy='require' name='ds_cpl'/>
+ <feature policy='require' name='monitor'/>
+ <feature policy='require' name='dtes64'/>
+ <feature policy='require' name='pbe'/>
+ <feature policy='require' name='tm'/>
+ <feature policy='require' name='ht'/>
+ <feature policy='require' name='ss'/>
+ <feature policy='require' name='acpi'/>
+ <feature policy='require' name='ds'/>
+ <feature policy='require' name='vme'/>
+</cpu>
diff --git a/tests/cputestdata/x86-host-invtsc.xml b/tests/cputestdata/x86-host-invtsc.xml
new file mode 100644
index 0000000..f558399
--- /dev/null
+++ b/tests/cputestdata/x86-host-invtsc.xml
@@ -0,0 +1,27 @@
+<cpu>
+ <arch>x86_64</arch>
+ <model>SandyBridge</model>
+ <vendor>Intel</vendor>
+ <topology sockets='1' cores='2' threads='2'/>
+ <feature name='invtsc'/>
+ <feature name='osxsave'/>
+ <feature name='pcid'/>
+ <feature name='pdcm'/>
+ <feature name='xtpr'/>
+ <feature name='tm2'/>
+ <feature name='est'/>
+ <feature name='smx'/>
+ <feature name='vmx'/>
+ <feature name='ds_cpl'/>
+ <feature name='monitor'/>
+ <feature name='dtes64'/>
+ <feature name='pbe'/>
+ <feature name='tm'/>
+ <feature name='ht'/>
+ <feature name='ss'/>
+ <feature name='acpi'/>
+ <feature name='ds'/>
+ <feature name='vme'/>
+ <pages unit='KiB' size='4'/>
+ <pages unit='KiB' size='2048'/>
+</cpu>
--
1.8.5.5
10 years, 3 months
[libvirt] Entering freeze for libvirt-1.2.8
by Daniel Veillard
So I tagged 1.2.8-rc1 in git and made tarball and signed rpms
available at the usual place:
ftp://libvirt.org/libvirt/
While we seems to have the new API in place it's also clear that there
is a bunch of patches still waiting, either related to the new APIs
or blocked by lack of review. Please try to prioritize filling up API
implementations, and bug fixes for the reviews but I think we need to be
open about incremental improvements when they are very specific and
allow them in !
I will try to release by Tuesday 2nd Sep, as I will be on the road
next week after that time. However the good point of that monthly cycle
is that if you get the ACKs needed even if that's not in 1.2.8 that will
be in for 1.2.9 next month, in time for KVM Forum :-)
Please give a try to the current version, I'm a limited capacity
to test it this time,
thanks !
Daniel
--
Daniel Veillard | Open Source and Standards, Red Hat
veillard(a)redhat.com | libxml Gnome XML XSLT toolkit http://xmlsoft.org/
http://veillard.com/ | virtualization library http://libvirt.org/
10 years, 3 months
[libvirt] [PATCH 0/2] Use huge pages on UMA guests widely
by Michal Privoznik
*** BLURB HERE ***
Michal Privoznik (2):
conf: Disallow nonexistent NUMA nodes for hugepages
qemu: Honor hugepages for UMA domains
src/conf/domain_conf.c | 36 +++++++++++++++++
src/qemu/qemu_command.c | 25 ++++++++++--
.../qemuxml2argv-hugepages-pages4.xml | 45 ++++++++++++++++++++++
.../qemuxml2argv-hugepages-pages5.args | 7 ++++
.../qemuxml2argv-hugepages-pages5.xml | 32 +++++++++++++++
tests/qemuxml2argvtest.c | 2 +
6 files changed, 143 insertions(+), 4 deletions(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hugepages-pages4.xml
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hugepages-pages5.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hugepages-pages5.xml
--
1.8.5.5
10 years, 3 months