Compare commits

..

23 Commits

Author SHA1 Message Date
Fedora Release Engineering b32c6d8d48 dist-git conversion 2010-07-29 07:21:05 +00:00
Bill Nottingham 18819f9796 Fix typo that causes a failure to update the common directory. (releng #2781) 2009-11-26 01:55:06 +00:00
Mark McLoughlin 7b23a93c36 * Mon Oct 19 2009 Mark McLoughlin <markmc@redhat.com> - 0.6.2-19
- Ignore re-labelling errors on NFS (#517157)
2009-10-19 11:15:16 +00:00
Mark McLoughlin e8eadea9cd * Wed Sep 30 2009 Mark McLoughlin <markmc@redhat.com> - 0.6.2-18
- Fix qemu-kvm version detection so GSO is enabled for virtio_net (#526472)
2009-09-30 14:20:16 +00:00
Mark McLoughlin 5d42cf83f8 Add URL to source tag 2009-08-21 10:20:12 +00:00
Mark McLoughlin 36d6c9d752 * Wed Aug 19 2009 Mark McLoughlin <markmc@redhat.com> - 0.6.2-17
- Fix migration completion with newer versions of qemu (#516187)
- Fix dumpxml segfault with newer versions of Xen (#518091)
2009-08-19 17:08:59 +00:00
Mark McLoughlin 529d097d28 * Wed Aug 19 2009 Mark McLoughlin <markmc@redhat.com> - 0.6.2-16.fc11
- Allow PCI bus reset to reset other devices (#499678)
- Fix stupid PCI reset error message (bug #499678)
- Allow PM reset on multi-function PCI devices (bug #515689)
- Re-attach PCI host devices after guest shuts down (bug #499561)
- Fixes list corruption after disk hot-unplug
- Fix minor 'virsh nodedev-list --tree' annoyance
2009-08-19 16:15:46 +00:00
Mark McLoughlin 3eb78ffd37 Sync patches from git 2009-08-17 08:08:56 +00:00
Daniel P. Berrange 8841355697 Log and ignore NUMA topology problems (rhbz #506590) 2009-08-13 16:07:23 +00:00
Daniel P. Berrange 40a867daeb Misc important fixes from BZ
- Fix crash when attaching/detaching non-existant PCI device (rhbz #510907)
- Fix QEMU guest name/uuid uniqueness checks (rhbz #507405)
- Fix to use correct pci_add/del syntax for QEMU (rhbz #499669)
- Relabel disks before hotplugging them to guest (rhbz #496442)
- Correctly handle 8-bit high bytes when escaping XML (rhbz #479517)
2009-08-05 15:48:14 +00:00
Mark McLoughlin 60e1b2cda5 * Fri Jul 3 2009 Mark McLoughlin <markmc@redhat.com> - 0.6.2-13.fc11
- Fix libvirtd crash with bad capabilities data (bug #505635)
- Don't unnecessarily try to change a file context (bug #507555)
2009-07-03 10:05:41 +00:00
Mark McLoughlin c8361aee7d * Fri Jun 5 2009 Mark McLoughlin <markmc@redhat.com> - 0.6.2-12.fc11
- Use the correct QEMU machine type for ppc (bug #502862)
- Fix crash with TLS connections (bug #503066)
- Fix broken networking with newer qemu releases (bug #503275)
- Remove the qemu BuildRequires
2009-06-05 11:47:31 +00:00
Mark McLoughlin bda88aaa38 * Mon May 25 2009 Mark McLoughlin <markmc@redhat.com> - 0.6.2-11.fc11
- Bring up the bridge, even if it doesn't have an IP address (bug #501912)
2009-05-25 15:23:17 +00:00
Mark McLoughlin ca4d795c85 * Fri May 22 2009 Mark McLoughlin <markmc@redhat.com> - 0.6.2-10.fc11
- Don't log monitor output to domain log file (bug #499584)
2009-05-22 09:24:30 +00:00
Mark McLoughlin e2e196d813 * Thu May 21 2009 Mark McLoughlin <markmc@redhat.com> - 0.6.2-9.fc11
- Fix qemu argv detection with latest qemu (bug #501923)
- Fix XML attribute escaping (bug #499791)
- Fix serious event handling issues causing guests to be destroyed (bug #499698)
2009-05-21 12:07:19 +00:00
Cole Robinson a5a2a38a5e Don't try to label a disk with no path (e.g. empty cdrom) (bug #499569) 2009-05-11 02:28:23 +00:00
Mark McLoughlin 30f098460c * Thu May 7 2009 Mark McLoughlin <markmc@redhat.com> - 0.6.2-7.fc11
- Enable migration for qemu 0.10 (bug #499704)
2009-05-07 19:08:42 +00:00
Cole Robinson 7017c99a1e Refresh qemu caps when getCapabilities is called (bug #460649) 2009-05-06 16:32:34 +00:00
Mark McLoughlin 1c41ce6f30 * Wed May 6 2009 Mark McLoughlin <markmc@redhat.com> - 0.6.2-5.fc11
- Fix handling of <hostdev managed='yes'> (bug #499386)
2009-05-06 15:51:47 +00:00
Daniel P. Berrange c6db79d97f Fix labelling of shared/readonly disks (rhbz #493692) 2009-05-05 13:01:15 +00:00
Daniel Veillard 7b7f8cc27f - Fix missing directories in spec (#496945 and gtk-doc)
Daniel
2009-04-28 10:57:59 +00:00
Mark McLoughlin a9cc41b082 * Thu Apr 16 2009 Mark McLoughlin <markmc@redhat.com> - 0.6.2-2.fc11
- Fix qemu drive format specification (#496092)
2009-04-16 15:26:45 +00:00
Jesse Keating ce1593f88f Initialize branch F-11 for libvirt 2009-04-15 07:13:06 +00:00
68 changed files with 4884 additions and 4769 deletions
+4 -1
View File
@@ -2,4 +2,7 @@
*.rpm
i686
x86_64
libvirt-*.tar.xz
libvirt-*.tar.gz
libvirt-0.6.0.tar.gz
libvirt-0.6.1.tar.gz
libvirt-0.6.2.tar.gz
@@ -1,34 +0,0 @@
From: Stefan Berger <stefanb@linux.vnet.ibm.com>
Date: Thu, 29 Jun 2017 14:01:11 -0400
Subject: [PATCH] tpm: Use /dev/null for cancel path if none was found
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
TPM 2 does not implement sysfs files for cancellation of commands.
We therefore use /dev/null for the cancel path passed to QEMU.
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
Tested-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
(cherry picked from commit dfbb15b75433e520fb1b905c1c3e28753e53e4a5)
---
src/util/virtpm.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/src/util/virtpm.c b/src/util/virtpm.c
index 6d9b0657a..d5c10da38 100644
--- a/src/util/virtpm.c
+++ b/src/util/virtpm.c
@@ -61,9 +61,7 @@ virTPMCreateCancelPath(const char *devpath)
VIR_FREE(path);
}
if (!path)
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("No usable sysfs TPM cancel file could be "
- "found"));
+ ignore_value(VIR_STRDUP(path, "/dev/null"));
} else {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("TPM device path %s is invalid"), devpath);
@@ -1,108 +0,0 @@
From: Cole Robinson <crobinso@redhat.com>
Date: Sun, 27 Aug 2017 11:23:47 -0400
Subject: [PATCH] security: add MANAGER_MOUNT_NAMESPACE flag
The VIR_SECURITY_MANAGER_MOUNT_NAMESPACE flag informs the DAC driver
if mount namespaces are in use for the VM. Will be used for future
changes.
Wire it up in the qemu driver
(cherry picked from commit 321031e482425dfeae0f125cdac6df870f079efd)
---
src/qemu/qemu_driver.c | 2 ++
src/security/security_dac.c | 10 ++++++++++
src/security/security_dac.h | 3 +++
src/security/security_manager.c | 4 +++-
src/security/security_manager.h | 1 +
5 files changed, 19 insertions(+), 1 deletion(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index b7824512c..1f9264639 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -419,6 +419,8 @@ qemuSecurityInit(virQEMUDriverPtr driver)
if (virQEMUDriverIsPrivileged(driver)) {
if (cfg->dynamicOwnership)
flags |= VIR_SECURITY_MANAGER_DYNAMIC_OWNERSHIP;
+ if (virBitmapIsBitSet(cfg->namespaces, QEMU_DOMAIN_NS_MOUNT))
+ flags |= VIR_SECURITY_MANAGER_MOUNT_NAMESPACE;
if (!(mgr = qemuSecurityNewDAC(QEMU_DRIVER_NAME,
cfg->user,
cfg->group,
diff --git a/src/security/security_dac.c b/src/security/security_dac.c
index ca7a6af6d..507be44a2 100644
--- a/src/security/security_dac.c
+++ b/src/security/security_dac.c
@@ -57,6 +57,7 @@ struct _virSecurityDACData {
gid_t *groups;
int ngroups;
bool dynamicOwnership;
+ bool mountNamespace;
char *baselabel;
virSecurityManagerDACChownCallback chownCallback;
};
@@ -237,6 +238,15 @@ virSecurityDACSetDynamicOwnership(virSecurityManagerPtr mgr,
priv->dynamicOwnership = dynamicOwnership;
}
+void
+virSecurityDACSetMountNamespace(virSecurityManagerPtr mgr,
+ bool mountNamespace)
+{
+ virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+ priv->mountNamespace = mountNamespace;
+}
+
+
void
virSecurityDACSetChownCallback(virSecurityManagerPtr mgr,
virSecurityManagerDACChownCallback chownCallback)
diff --git a/src/security/security_dac.h b/src/security/security_dac.h
index 846cefbb5..97681c961 100644
--- a/src/security/security_dac.h
+++ b/src/security/security_dac.h
@@ -32,6 +32,9 @@ int virSecurityDACSetUserAndGroup(virSecurityManagerPtr mgr,
void virSecurityDACSetDynamicOwnership(virSecurityManagerPtr mgr,
bool dynamic);
+void virSecurityDACSetMountNamespace(virSecurityManagerPtr mgr,
+ bool mountNamespace);
+
void virSecurityDACSetChownCallback(virSecurityManagerPtr mgr,
virSecurityManagerDACChownCallback chownCallback);
diff --git a/src/security/security_manager.c b/src/security/security_manager.c
index 95b995230..e43c99d4f 100644
--- a/src/security/security_manager.c
+++ b/src/security/security_manager.c
@@ -146,7 +146,8 @@ virSecurityManagerNewDAC(const char *virtDriver,
virSecurityManagerPtr mgr;
virCheckFlags(VIR_SECURITY_MANAGER_NEW_MASK |
- VIR_SECURITY_MANAGER_DYNAMIC_OWNERSHIP, NULL);
+ VIR_SECURITY_MANAGER_DYNAMIC_OWNERSHIP |
+ VIR_SECURITY_MANAGER_MOUNT_NAMESPACE, NULL);
mgr = virSecurityManagerNewDriver(&virSecurityDriverDAC,
virtDriver,
@@ -161,6 +162,7 @@ virSecurityManagerNewDAC(const char *virtDriver,
}
virSecurityDACSetDynamicOwnership(mgr, flags & VIR_SECURITY_MANAGER_DYNAMIC_OWNERSHIP);
+ virSecurityDACSetMountNamespace(mgr, flags & VIR_SECURITY_MANAGER_MOUNT_NAMESPACE);
virSecurityDACSetChownCallback(mgr, chownCallback);
return mgr;
diff --git a/src/security/security_manager.h b/src/security/security_manager.h
index 01296d339..08fb89203 100644
--- a/src/security/security_manager.h
+++ b/src/security/security_manager.h
@@ -36,6 +36,7 @@ typedef enum {
VIR_SECURITY_MANAGER_REQUIRE_CONFINED = 1 << 2,
VIR_SECURITY_MANAGER_PRIVILEGED = 1 << 3,
VIR_SECURITY_MANAGER_DYNAMIC_OWNERSHIP = 1 << 4,
+ VIR_SECURITY_MANAGER_MOUNT_NAMESPACE = 1 << 5,
} virSecurityManagerNewFlags;
# define VIR_SECURITY_MANAGER_NEW_MASK \
@@ -1,101 +0,0 @@
From: Cole Robinson <crobinso@redhat.com>
Date: Mon, 17 Jul 2017 08:57:57 -0400
Subject: [PATCH] security: dac: relabel spice rendernode
For a logged in user this a path like /dev/dri/renderD128 will have
default ownership root:video which won't work for the qemu:qemu user,
so we need to chown it.
We only do this when mount namespaces are enabled in the qemu driver,
so the chown'ing doesn't interfere with other users of the shared
render node path
https://bugzilla.redhat.com/show_bug.cgi?id=1460804
(cherry picked from commit 98931187eefdec6f2dea5cb82ab6d23a3ffa6634)
---
src/security/security_dac.c | 58 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 58 insertions(+)
diff --git a/src/security/security_dac.c b/src/security/security_dac.c
index 507be44a2..349dbe81d 100644
--- a/src/security/security_dac.c
+++ b/src/security/security_dac.c
@@ -1380,6 +1380,54 @@ virSecurityDACRestoreTPMFileLabel(virSecurityManagerPtr mgr,
}
+static int
+virSecurityDACSetGraphicsLabel(virSecurityManagerPtr mgr,
+ virDomainDefPtr def,
+ virDomainGraphicsDefPtr gfx)
+
+{
+ virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+ virSecurityLabelDefPtr seclabel;
+ uid_t user;
+ gid_t group;
+
+ /* Skip chowning the shared render file if namespaces are disabled */
+ if (!priv->mountNamespace)
+ return 0;
+
+ seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);
+ if (seclabel && !seclabel->relabel)
+ return 0;
+
+ if (virSecurityDACGetIds(seclabel, priv, &user, &group, NULL, NULL) < 0)
+ return -1;
+
+ if (gfx->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE &&
+ gfx->data.spice.gl == VIR_TRISTATE_BOOL_YES &&
+ gfx->data.spice.rendernode) {
+ if (virSecurityDACSetOwnership(priv, NULL,
+ gfx->data.spice.rendernode,
+ user, group) < 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static int
+virSecurityDACRestoreGraphicsLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+ virDomainDefPtr def ATTRIBUTE_UNUSED,
+ virDomainGraphicsDefPtr gfx ATTRIBUTE_UNUSED)
+
+{
+ /* The only graphics labelling we do is dependent on mountNamespaces,
+ in which case 'restoring' the label doesn't actually accomplish
+ anything, so there's nothing to do here */
+ return 0;
+}
+
+
static int
virSecurityDACSetInputLabel(virSecurityManagerPtr mgr,
virDomainDefPtr def,
@@ -1491,6 +1539,11 @@ virSecurityDACRestoreAllLabel(virSecurityManagerPtr mgr,
rc = -1;
}
+ for (i = 0; i < def->ngraphics; i++) {
+ if (virSecurityDACRestoreGraphicsLabel(mgr, def, def->graphics[i]) < 0)
+ return -1;
+ }
+
for (i = 0; i < def->ninputs; i++) {
if (virSecurityDACRestoreInputLabel(mgr, def, def->inputs[i]) < 0)
rc = -1;
@@ -1611,6 +1664,11 @@ virSecurityDACSetAllLabel(virSecurityManagerPtr mgr,
return -1;
}
+ for (i = 0; i < def->ngraphics; i++) {
+ if (virSecurityDACSetGraphicsLabel(mgr, def, def->graphics[i]) < 0)
+ return -1;
+ }
+
for (i = 0; i < def->ninputs; i++) {
if (virSecurityDACSetInputLabel(mgr, def, def->inputs[i]) < 0)
return -1;
@@ -1,72 +0,0 @@
From: "Daniel P. Berrange" <berrange@redhat.com>
Date: Thu, 5 Oct 2017 17:54:28 +0100
Subject: [PATCH] qemu: ensure TLS clients always verify the server certificate
The default_tls_x509_verify (and related) parameters in qemu.conf
control whether the QEMU TLS servers request & verify certificates
from clients. This works as a simple access control system for
servers by requiring the CA to issue certs to permitted clients.
This use of client certificates is disabled by default, since it
requires extra work to issue client certificates.
Unfortunately the code was using this configuration parameter when
setting up both TLS clients and servers in QEMU. The result was that
TLS clients for character devices and disk devices had verification
turned off, meaning they would ignore errors while validating the
server certificate.
This allows for trivial MITM attacks between client and server,
as any certificate returned by the attacker will be accepted by
the client.
This is assigned CVE-2017-1000256 / LSN-2017-0002
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
(cherry picked from commit 441d3eb6d1be940a67ce45a286602a967601b157)
(cherry picked from commit dc6c41798d1eb5c52c75365ffa22f7672709dfa7)
---
src/qemu/qemu_command.c | 2 +-
tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-chardev.args | 2 +-
.../qemuxml2argv-serial-tcp-tlsx509-secret-chardev.args | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 9a27987d4..ae78cd17e 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -718,7 +718,7 @@ qemuBuildTLSx509BackendProps(const char *tlspath,
if (virJSONValueObjectCreate(propsret,
"s:dir", path,
"s:endpoint", (isListen ? "server": "client"),
- "b:verify-peer", verifypeer,
+ "b:verify-peer", (isListen ? verifypeer : true),
NULL) < 0)
goto cleanup;
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-chardev.args b/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-chardev.args
index 5aff7734e..ab5f7e27f 100644
--- a/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-chardev.args
+++ b/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-chardev.args
@@ -26,7 +26,7 @@ server,nowait \
localport=1111 \
-device isa-serial,chardev=charserial0,id=serial0 \
-object tls-creds-x509,id=objcharserial1_tls0,dir=/etc/pki/libvirt-chardev,\
-endpoint=client,verify-peer=no \
+endpoint=client,verify-peer=yes \
-chardev socket,id=charserial1,host=127.0.0.1,port=5555,\
tls-creds=objcharserial1_tls0 \
-device isa-serial,chardev=charserial1,id=serial1 \
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-secret-chardev.args b/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-secret-chardev.args
index 91f1fe0cd..2567abbfa 100644
--- a/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-secret-chardev.args
+++ b/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-secret-chardev.args
@@ -31,7 +31,7 @@ localport=1111 \
data=9eao5F8qtkGt+seB1HYivWIxbtwUu6MQtg1zpj/oDtUsPr1q8wBYM91uEHCn6j/1,\
keyid=masterKey0,iv=AAECAwQFBgcICQoLDA0ODw==,format=base64 \
-object tls-creds-x509,id=objcharserial1_tls0,dir=/etc/pki/libvirt-chardev,\
-endpoint=client,verify-peer=no,passwordid=charserial1-secret0 \
+endpoint=client,verify-peer=yes,passwordid=charserial1-secret0 \
-chardev socket,id=charserial1,host=127.0.0.1,port=5555,\
tls-creds=objcharserial1_tls0 \
-device isa-serial,chardev=charserial1,id=serial1 \
@@ -1,177 +0,0 @@
From: Peter Krempa <pkrempa@redhat.com>
Date: Wed, 15 Nov 2017 13:15:57 +0100
Subject: [PATCH] qemu: Move snapshot disk validation functions into one
Move the code so that both the new image and old image can be verified
in the same function.
(cherry picked from commit 8ffdeed455650557df531aafc66c20b31bd4e0c4)
---
src/qemu/qemu_driver.c | 91 ++++++++++++++++++++------------------------------
1 file changed, 36 insertions(+), 55 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 1f9264639..57f0c2bf4 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -13793,17 +13793,19 @@ qemuDomainSnapshotCreateActiveInternal(virConnectPtr conn,
static int
-qemuDomainSnapshotPrepareDiskExternalBackingInactive(virDomainDiskDefPtr disk)
+qemuDomainSnapshotPrepareDiskExternalInactive(virDomainSnapshotDiskDefPtr snapdisk,
+ virDomainDiskDefPtr domdisk)
{
- int actualType = virStorageSourceGetActualType(disk->src);
+ int domDiskType = virStorageSourceGetActualType(domdisk->src);
+ int snapDiskType = virStorageSourceGetActualType(snapdisk->src);
- switch ((virStorageType) actualType) {
+ switch ((virStorageType) domDiskType) {
case VIR_STORAGE_TYPE_BLOCK:
case VIR_STORAGE_TYPE_FILE:
- return 0;
+ break;
case VIR_STORAGE_TYPE_NETWORK:
- switch ((virStorageNetProtocol) disk->src->protocol) {
+ switch ((virStorageNetProtocol) domdisk->src->protocol) {
case VIR_STORAGE_NET_PROTOCOL_NONE:
case VIR_STORAGE_NET_PROTOCOL_NBD:
case VIR_STORAGE_NET_PROTOCOL_RBD:
@@ -13820,7 +13822,7 @@ qemuDomainSnapshotPrepareDiskExternalBackingInactive(virDomainDiskDefPtr disk)
virReportError(VIR_ERR_INTERNAL_ERROR,
_("external inactive snapshots are not supported on "
"'network' disks using '%s' protocol"),
- virStorageNetProtocolTypeToString(disk->src->protocol));
+ virStorageNetProtocolTypeToString(domdisk->src->protocol));
return -1;
}
break;
@@ -13831,7 +13833,23 @@ qemuDomainSnapshotPrepareDiskExternalBackingInactive(virDomainDiskDefPtr disk)
case VIR_STORAGE_TYPE_LAST:
virReportError(VIR_ERR_INTERNAL_ERROR,
_("external inactive snapshots are not supported on "
- "'%s' disks"), virStorageTypeToString(actualType));
+ "'%s' disks"), virStorageTypeToString(domDiskType));
+ return -1;
+ }
+
+ switch ((virStorageType) snapDiskType) {
+ case VIR_STORAGE_TYPE_BLOCK:
+ case VIR_STORAGE_TYPE_FILE:
+ break;
+
+ case VIR_STORAGE_TYPE_NETWORK:
+ case VIR_STORAGE_TYPE_DIR:
+ case VIR_STORAGE_TYPE_VOLUME:
+ case VIR_STORAGE_TYPE_NONE:
+ case VIR_STORAGE_TYPE_LAST:
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("external inactive snapshots are not supported on "
+ "'%s' disks"), virStorageTypeToString(snapDiskType));
return -1;
}
@@ -13840,33 +13858,27 @@ qemuDomainSnapshotPrepareDiskExternalBackingInactive(virDomainDiskDefPtr disk)
static int
-qemuDomainSnapshotPrepareDiskExternalBackingActive(virDomainDiskDefPtr disk)
+qemuDomainSnapshotPrepareDiskExternalActive(virDomainSnapshotDiskDefPtr snapdisk,
+ virDomainDiskDefPtr domdisk)
{
- if (disk->device == VIR_DOMAIN_DISK_DEVICE_LUN) {
+ int actualType = virStorageSourceGetActualType(snapdisk->src);
+
+ if (domdisk->device == VIR_DOMAIN_DISK_DEVICE_LUN) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("external active snapshots are not supported on scsi "
"passthrough devices"));
return -1;
}
- return 0;
-}
-
-
-static int
-qemuDomainSnapshotPrepareDiskExternalOverlayActive(virDomainSnapshotDiskDefPtr disk)
-{
- int actualType = virStorageSourceGetActualType(disk->src);
-
switch ((virStorageType) actualType) {
case VIR_STORAGE_TYPE_BLOCK:
case VIR_STORAGE_TYPE_FILE:
- return 0;
+ break;
case VIR_STORAGE_TYPE_NETWORK:
- switch ((virStorageNetProtocol) disk->src->protocol) {
+ switch ((virStorageNetProtocol) snapdisk->src->protocol) {
case VIR_STORAGE_NET_PROTOCOL_GLUSTER:
- return 0;
+ break;
case VIR_STORAGE_NET_PROTOCOL_NONE:
case VIR_STORAGE_NET_PROTOCOL_NBD:
@@ -13883,7 +13895,7 @@ qemuDomainSnapshotPrepareDiskExternalOverlayActive(virDomainSnapshotDiskDefPtr d
virReportError(VIR_ERR_INTERNAL_ERROR,
_("external active snapshots are not supported on "
"'network' disks using '%s' protocol"),
- virStorageNetProtocolTypeToString(disk->src->protocol));
+ virStorageNetProtocolTypeToString(snapdisk->src->protocol));
return -1;
}
@@ -13903,31 +13915,6 @@ qemuDomainSnapshotPrepareDiskExternalOverlayActive(virDomainSnapshotDiskDefPtr d
}
-static int
-qemuDomainSnapshotPrepareDiskExternalOverlayInactive(virDomainSnapshotDiskDefPtr disk)
-{
- int actualType = virStorageSourceGetActualType(disk->src);
-
- switch ((virStorageType) actualType) {
- case VIR_STORAGE_TYPE_BLOCK:
- case VIR_STORAGE_TYPE_FILE:
- return 0;
-
- case VIR_STORAGE_TYPE_NETWORK:
- case VIR_STORAGE_TYPE_DIR:
- case VIR_STORAGE_TYPE_VOLUME:
- case VIR_STORAGE_TYPE_NONE:
- case VIR_STORAGE_TYPE_LAST:
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("external inactive snapshots are not supported on "
- "'%s' disks"), virStorageTypeToString(actualType));
- return -1;
- }
-
- return 0;
-}
-
-
static int
qemuDomainSnapshotPrepareDiskExternal(virConnectPtr conn,
virDomainDiskDefPtr disk,
@@ -13945,16 +13932,10 @@ qemuDomainSnapshotPrepareDiskExternal(virConnectPtr conn,
if (virStorageTranslateDiskSourcePool(conn, disk) < 0)
return -1;
- if (qemuDomainSnapshotPrepareDiskExternalBackingInactive(disk) < 0)
- return -1;
-
- if (qemuDomainSnapshotPrepareDiskExternalOverlayInactive(snapdisk) < 0)
+ if (qemuDomainSnapshotPrepareDiskExternalInactive(snapdisk, disk) < 0)
return -1;
} else {
- if (qemuDomainSnapshotPrepareDiskExternalBackingActive(disk) < 0)
- return -1;
-
- if (qemuDomainSnapshotPrepareDiskExternalOverlayActive(snapdisk) < 0)
+ if (qemuDomainSnapshotPrepareDiskExternalActive(snapdisk, disk) < 0)
return -1;
}
@@ -1,55 +0,0 @@
From: Peter Krempa <pkrempa@redhat.com>
Date: Tue, 14 Nov 2017 15:34:46 +0100
Subject: [PATCH] qemu: block: Add function to check if storage source allows
concurrent access
Storage source format backing a shared device (e.g. running a cluster
filesystem) needs to support the sharing so that metadata are not
corrupted. Add a central function for checking this.
(cherry picked from commit 1fc3cd8731640aefc48bbd9fc489f21cb99c6f67)
---
src/qemu/qemu_block.c | 15 +++++++++++++++
src/qemu/qemu_block.h | 3 +++
2 files changed, 18 insertions(+)
diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
index 7fb12ea5a..4c0a5eb78 100644
--- a/src/qemu/qemu_block.c
+++ b/src/qemu/qemu_block.c
@@ -379,6 +379,21 @@ qemuBlockGetNodeData(virJSONValuePtr data)
}
+/**
+ * qemuBlockStorageSourceSupportsConcurrentAccess:
+ * @src: disk storage source
+ *
+ * Returns true if the given storage format supports concurrent access from two
+ * separate processes.
+ */
+bool
+qemuBlockStorageSourceSupportsConcurrentAccess(virStorageSourcePtr src)
+{
+ /* no need to check in backing chain since only RAW storage supports this */
+ return src->format == VIR_STORAGE_FILE_RAW;
+}
+
+
/**
* qemuBlockStorageSourceBuildHostsJSONSocketAddress:
* @src: disk storage source
diff --git a/src/qemu/qemu_block.h b/src/qemu/qemu_block.h
index f0a2c9aa7..ebf3149ce 100644
--- a/src/qemu/qemu_block.h
+++ b/src/qemu/qemu_block.h
@@ -53,6 +53,9 @@ qemuBlockNodeNamesDetect(virQEMUDriverPtr driver,
virHashTablePtr
qemuBlockGetNodeData(virJSONValuePtr data);
+bool
+qemuBlockStorageSourceSupportsConcurrentAccess(virStorageSourcePtr src);
+
virJSONValuePtr
qemuBlockStorageSourceGetBackendProps(virStorageSourcePtr src);
@@ -1,146 +0,0 @@
From: Peter Krempa <pkrempa@redhat.com>
Date: Tue, 14 Nov 2017 15:37:09 +0100
Subject: [PATCH] qemu: domain: Reject shared disk access if backing format
does not support it
Disk sharing between two VMs may corrupt the images if the format driver
does not support it. Check that the user declared use of a supported
storage format when they want to share the disk.
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1511480
(cherry picked from commit 3b03a27cd00c2f032661d2bf8905795425752fc7)
---
src/qemu/qemu_domain.c | 29 +++++++++++++++++++++-
.../qemuxml2argv-disk-drive-shared-qcow.xml | 28 +++++++++++++++++++++
.../qemuxml2argv-disk-drive-shared.args | 2 +-
.../qemuxml2argv-disk-drive-shared.xml | 2 +-
tests/qemuxml2argvtest.c | 1 +
5 files changed, 59 insertions(+), 3 deletions(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-shared-qcow.xml
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index b98ffffae..42d17c1b0 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -25,6 +25,7 @@
#include "qemu_domain.h"
#include "qemu_alias.h"
+#include "qemu_block.h"
#include "qemu_cgroup.h"
#include "qemu_command.h"
#include "qemu_process.h"
@@ -3299,6 +3300,29 @@ qemuDomainRedirdevDefValidate(const virDomainRedirdevDef *def)
}
+static int
+qemuDomainDeviceDefValidateDisk(const virDomainDiskDef *disk)
+{
+ if (disk->src->shared && !disk->src->readonly) {
+ if (disk->src->format <= VIR_STORAGE_FILE_AUTO) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("shared access for disk '%s' requires use of "
+ "explicitly specified disk format"), disk->dst);
+ return -1;
+ }
+
+ if (!qemuBlockStorageSourceSupportsConcurrentAccess(disk->src)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("shared access for disk '%s' requires use of "
+ "supported storage format"), disk->dst);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+
static int
qemuDomainDeviceDefValidate(const virDomainDeviceDef *dev,
const virDomainDef *def ATTRIBUTE_UNUSED,
@@ -3308,7 +3332,10 @@ qemuDomainDeviceDefValidate(const virDomainDeviceDef *dev,
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
int ret = -1;
- if (dev->type == VIR_DOMAIN_DEVICE_NET) {
+ if (dev->type == VIR_DOMAIN_DEVICE_DISK) {
+ if (qemuDomainDeviceDefValidateDisk(dev->data.disk) < 0)
+ goto cleanup;
+ } else if (dev->type == VIR_DOMAIN_DEVICE_NET) {
const virDomainNetDef *net = dev->data.net;
if (net->guestIP.nroutes || net->guestIP.nips) {
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-shared-qcow.xml b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-shared-qcow.xml
new file mode 100644
index 000000000..ca88a944b
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-shared-qcow.xml
@@ -0,0 +1,28 @@
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>219136</memory>
+ <currentMemory unit='KiB'>219136</currentMemory>
+ <vcpu placement='static'>1</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu-system-i686</emulator>
+ <disk type='block' device='disk'>
+ <driver name='qemu' type='qcow2'/>
+ <source dev='/dev/HostVG/QEMUGuest1'/>
+ <target dev='hda' bus='ide'/>
+ <shareable/>
+ <address type='drive' controller='0' bus='0' target='0' unit='0'/>
+ </disk>
+ <controller type='usb' index='0'/>
+ <controller type='ide' index='0'/>
+ <memballoon model='virtio'/>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-shared.args b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-shared.args
index 502157bf8..326fde1b3 100644
--- a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-shared.args
+++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-shared.args
@@ -19,7 +19,7 @@ server,nowait \
-no-acpi \
-boot c \
-usb \
--drive file=/dev/HostVG/QEMUGuest1,format=qcow2,if=none,id=drive-ide0-0-0,\
+-drive file=/dev/HostVG/QEMUGuest1,format=raw,if=none,id=drive-ide0-0-0,\
serial=XYZXYZXYZYXXYZYZYXYZY,cache=none \
-device ide-drive,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0 \
-drive file=/dev/HostVG/QEMUGuest2,format=raw,if=none,media=cdrom,\
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-shared.xml b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-shared.xml
index 9f7472378..677c2b0b7 100644
--- a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-shared.xml
+++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-shared.xml
@@ -15,7 +15,7 @@
<devices>
<emulator>/usr/bin/qemu-system-i686</emulator>
<disk type='block' device='disk'>
- <driver name='qemu' type='qcow2'/>
+ <driver name='qemu' type='raw'/>
<source dev='/dev/HostVG/QEMUGuest1'/>
<target dev='hda' bus='ide'/>
<shareable/>
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 18f06e5aa..93f892229 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -895,6 +895,7 @@ mymain(void)
QEMU_CAPS_DRIVE_BOOT);
DO_TEST("disk-drive-shared",
QEMU_CAPS_DRIVE_SERIAL);
+ DO_TEST_PARSE_ERROR("disk-drive-shared-qcow", NONE);
DO_TEST("disk-drive-error-policy-stop",
QEMU_CAPS_MONITOR_JSON);
DO_TEST("disk-drive-error-policy-enospace",
@@ -1,63 +0,0 @@
From: Peter Krempa <pkrempa@redhat.com>
Date: Wed, 15 Nov 2017 13:41:01 +0100
Subject: [PATCH] qemu: snapshot: Disallow snapshot of unsupported shared disks
Creating a snapshot would introduce a possibly unsupported member for
sharing into the backing chain. Add a check to prevent that from
happening.
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1511480
(cherry picked from commit 9b2fbfa6f6b535b9f41a7503531d43d86d7a8868)
---
src/qemu/qemu_driver.c | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 57f0c2bf4..91119a494 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -13792,6 +13792,24 @@ qemuDomainSnapshotCreateActiveInternal(virConnectPtr conn,
}
+static int
+qemuDomainSnapshotPrepareDiskShared(virDomainSnapshotDiskDefPtr snapdisk,
+ virDomainDiskDefPtr domdisk)
+{
+ if (!domdisk->src->shared || domdisk->src->readonly)
+ return 0;
+
+ if (!qemuBlockStorageSourceSupportsConcurrentAccess(snapdisk->src)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("shared access for disk '%s' requires use of "
+ "supported storage format"), domdisk->dst);
+ return -1;
+ }
+
+ return 0;
+}
+
+
static int
qemuDomainSnapshotPrepareDiskExternalInactive(virDomainSnapshotDiskDefPtr snapdisk,
virDomainDiskDefPtr domdisk)
@@ -13853,6 +13871,9 @@ qemuDomainSnapshotPrepareDiskExternalInactive(virDomainSnapshotDiskDefPtr snapdi
return -1;
}
+ if (qemuDomainSnapshotPrepareDiskShared(snapdisk, domdisk) < 0)
+ return -1;
+
return 0;
}
@@ -13911,6 +13932,9 @@ qemuDomainSnapshotPrepareDiskExternalActive(virDomainSnapshotDiskDefPtr snapdisk
return -1;
}
+ if (qemuDomainSnapshotPrepareDiskShared(snapdisk, domdisk) < 0)
+ return -1;
+
return 0;
}
@@ -1,34 +0,0 @@
From: Peter Krempa <pkrempa@redhat.com>
Date: Wed, 15 Nov 2017 14:33:11 +0100
Subject: [PATCH] qemu: Disallow pivot of shared disks to unsupported storage
Pivoting to a unsupported storage type might break the assumption that
shared disks will not corrupt metadata.
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1511480
(cherry picked from commit 2b41c86294786c07f53afa633fe3dce703debc3c)
---
src/qemu/qemu_driver.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 91119a494..208ccc9bc 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -16325,6 +16325,16 @@ qemuDomainBlockPivot(virQEMUDriverPtr driver,
goto cleanup;
}
+ /* When pivoting to a shareable disk we need to make sure that the disk can
+ * be safely shared, since block copy might have changed the format. */
+ if (disk->src->shared && !disk->src->readonly &&
+ !qemuBlockStorageSourceSupportsConcurrentAccess(disk->mirror)) {
+ virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
+ _("can't pivot a shared disk to a storage volume not "
+ "supporting sharing"));
+ goto cleanup;
+ }
+
/* For active commit, the mirror is part of the already labeled
* chain. For blockcopy, we previously labeled only the top-level
* image; but if the user is reusing an external image that
@@ -1,126 +0,0 @@
From: Peter Krempa <pkrempa@redhat.com>
Date: Wed, 15 Nov 2017 15:02:58 +0100
Subject: [PATCH] qemu: caps: Add capability for 'share-rw' disk option
'share-rw' for the disk device configures qemu to allow concurrent
access to the backing storage.
The capability is checked in various supported disk frontend buses since
it does not make sense to partially backport it.
(cherry picked from commit 860a3c4bea1d24773d8a495f213d5de3ac48a462)
---
src/qemu/qemu_capabilities.c | 14 ++++++++++++++
src/qemu/qemu_capabilities.h | 10 ++++++++++
tests/qemucapabilitiesdata/caps_2.9.0.ppc64le.xml | 1 +
tests/qemucapabilitiesdata/caps_2.9.0.s390x.xml | 1 +
tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml | 1 +
5 files changed, 27 insertions(+)
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index e7ea6f47c..2de84715e 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -439,6 +439,16 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST,
"virtio-net.tx_queue_size",
"chardev-reconnect",
"virtio-gpu.max_outputs",
+
+ /* 270 */
+ "vxhs",
+ "virtio-blk.num-queues",
+ "machine.pseries.resize-hpt",
+ "vmcoreinfo",
+ "spapr-vty",
+
+ /* 275 */
+ "disk-share-rw",
);
@@ -1702,6 +1712,7 @@ static struct virQEMUCapsStringFlags virQEMUCapsObjectPropsVirtioBlk[] = {
{ "event_idx", QEMU_CAPS_VIRTIO_BLK_EVENT_IDX },
{ "scsi", QEMU_CAPS_VIRTIO_BLK_SCSI },
{ "logical_block_size", QEMU_CAPS_BLOCKIO },
+ { "share-rw", QEMU_CAPS_DISK_SHARE_RW },
};
static struct virQEMUCapsStringFlags virQEMUCapsObjectPropsVirtioNet[] = {
@@ -1732,10 +1743,12 @@ static struct virQEMUCapsStringFlags virQEMUCapsObjectPropsVfioPCI[] = {
static struct virQEMUCapsStringFlags virQEMUCapsObjectPropsSCSIDisk[] = {
{ "channel", QEMU_CAPS_SCSI_DISK_CHANNEL },
{ "wwn", QEMU_CAPS_SCSI_DISK_WWN },
+ { "share-rw", QEMU_CAPS_DISK_SHARE_RW },
};
static struct virQEMUCapsStringFlags virQEMUCapsObjectPropsIDEDrive[] = {
{ "wwn", QEMU_CAPS_IDE_DRIVE_WWN },
+ { "share-rw", QEMU_CAPS_DISK_SHARE_RW },
};
static struct virQEMUCapsStringFlags virQEMUCapsObjectPropsPiix4PM[] = {
@@ -1766,6 +1779,7 @@ static struct virQEMUCapsStringFlags virQEMUCapsObjectPropsQ35PCIHost[] = {
static struct virQEMUCapsStringFlags virQEMUCapsObjectPropsUSBStorage[] = {
{ "removable", QEMU_CAPS_USB_STORAGE_REMOVABLE },
+ { "share-rw", QEMU_CAPS_DISK_SHARE_RW },
};
static struct virQEMUCapsStringFlags virQEMUCapsObjectPropsKVMPit[] = {
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index f32687d4a..9c92d6b46 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -426,6 +426,16 @@ typedef enum {
QEMU_CAPS_CHARDEV_RECONNECT, /* -chardev reconnect */
QEMU_CAPS_VIRTIO_GPU_MAX_OUTPUTS, /* -device virtio-(vga|gpu-*),max-outputs= */
+ /* 270 */
+ QEMU_CAPS_VXHS, /* -drive file.driver=vxhs via query-qmp-schema */
+ QEMU_CAPS_VIRTIO_BLK_NUM_QUEUES, /* virtio-blk-*.num-queues */
+ QEMU_CAPS_MACHINE_PSERIES_RESIZE_HPT, /* -machine pseries,resize-hpt */
+ QEMU_CAPS_DEVICE_VMCOREINFO, /* -device vmcoreinfo */
+ QEMU_CAPS_DEVICE_SPAPR_VTY, /* -device spapr-vty */
+
+ /* 275 */
+ QEMU_CAPS_DISK_SHARE_RW, /* share-rw=on for concurrent disk access */
+
QEMU_CAPS_LAST /* this must always be the last item */
} virQEMUCapsFlags;
diff --git a/tests/qemucapabilitiesdata/caps_2.9.0.ppc64le.xml b/tests/qemucapabilitiesdata/caps_2.9.0.ppc64le.xml
index a373a6db6..9551907c6 100644
--- a/tests/qemucapabilitiesdata/caps_2.9.0.ppc64le.xml
+++ b/tests/qemucapabilitiesdata/caps_2.9.0.ppc64le.xml
@@ -172,6 +172,7 @@
<flag name='vnc-multi-servers'/>
<flag name='chardev-reconnect'/>
<flag name='virtio-gpu.max_outputs'/>
+ <flag name='disk-share-rw'/>
<version>2009000</version>
<kvmVersion>0</kvmVersion>
<package> (v2.9.0)</package>
diff --git a/tests/qemucapabilitiesdata/caps_2.9.0.s390x.xml b/tests/qemucapabilitiesdata/caps_2.9.0.s390x.xml
index e80782cfb..0a6fbd077 100644
--- a/tests/qemucapabilitiesdata/caps_2.9.0.s390x.xml
+++ b/tests/qemucapabilitiesdata/caps_2.9.0.s390x.xml
@@ -137,6 +137,7 @@
<flag name='vnc-multi-servers'/>
<flag name='chardev-reconnect'/>
<flag name='virtio-gpu.max_outputs'/>
+ <flag name='disk-share-rw'/>
<version>2009000</version>
<kvmVersion>0</kvmVersion>
<package></package>
diff --git a/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml
index 3641d0332..1294ebdb3 100644
--- a/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml
+++ b/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml
@@ -220,6 +220,7 @@
<flag name='vnc-multi-servers'/>
<flag name='chardev-reconnect'/>
<flag name='virtio-gpu.max_outputs'/>
+ <flag name='disk-share-rw'/>
<version>2009000</version>
<kvmVersion>0</kvmVersion>
<package> (v2.9.0)</package>
@@ -1,133 +0,0 @@
From: Peter Krempa <pkrempa@redhat.com>
Date: Wed, 15 Nov 2017 15:21:14 +0100
Subject: [PATCH] qemu: command: Mark <shared/> disks as such in qemu
Qemu has now an internal mechanism for locking images to fix specific
cases of disk corruption. This requires libvirt to mark the image as
shared so that qemu lifts certain restrictions.
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1378242
(cherry picked from commit 28907b0043fbf71085a798372ab9c816ba043b93)
---
src/qemu/qemu_command.c | 4 +++
.../qemuxml2argv-disk-drive-shared-locking.args | 32 +++++++++++++++++
.../qemuxml2argv-disk-drive-shared-locking.xml | 42 ++++++++++++++++++++++
tests/qemuxml2argvtest.c | 2 ++
4 files changed, 80 insertions(+)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-shared-locking.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-shared-locking.xml
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index ae78cd17e..883525752 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -2075,6 +2075,10 @@ qemuBuildDriveDevStr(const virDomainDef *def,
goto error;
}
+ if (disk->src->shared &&
+ virQEMUCapsGet(qemuCaps, QEMU_CAPS_DISK_SHARE_RW))
+ virBufferAddLit(&opt, ",share-rw=on");
+
if (!(drivealias = qemuAliasFromDisk(disk)))
goto error;
virBufferAsprintf(&opt, ",drive=%s,id=%s", drivealias, disk->info.alias);
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-shared-locking.args b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-shared-locking.args
new file mode 100644
index 000000000..cdf17f26d
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-shared-locking.args
@@ -0,0 +1,32 @@
+LC_ALL=C \
+PATH=/bin \
+HOME=/home/test \
+USER=test \
+LOGNAME=test \
+QEMU_AUDIO_DRV=none \
+/usr/bin/qemu-system-i686 \
+-name QEMUGuest1 \
+-S \
+-M pc \
+-m 214 \
+-smp 1,sockets=1,cores=1,threads=1 \
+-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
+-nographic \
+-nodefaults \
+-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-QEMUGuest1/monitor.sock,\
+server,nowait \
+-mon chardev=charmonitor,id=monitor,mode=readline \
+-no-acpi \
+-boot c \
+-device virtio-scsi-pci,id=scsi0,bus=pci.0,addr=0x3 \
+-usb \
+-drive file=/dev/ide,format=raw,if=none,id=drive-ide0-0-0,cache=none \
+-device ide-drive,bus=ide.0,unit=0,share-rw=on,drive=drive-ide0-0-0,\
+id=ide0-0-0 \
+-drive file=/dev/scsi,format=raw,if=none,id=drive-scsi0-0-0-0,cache=none \
+-device scsi-disk,bus=scsi0.0,channel=0,scsi-id=0,lun=0,share-rw=on,\
+drive=drive-scsi0-0-0-0,id=scsi0-0-0-0 \
+-drive file=/dev/virtio,format=raw,if=none,id=drive-virtio-disk0,cache=none \
+-device virtio-blk-pci,bus=pci.0,addr=0x4,share-rw=on,drive=drive-virtio-disk0,\
+id=virtio-disk0 \
+-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x5
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-shared-locking.xml b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-shared-locking.xml
new file mode 100644
index 000000000..dd48857a3
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-shared-locking.xml
@@ -0,0 +1,42 @@
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>219136</memory>
+ <currentMemory unit='KiB'>219136</currentMemory>
+ <vcpu placement='static'>1</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu-system-i686</emulator>
+ <disk type='block' device='disk'>
+ <driver name='qemu' type='raw'/>
+ <source dev='/dev/ide'/>
+ <target dev='hda' bus='ide'/>
+ <shareable/>
+ <address type='drive' controller='0' bus='0' target='0' unit='0'/>
+ </disk>
+ <disk type='block' device='disk'>
+ <driver name='qemu' type='raw'/>
+ <source dev='/dev/scsi'/>
+ <target dev='sda' bus='scsi'/>
+ <shareable/>
+ <address type='drive' controller='0' bus='0' target='0' unit='0'/>
+ </disk>
+ <disk type='block' device='disk'>
+ <driver name='qemu' type='raw'/>
+ <source dev='/dev/virtio'/>
+ <target dev='vda' bus='virtio'/>
+ <shareable/>
+ </disk>
+ <controller type='usb' index='0'/>
+ <controller type='ide' index='0'/>
+ <controller type='scsi' index='0' model='virtio-scsi'/>
+ <memballoon model='virtio'/>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 93f892229..9585fdb70 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -896,6 +896,8 @@ mymain(void)
DO_TEST("disk-drive-shared",
QEMU_CAPS_DRIVE_SERIAL);
DO_TEST_PARSE_ERROR("disk-drive-shared-qcow", NONE);
+ DO_TEST("disk-drive-shared-locking",
+ QEMU_CAPS_VIRTIO_SCSI, QEMU_CAPS_DISK_SHARE_RW);
DO_TEST("disk-drive-error-policy-stop",
QEMU_CAPS_MONITOR_JSON);
DO_TEST("disk-drive-error-policy-enospace",
@@ -1,36 +0,0 @@
From: Peter Krempa <pkrempa@redhat.com>
Date: Wed, 20 Dec 2017 12:58:36 +0100
Subject: [PATCH] util: probe: Add quiet versions of the "PROBE" macro
PROBE macro adds a logging entry, when used in places seeing a lot of
traffic this can cause a significant slowdown.
(cherry picked from commit f06e488d5484031a76e7ed231c8fef8fa1181d2c)
---
src/util/virprobe.h | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/src/util/virprobe.h b/src/util/virprobe.h
index 7565954af..bd8c32964 100644
--- a/src/util/virprobe.h
+++ b/src/util/virprobe.h
@@ -90,11 +90,19 @@
PROBE_EXPAND(LIBVIRT_ ## NAME, \
VIR_ADD_CASTS(__VA_ARGS__)); \
}
+
+# define PROBE_QUIET(NAME, FMT, ...) \
+ if (LIBVIRT_ ## NAME ## _ENABLED()) { \
+ PROBE_EXPAND(LIBVIRT_ ## NAME, \
+ VIR_ADD_CASTS(__VA_ARGS__)); \
+ }
# else
# define PROBE(NAME, FMT, ...) \
VIR_INFO_INT(&virLogSelf, \
__FILE__, __LINE__, __func__, \
#NAME ": " FMT, __VA_ARGS__);
+
+# define PROBE_QUIET(NAME, FMT, ...)
# endif
#endif /* __VIR_PROBE_H__ */
@@ -1,49 +0,0 @@
From: Peter Krempa <pkrempa@redhat.com>
Date: Wed, 20 Dec 2017 13:09:07 +0100
Subject: [PATCH] qemu: monitor: Decrease logging verbosity
The PROBE macro used in qemuMonitorIOProcess and the VIR_DEBUG message
in qemuMonitorJSONIOProcess create a lot of logging churn when debug
logging is enabled during monitor communication.
The messages logged from the PROBE macro are rather useless since they
are reporting the partial state of receiving the reply from qemu. The
actual full reply is still logged in qemuMonitorJSONIOProcessLine once
the full message is received.
(cherry picked from commit f10bb3347b43d900ff361cda5fe1996782284991)
---
src/qemu/qemu_monitor.c | 4 ++--
src/qemu/qemu_monitor_json.c | 3 +++
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index 19082d8bf..3def28852 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -434,8 +434,8 @@ qemuMonitorIOProcess(qemuMonitorPtr mon)
# endif
#endif
- PROBE(QEMU_MONITOR_IO_PROCESS,
- "mon=%p buf=%s len=%zu", mon, mon->buffer, mon->bufferOffset);
+ PROBE_QUIET(QEMU_MONITOR_IO_PROCESS, "mon=%p buf=%s len=%zu",
+ mon, mon->buffer, mon->bufferOffset);
if (mon->json)
len = qemuMonitorJSONIOProcess(mon,
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index df5fb7c8f..461aae089 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -259,7 +259,10 @@ int qemuMonitorJSONIOProcess(qemuMonitorPtr mon,
}
}
+#if DEBUG_IO
VIR_DEBUG("Total used %d bytes out of %zd available in buffer", used, len);
+#endif
+
return used;
}
@@ -1,63 +0,0 @@
From: Lubomir Rintel <lkundrak@v3.sk>
Date: Sat, 27 Jan 2018 23:43:58 +0100
Subject: [PATCH] virlog: determine the hostname on startup CVE-2018-6764
At later point it might not be possible or even safe to use getaddrinfo(). It
can in turn result in a load of NSS module.
Notably, on a LXC container startup we may find ourselves with the guest
filesystem already having replaced the host one. Loading a NSS module
from the guest tree would allow a malicous guest to escape the
confinement of its container environment because libvirt will not yet
have locked it down.
(cherry picked from commit 759b4d1b0fe5f4d84d98b99153dfa7ac289dd167)
---
src/util/virlog.c | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/src/util/virlog.c b/src/util/virlog.c
index d45a451a7..05e0e199e 100644
--- a/src/util/virlog.c
+++ b/src/util/virlog.c
@@ -64,6 +64,7 @@
VIR_LOG_INIT("util.log");
static regex_t *virLogRegex;
+static char *virLogHostname;
#define VIR_LOG_DATE_REGEX "[0-9]{4}-[0-9]{2}-[0-9]{2}"
@@ -271,6 +272,12 @@ virLogOnceInit(void)
VIR_FREE(virLogRegex);
}
+ /* We get and remember the hostname early, because at later time
+ * it might not be possible to load NSS modules via getaddrinfo()
+ * (e.g. at container startup the host filesystem will not be
+ * accessible anymore. */
+ virLogHostname = virGetHostnameQuiet();
+
virLogUnlock();
return 0;
}
@@ -466,17 +473,14 @@ static int
virLogHostnameString(char **rawmsg,
char **msg)
{
- char *hostname = virGetHostnameQuiet();
char *hoststr;
- if (!hostname)
+ if (!virLogHostname)
return -1;
- if (virAsprintfQuiet(&hoststr, "hostname: %s", hostname) < 0) {
- VIR_FREE(hostname);
+ if (virAsprintfQuiet(&hoststr, "hostname: %s", virLogHostname) < 0) {
return -1;
}
- VIR_FREE(hostname);
if (virLogFormatString(msg, 0, NULL, VIR_LOG_INFO, hoststr) < 0) {
VIR_FREE(hoststr);
-27
View File
@@ -1,27 +0,0 @@
From: Andrea Bolognani <abologna@redhat.com>
Date: Wed, 7 Feb 2018 14:39:18 +0100
Subject: [PATCH] util: Fix syntax-check
Broken by 759b4d1b0fe5f4d84d98b99153dfa7ac289dd167.
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
(cherry picked from commit 6ce3acc129bfdbe7fd02bcb8bbe8af6d13903684)
---
src/util/virlog.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/util/virlog.c b/src/util/virlog.c
index 05e0e199e..056b53cda 100644
--- a/src/util/virlog.c
+++ b/src/util/virlog.c
@@ -478,9 +478,8 @@ virLogHostnameString(char **rawmsg,
if (!virLogHostname)
return -1;
- if (virAsprintfQuiet(&hoststr, "hostname: %s", virLogHostname) < 0) {
+ if (virAsprintfQuiet(&hoststr, "hostname: %s", virLogHostname) < 0)
return -1;
- }
if (virLogFormatString(msg, 0, NULL, VIR_LOG_INFO, hoststr) < 0) {
VIR_FREE(hoststr);
@@ -1,121 +0,0 @@
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
Date: Mon, 12 Feb 2018 10:03:08 +0000
Subject: [PATCH] log: fix deadlock obtaining hostname (related CVE-2018-6764)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The fix for CVE-2018-6764 introduced a potential deadlock scenario
that gets triggered by the NSS module when virGetHostname() calls
getaddrinfo to resolve the hostname:
#0 0x00007f6e714b57e7 in futex_wait
#1 futex_wait_simple
#2 __pthread_once_slow
#3 0x00007f6e71d16e7d in virOnce
#4 0x00007f6e71d0997c in virLogInitialize
#5 0x00007f6e71d0a09a in virLogVMessage
#6 0x00007f6e71d09ffd in virLogMessage
#7 0x00007f6e71d0db22 in virObjectNew
#8 0x00007f6e71d0dbf1 in virObjectLockableNew
#9 0x00007f6e71d0d3e5 in virMacMapNew
#10 0x00007f6e71cdc50a in findLease
#11 0x00007f6e71cdcc56 in _nss_libvirt_gethostbyname4_r
#12 0x00007f6e724631fc in gaih_inet
#13 0x00007f6e72464697 in __GI_getaddrinfo
#14 0x00007f6e71d19e81 in virGetHostnameImpl
#15 0x00007f6e71d1a057 in virGetHostnameQuiet
#16 0x00007f6e71d09936 in virLogOnceInit
#17 0x00007f6e71d09952 in virLogOnce
#18 0x00007f6e714b5829 in __pthread_once_slow
#19 0x00007f6e71d16e7d in virOnce
#20 0x00007f6e71d0997c in virLogInitialize
#21 0x00007f6e71d0a09a in virLogVMessage
#22 0x00007f6e71d09ffd in virLogMessage
#23 0x00007f6e71d0db22 in virObjectNew
#24 0x00007f6e71d0dbf1 in virObjectLockableNew
#25 0x00007f6e71d0d3e5 in virMacMapNew
#26 0x00007f6e71cdc50a in findLease
#27 0x00007f6e71cdc839 in _nss_libvirt_gethostbyname3_r
#28 0x00007f6e71cdc724 in _nss_libvirt_gethostbyname2_r
#29 0x00007f6e7248f72f in __gethostbyname2_r
#30 0x00007f6e7248f494 in gethostbyname2
#31 0x000056348c30c36d in hosts_keys
#32 0x000056348c30b7d2 in main
Fortunately the extra stuff virGetHostname does is totally irrelevant to
the needs of the logging code, so we can just inline a call to the
native hostname() syscall directly.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
(cherry picked from commit c2dc6698c88fb591639e542c8ecb0076c54f3dfb)
---
cfg.mk | 2 +-
src/util/virlog.c | 20 ++++++++++++++------
2 files changed, 15 insertions(+), 7 deletions(-)
diff --git a/cfg.mk b/cfg.mk
index 56cb14bd9..a4131592c 100644
--- a/cfg.mk
+++ b/cfg.mk
@@ -1158,7 +1158,7 @@ _src2=src/(util/vircommand|libvirt|lxc/lxc_controller|locking/lock_daemon|loggin
exclude_file_name_regexp--sc_prohibit_fork_wrappers = \
(^($(_src2)|tests/testutils|daemon/libvirtd)\.c$$)
-exclude_file_name_regexp--sc_prohibit_gethostname = ^src/util/virutil\.c$$
+exclude_file_name_regexp--sc_prohibit_gethostname = ^src/util/vir(util|log)\.c$$
exclude_file_name_regexp--sc_prohibit_internal_functions = \
^src/(util/(viralloc|virutil|virfile)\.[hc]|esx/esx_vi\.c)$$
diff --git a/src/util/virlog.c b/src/util/virlog.c
index 056b53cda..f76fc2caf 100644
--- a/src/util/virlog.c
+++ b/src/util/virlog.c
@@ -64,7 +64,7 @@
VIR_LOG_INIT("util.log");
static regex_t *virLogRegex;
-static char *virLogHostname;
+static char virLogHostname[HOST_NAME_MAX+1];
#define VIR_LOG_DATE_REGEX "[0-9]{4}-[0-9]{2}-[0-9]{2}"
@@ -261,6 +261,8 @@ virLogPriorityString(virLogPriority lvl)
static int
virLogOnceInit(void)
{
+ int r;
+
if (virMutexInit(&virLogMutex) < 0)
return -1;
@@ -275,8 +277,17 @@ virLogOnceInit(void)
/* We get and remember the hostname early, because at later time
* it might not be possible to load NSS modules via getaddrinfo()
* (e.g. at container startup the host filesystem will not be
- * accessible anymore. */
- virLogHostname = virGetHostnameQuiet();
+ * accessible anymore.
+ * Must not use virGetHostname though as that causes re-entrancy
+ * problems if it triggers logging codepaths
+ */
+ r = gethostname(virLogHostname, sizeof(virLogHostname));
+ if (r == -1) {
+ ignore_value(virStrcpy(virLogHostname,
+ "(unknown)", sizeof(virLogHostname)));
+ } else {
+ NUL_TERMINATE(virLogHostname);
+ }
virLogUnlock();
return 0;
@@ -475,9 +486,6 @@ virLogHostnameString(char **rawmsg,
{
char *hoststr;
- if (!virLogHostname)
- return -1;
-
if (virAsprintfQuiet(&hoststr, "hostname: %s", virLogHostname) < 0)
return -1;
@@ -1,59 +0,0 @@
From: Michal Privoznik <mprivozn@redhat.com>
Date: Thu, 4 Jan 2018 11:11:53 +0100
Subject: [PATCH] qemuDomainAttachDeviceMknodHelper: Remove symlink before
creating it
https://bugzilla.redhat.com/show_bug.cgi?id=1528502
So imagine you have /dev/blah symlink which points to /dev/sda.
You attach /dev/blah as disk to your domain. Libvirt correctly
creates the /dev/blah -> /dev/sda symlink in the qemu namespace.
However, then you detach the disk, change the symlink so that it
points to /dev/sdb and tries to attach the disk again. This time,
however, the attach fails (well, qemu attaches wrong disk)
because the code assumes that symlinks don't change. Well they
do.
This is inspired by test fix written by Eduardo Habkost.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Andrea Bolognani <abologna@redhat.com>
(cherry picked from commit db98e7f67ea0d7699410f514f01947cef5128a6c)
---
src/qemu/qemu_domain.c | 22 ++++++++++++++++------
1 file changed, 16 insertions(+), 6 deletions(-)
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 42d17c1b0..e0f4aaafa 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -8864,13 +8864,23 @@ qemuDomainAttachDeviceMknodHelper(pid_t pid ATTRIBUTE_UNUSED,
if (isLink) {
VIR_DEBUG("Creating symlink %s -> %s", data->file, data->target);
+
+ /* First, unlink the symlink target. Symlinks change and
+ * therefore we have no guarantees that pre-existing
+ * symlink is still valid. */
+ if (unlink(data->file) < 0 &&
+ errno != ENOENT) {
+ virReportSystemError(errno,
+ _("Unable to remove symlink %s"),
+ data->file);
+ goto cleanup;
+ }
+
if (symlink(data->target, data->file) < 0) {
- if (errno != EEXIST) {
- virReportSystemError(errno,
- _("Unable to create symlink %s"),
- data->target);
- goto cleanup;
- }
+ virReportSystemError(errno,
+ _("Unable to create symlink %s (pointing to %s)"),
+ data->file, data->target);
+ goto cleanup;
} else {
delDevice = true;
}
@@ -1,110 +0,0 @@
From ce5aebeacd10a1c15cb3ee46a59c8b5ff235589e Mon Sep 17 00:00:00 2001
Message-Id: <ce5aebeacd10a1c15cb3ee46a59c8b5ff235589e.1530632895.git.crobinso@redhat.com>
From: Laine Stump <laine@laine.org>
Date: Wed, 25 Apr 2018 17:12:03 -0400
Subject: [PATCH] nwfilter: increase pcap buffer size to be compatible with
TPACKET_V3
When an nwfilter rule sets the parameter CTRL_IP_LEARNING to "dhcp",
this turns on the "dhcpsnoop" thread, which uses libpcap to monitor
traffic on the domain's tap device and extract the IP address from the
DHCP response.
If libpcap on the host is built with HAVE_TPACKET3 defined (to enable
support for TPACKET_V3), the dhcpsnoop code's initialization of the
libpcap socket would fail with the following error:
virNWFilterSnoopDHCPOpen:1134 : internal error: pcap_setfilter: can't remove kernel filter: Bad file descriptor
It turns out that this was because TPACKET_V3 requires a larger buffer
size than libvirt was setting (we were setting it to 128k). Changing
the buffer size to 256k eliminates the error, and the dhcpsnoop thread
once again works properly.
A fuller explanation of why TPACKET_V3 requires such a large buffer,
for future git spelunkers:
libpcap calls setsockopt(... SOL_PACKET, PACKET_RX_RING...) to setup a
ring buffer for receiving packets; two of the attributes sent to this
API are called tp_frame_size, and tp_frame_nr. If libpcap was built
with HAVE_TPACKET3 defined, tp_trame_size is set to MAXIMUM_SNAPLEN
(defined in libpcap sources as 262144) and tp_frame_nr is set to:
[the buffer size we set, i.e. PCAP_BUFFERSIZE i.e. 262144] / tp_frame_size.
So if PCAP_BUFFERSIZE < MAXIMUM_SNAPLEN, then tp_frame_nr (the number
of frames in the ring buffer) is 0, which is nonsensical. This same
value is later used as a multiplier to determine the size for a call
to malloc() (which would also fail).
(NB: if HAVE_TPACKET3 is *not* defined, then tp_frame_size is set to
the snaplen set by the user (in our case 576) plus a small amount to
account for ethernet headers, so 256k is far more than adequate)
Since the TPACKET_V3 code in libpcap actually reads multiple packets
into each frame, it's not a problem to have only a single frame
(especially when we are monitoring such infrequent traffic), so it's
okay to set this relatively small buffer size (in comparison to the
default, which is 2MB), which is important since every guest using
dhcp snooping in a nwfilter rule will hold 2 of these buffers for the
entire life of the guest.
Thanks to Christian Ehrhardt for discovering that buffer size was the
problem (this was not at all obvious from the error that was logged!)
Resolves: https://bugzilla.redhat.com/1547237
Fixes: https://bugs.launchpad.net/libvirt/+bug/1758037
Signed-off-by: Laine Stump <laine@laine.org>
Reviewed-by: Christian Ehrhardt <christian.ehrhardt@canonical.com> (V1)
Reviewed-by: John Ferlan <jferlan@redhat.com>
Tested-by: Christian Ehrhardt <christian.ehrhardt@canonical.com>
Signed-off-by: Cole Robinson <crobinso@redhat.com>
---
src/nwfilter/nwfilter_dhcpsnoop.c | 22 +++++++++++++++++++---
1 file changed, 19 insertions(+), 3 deletions(-)
diff --git a/src/nwfilter/nwfilter_dhcpsnoop.c b/src/nwfilter/nwfilter_dhcpsnoop.c
index 6069e70460..50cfb944a2 100644
--- a/src/nwfilter/nwfilter_dhcpsnoop.c
+++ b/src/nwfilter/nwfilter_dhcpsnoop.c
@@ -256,10 +256,21 @@ struct _virNWFilterDHCPDecodeJob {
# define DHCP_BURST_INTERVAL_S 10 /* sec */
/*
- * libpcap 1.5 requires a 128kb buffer
- * 128 kb is bigger than (DHCP_PKT_BURST * PCAP_PBUFSIZE / 2)
+ * NB: Any libpcap built with HAVE_TPACKET3 will require
+ * PCAP_BUFFERSIZE to be at least 262144 (although
+ * pcap_set_buffer_size() with a lower value will succeed, and the
+ * error will only show up later when pcap_setfilter() is called).
+ *
+ * It is possible that in the future libpcap could increase the
+ * minimum size even further, but due to the fact that each guest
+ * using dhcp snooping keeps 2 pcap sockets open (and thus 2 buffers
+ * allocated) for the life of the guest, we want to minimize the
+ * length of the buffer, so instead of leaving it at the default size
+ * (2MB), we are setting it to the minimum viable size and including
+ * this clue in the source to help quickly resolve the problem when/if
+ * it reoccurs.
*/
-# define PCAP_BUFFERSIZE (128 * 1024)
+# define PCAP_BUFFERSIZE (256 * 1024)
# define MAX_QUEUED_JOBS (DHCP_PKT_BURST + 2 * DHCP_PKT_RATE)
@@ -1114,6 +1125,11 @@ virNWFilterSnoopDHCPOpen(const char *ifname, virMacAddr *mac,
goto cleanup_nohandle;
}
+ /* IMPORTANT: If there is any failure of *any* pcap_* function
+ * during setup of the socket, look to the comment where
+ * PCAP_BUFFERSIZE is defined. It may be too small, even if the
+ * generated error doesn't imply that.
+ */
if (pcap_set_snaplen(handle, PCAP_PBUFSIZE) < 0 ||
pcap_set_buffer_size(handle, PCAP_BUFFERSIZE) < 0 ||
pcap_activate(handle) < 0) {
--
2.17.1
@@ -1,74 +0,0 @@
From e18672ce9a5fff383992fd6e842d1cbe85c141ea Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Tue, 12 Dec 2017 16:23:40 +0100
Subject: [PATCH 10/19] util: add virFileReadHeaderQuiet wrapper around
virFileReadHeaderFD
CVE-2017-5715
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
---
src/libvirt_private.syms | 1 +
src/util/virfile.c | 19 +++++++++++++++++++
src/util/virfile.h | 2 ++
3 files changed, 22 insertions(+)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index f30a04b145..29b73fa046 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1703,6 +1703,7 @@ virFileReadAll;
virFileReadAllQuiet;
virFileReadBufQuiet;
virFileReadHeaderFD;
+virFileReadHeaderQuiet;
virFileReadLimFD;
virFileReadLink;
virFileReadValueBitmap;
diff --git a/src/util/virfile.c b/src/util/virfile.c
index 2f28e83f44..269db995ff 100644
--- a/src/util/virfile.c
+++ b/src/util/virfile.c
@@ -1356,6 +1356,25 @@ virFileReadHeaderFD(int fd, int maxlen, char **buf)
}
+int
+virFileReadHeaderQuiet(const char *path,
+ int maxlen,
+ char **buf)
+{
+ int fd;
+ int len;
+
+ fd = open(path, O_RDONLY);
+ if (fd < 0)
+ return -1;
+
+ len = virFileReadHeaderFD(fd, maxlen, buf);
+ VIR_FORCE_CLOSE(fd);
+
+ return len;
+}
+
+
/* A wrapper around saferead_lim that maps a failure due to
exceeding the maximum size limitation to EOVERFLOW. */
int
diff --git a/src/util/virfile.h b/src/util/virfile.h
index 57ceb80721..657e7216fb 100644
--- a/src/util/virfile.h
+++ b/src/util/virfile.h
@@ -129,6 +129,8 @@ int virFileDeleteTree(const char *dir);
int virFileReadHeaderFD(int fd, int maxlen, char **buf)
ATTRIBUTE_RETURN_CHECK ATTRIBUTE_NONNULL(3);
+int virFileReadHeaderQuiet(const char *path, int maxlen, char **buf)
+ ATTRIBUTE_RETURN_CHECK ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3);
int virFileReadLimFD(int fd, int maxlen, char **buf)
ATTRIBUTE_RETURN_CHECK ATTRIBUTE_NONNULL(3);
int virFileReadAll(const char *path, int maxlen, char **buf)
--
2.17.0
@@ -1,36 +0,0 @@
From a84e70ad247da5d3ad13615efd70b91951392aa1 Mon Sep 17 00:00:00 2001
From: Jiri Denemark <jdenemar@redhat.com>
Date: Fri, 5 Jan 2018 17:43:03 +0100
Subject: [PATCH 12/19] cpu_x86: Copy CPU signature from ancestor
When specifying a new CPU model in cpu_map.xml as an extension to an
existing model, we forgot to copy the signature (family + model) from
the original CPU model.
We don't use this way of specifying CPU models, but it's still supported
and it becomes useful when someone wants to quickly hack up a CPU model
for testing or when creating additional variants of existing models to
help with fixing some spectral issues.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
Reviewed-by: Pavel Hrdina <phrdina@redhat.com>
(cherry picked from commit b427cf4831d0ea7aac9dd1a3aa7682478356a483)
---
src/cpu/cpu_x86.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
index 2864454211..3b7a6f95fe 100644
--- a/src/cpu/cpu_x86.c
+++ b/src/cpu/cpu_x86.c
@@ -1206,6 +1206,7 @@ x86ModelParse(xmlXPathContextPtr ctxt,
VIR_FREE(name);
model->vendor = ancestor->vendor;
+ model->signature = ancestor->signature;
if (x86DataCopy(&model->data, &ancestor->data) < 0)
goto error;
}
--
2.17.0
@@ -1,97 +0,0 @@
From de12d97c029d6644bb42afaa38410c4263bef41f Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Tue, 12 Dec 2017 16:23:41 +0100
Subject: [PATCH 13/19] util: introduce virHostCPUGetMicrocodeVersion
This new API reads host's CPU microcode version from /proc/cpuinfo.
Unfortunately, there is no other way of reading microcode version which
would be usable from both system and session daemon.
CVE-2017-5715
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
---
src/libvirt_private.syms | 1 +
src/util/virhostcpu.c | 43 ++++++++++++++++++++++++++++++++++++++++
src/util/virhostcpu.h | 2 ++
3 files changed, 46 insertions(+)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 29b73fa046..0ecd58a12c 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1811,6 +1811,7 @@ virHostCPUGetCount;
virHostCPUGetInfo;
virHostCPUGetKVMMaxVCPUs;
virHostCPUGetMap;
+virHostCPUGetMicrocodeVersion;
virHostCPUGetOnline;
virHostCPUGetOnlineBitmap;
virHostCPUGetPresentBitmap;
diff --git a/src/util/virhostcpu.c b/src/util/virhostcpu.c
index c485a97211..713fdec553 100644
--- a/src/util/virhostcpu.c
+++ b/src/util/virhostcpu.c
@@ -1206,3 +1206,46 @@ virHostCPUGetKVMMaxVCPUs(void)
return -1;
}
#endif /* HAVE_LINUX_KVM_H */
+
+
+#ifdef __linux__
+
+unsigned int
+virHostCPUGetMicrocodeVersion(void)
+{
+ char *outbuf = NULL;
+ char *cur;
+ unsigned int version = 0;
+
+ if (virFileReadHeaderQuiet(CPUINFO_PATH, 4096, &outbuf) < 0) {
+ char ebuf[1024];
+ VIR_DEBUG("Failed to read microcode version from %s: %s",
+ CPUINFO_PATH, virStrerror(errno, ebuf, sizeof(ebuf)));
+ return 0;
+ }
+
+ /* Account for format 'microcode : XXXX'*/
+ if (!(cur = strstr(outbuf, "microcode")) ||
+ !(cur = strchr(cur, ':')))
+ goto cleanup;
+ cur++;
+
+ /* Linux places the microcode revision in a 32-bit integer, so
+ * ui is fine for us too. */
+ if (virStrToLong_ui(cur, &cur, 0, &version) < 0)
+ goto cleanup;
+
+ cleanup:
+ VIR_FREE(outbuf);
+ return version;
+}
+
+#else
+
+unsigned int
+virHostCPUGetMicrocodeVersion(void)
+{
+ return 0;
+}
+
+#endif
diff --git a/src/util/virhostcpu.h b/src/util/virhostcpu.h
index 67033de842..f9f3359288 100644
--- a/src/util/virhostcpu.h
+++ b/src/util/virhostcpu.h
@@ -66,4 +66,6 @@ virBitmapPtr virHostCPUGetSiblingsList(unsigned int cpu);
int virHostCPUGetOnline(unsigned int cpu, bool *online);
+unsigned int virHostCPUGetMicrocodeVersion(void);
+
#endif /* __VIR_HOSTCPU_H__*/
--
2.17.0
@@ -1,51 +0,0 @@
From a0ad8c160ed81417e4d5b46adf3118df1b6b1b77 Mon Sep 17 00:00:00 2001
From: Jiri Denemark <jdenemar@redhat.com>
Date: Wed, 13 Dec 2017 22:30:31 +0100
Subject: [PATCH 14/19] cpu_x86: Rename virCPUx86MapInitialize
The function will be used to initialize internal data of the x86 CPU
driver (including the CPU map).
CVE-2017-5715
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
---
src/cpu/cpu_x86.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
index 3b7a6f95fe..0cb0dcacb3 100644
--- a/src/cpu/cpu_x86.c
+++ b/src/cpu/cpu_x86.c
@@ -153,8 +153,8 @@ struct _virCPUx86Map {
};
static virCPUx86MapPtr cpuMap;
-int virCPUx86MapOnceInit(void);
-VIR_ONCE_GLOBAL_INIT(virCPUx86Map);
+int virCPUx86DriverOnceInit(void);
+VIR_ONCE_GLOBAL_INIT(virCPUx86Driver);
typedef enum {
@@ -1387,7 +1387,7 @@ virCPUx86LoadMap(void)
int
-virCPUx86MapOnceInit(void)
+virCPUx86DriverOnceInit(void)
{
if (!(cpuMap = virCPUx86LoadMap()))
return -1;
@@ -1399,7 +1399,7 @@ virCPUx86MapOnceInit(void)
static virCPUx86MapPtr
virCPUx86GetMap(void)
{
- if (virCPUx86MapInitialize() < 0)
+ if (virCPUx86DriverInitialize() < 0)
return NULL;
return cpuMap;
--
2.17.0
@@ -1,133 +0,0 @@
From c628c42493170bfd70f30d9fb56d0067e6e4828a Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Tue, 19 Jun 2018 16:47:20 +0100
Subject: [PATCH 15/19] conf: include x86 microcode version in virsh
capabiltiies
A microcode update can cause the CPUID bits to change; an example
from the past was the update that disabled TSX on several Haswell and
Broadwell machines.
In order to track the x86 microcode version in the QEMU capabilities,
we have to fetch it and store it in the host CPU. This also makes the
version visible in "virsh capabilities", which is a nice side effect.
CVE-2017-5715
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
---
src/conf/cpu_conf.c | 14 ++++++++++++++
src/conf/cpu_conf.h | 1 +
src/cpu/cpu_x86.c | 9 +++++++++
3 files changed, 24 insertions(+)
diff --git a/src/conf/cpu_conf.c b/src/conf/cpu_conf.c
index c21d11d244..3f3c25320e 100644
--- a/src/conf/cpu_conf.c
+++ b/src/conf/cpu_conf.c
@@ -127,6 +127,7 @@ virCPUDefCopyModelFilter(virCPUDefPtr dst,
VIR_STRDUP(dst->vendor_id, src->vendor_id) < 0 ||
VIR_ALLOC_N(dst->features, src->nfeatures) < 0)
return -1;
+ dst->microcodeVersion = src->microcodeVersion;
dst->nfeatures_max = src->nfeatures;
dst->nfeatures = 0;
@@ -178,6 +179,7 @@ virCPUDefStealModel(virCPUDefPtr dst,
VIR_STEAL_PTR(dst->model, src->model);
VIR_STEAL_PTR(dst->features, src->features);
+ dst->microcodeVersion = src->microcodeVersion;
dst->nfeatures_max = src->nfeatures_max;
src->nfeatures_max = 0;
dst->nfeatures = src->nfeatures;
@@ -379,6 +381,14 @@ virCPUDefParseXML(xmlXPathContextPtr ctxt,
goto cleanup;
}
VIR_FREE(arch);
+
+ if (virXPathBoolean("boolean(./microcode[1]/@version)", ctxt) > 0 &&
+ virXPathUInt("string(./microcode[1]/@version)", ctxt,
+ &def->microcodeVersion) < 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("invalid microcode version"));
+ goto cleanup;
+ }
}
if (!(def->model = virXPathString("string(./model[1])", ctxt)) &&
@@ -723,6 +733,10 @@ virCPUDefFormatBuf(virBufferPtr buf,
if (formatModel && def->vendor)
virBufferEscapeString(buf, "<vendor>%s</vendor>\n", def->vendor);
+ if (def->type == VIR_CPU_TYPE_HOST && def->microcodeVersion)
+ virBufferAsprintf(buf, "<microcode version='%u'/>\n",
+ def->microcodeVersion);
+
if (def->sockets && def->cores && def->threads) {
virBufferAddLit(buf, "<topology");
virBufferAsprintf(buf, " sockets='%u'", def->sockets);
diff --git a/src/conf/cpu_conf.h b/src/conf/cpu_conf.h
index b44974f47e..a30ecf8681 100644
--- a/src/conf/cpu_conf.h
+++ b/src/conf/cpu_conf.h
@@ -133,6 +133,7 @@ struct _virCPUDef {
char *vendor_id; /* vendor id returned by CPUID in the guest */
int fallback; /* enum virCPUFallback */
char *vendor;
+ unsigned int microcodeVersion;
unsigned int sockets;
unsigned int cores;
unsigned int threads;
diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
index 0cb0dcacb3..41aaa61c35 100644
--- a/src/cpu/cpu_x86.c
+++ b/src/cpu/cpu_x86.c
@@ -33,6 +33,7 @@
#include "virbuffer.h"
#include "virendian.h"
#include "virstring.h"
+#include "virhostcpu.h"
#define VIR_FROM_THIS VIR_FROM_CPU
@@ -153,6 +154,8 @@ struct _virCPUx86Map {
};
static virCPUx86MapPtr cpuMap;
+static unsigned int microcodeVersion;
+
int virCPUx86DriverOnceInit(void);
VIR_ONCE_GLOBAL_INIT(virCPUx86Driver);
@@ -1392,6 +1395,8 @@ virCPUx86DriverOnceInit(void)
if (!(cpuMap = virCPUx86LoadMap()))
return -1;
+ microcodeVersion = virHostCPUGetMicrocodeVersion();
+
return 0;
}
@@ -2409,6 +2414,9 @@ virCPUx86GetHost(virCPUDefPtr cpu,
virCPUDataPtr cpuData = NULL;
int ret = -1;
+ if (virCPUx86DriverInitialize() < 0)
+ goto cleanup;
+
if (!(cpuData = virCPUDataNew(archs[0])))
goto cleanup;
@@ -2417,6 +2425,7 @@ virCPUx86GetHost(virCPUDefPtr cpu,
goto cleanup;
ret = x86DecodeCPUData(cpu, cpuData, models, nmodels, NULL);
+ cpu->microcodeVersion = microcodeVersion;
cleanup:
virCPUx86DataFree(cpuData);
--
2.17.0
@@ -1,535 +0,0 @@
From a31edb693bb79f1ad8931db284f1dbceae178f27 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Tue, 19 Jun 2018 16:50:02 +0100
Subject: [PATCH 16/19] qemu: capabilities: force update if the microcode
version does not match
A microcode update can cause the CPUID bits to change; an example
from the past was the update that disabled TSX on several Haswell
and Broadwell machines.
Therefore, place microcode version in the virQEMUCaps struct and
XML, and rebuild the cache if the versions do not match.
CVE-2017-5715
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
---
src/qemu/qemu_capabilities.c | 40 ++++++++++++++++++-
src/qemu/qemu_capabilities.h | 6 ++-
src/qemu/qemu_capspriv.h | 6 +++
src/qemu/qemu_driver.c | 9 ++++-
.../caps_1.2.2.x86_64.xml | 1 +
.../caps_1.3.1.x86_64.xml | 1 +
.../caps_1.4.2.x86_64.xml | 1 +
.../caps_1.5.3.x86_64.xml | 1 +
.../caps_1.6.0.x86_64.xml | 1 +
.../caps_1.7.0.x86_64.xml | 1 +
.../caps_2.1.1.x86_64.xml | 1 +
.../caps_2.4.0.x86_64.xml | 1 +
.../caps_2.5.0.x86_64.xml | 1 +
.../caps_2.6.0-gicv2.aarch64.xml | 1 +
.../caps_2.6.0-gicv3.aarch64.xml | 1 +
.../caps_2.6.0.ppc64le.xml | 1 +
.../caps_2.6.0.x86_64.xml | 1 +
.../qemucapabilitiesdata/caps_2.7.0.s390x.xml | 1 +
.../caps_2.7.0.x86_64.xml | 1 +
.../qemucapabilitiesdata/caps_2.8.0.s390x.xml | 1 +
.../caps_2.8.0.x86_64.xml | 1 +
.../caps_2.9.0.ppc64le.xml | 1 +
.../qemucapabilitiesdata/caps_2.9.0.s390x.xml | 1 +
.../caps_2.9.0.x86_64.xml | 1 +
tests/qemucapabilitiestest.c | 14 +++++--
tests/qemucapsprobe.c | 2 +-
tests/testutilsqemu.c | 2 +-
27 files changed, 89 insertions(+), 10 deletions(-)
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 2de84715ea..72b70ce750 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -500,6 +500,7 @@ struct _virQEMUCaps {
unsigned int version;
unsigned int kvmVersion;
unsigned int libvirtVersion;
+ unsigned int microcodeVersion;
char *package;
virArch arch;
@@ -2304,6 +2305,7 @@ virQEMUCapsPtr virQEMUCapsNewCopy(virQEMUCapsPtr qemuCaps)
ret->version = qemuCaps->version;
ret->kvmVersion = qemuCaps->kvmVersion;
+ ret->microcodeVersion = qemuCaps->microcodeVersion;
if (VIR_STRDUP(ret->package, qemuCaps->package) < 0)
goto error;
@@ -3809,6 +3811,7 @@ struct _virQEMUCapsCachePriv {
uid_t runUid;
gid_t runGid;
virArch hostArch;
+ unsigned int microcodeVersion;
};
typedef struct _virQEMUCapsCachePriv virQEMUCapsCachePriv;
typedef virQEMUCapsCachePriv *virQEMUCapsCachePrivPtr;
@@ -3931,6 +3934,13 @@ virQEMUCapsLoadCache(virArch hostArch,
goto cleanup;
}
+ if (virXPathUInt("string(./microcodeVersion)", ctxt,
+ &qemuCaps->microcodeVersion) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("missing microcode version in QEMU capabilities cache"));
+ goto cleanup;
+ }
+
if (virXPathBoolean("boolean(./package)", ctxt) > 0) {
qemuCaps->package = virXPathString("string(./package)", ctxt);
if (!qemuCaps->package &&
@@ -4195,6 +4205,9 @@ virQEMUCapsFormatCache(virQEMUCapsPtr qemuCaps)
virBufferAsprintf(&buf, "<kvmVersion>%d</kvmVersion>\n",
qemuCaps->kvmVersion);
+ virBufferAsprintf(&buf, "<microcodeVersion>%u</microcodeVersion>\n",
+ qemuCaps->microcodeVersion);
+
if (qemuCaps->package)
virBufferAsprintf(&buf, "<package>%s</package>\n",
qemuCaps->package);
@@ -4336,6 +4349,16 @@ virQEMUCapsIsValid(void *data,
return false;
}
+ if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_KVM) &&
+ priv->microcodeVersion != qemuCaps->microcodeVersion) {
+ VIR_DEBUG("Outdated capabilities for '%s': microcode version changed "
+ "(%u vs %u)",
+ qemuCaps->binary,
+ priv->microcodeVersion,
+ qemuCaps->microcodeVersion);
+ return false;
+ }
+
return true;
}
@@ -5151,6 +5174,7 @@ virQEMUCapsNewForBinaryInternal(virArch hostArch,
const char *libDir,
uid_t runUid,
gid_t runGid,
+ unsigned int microcodeVersion,
bool qmpOnly)
{
virQEMUCapsPtr qemuCaps;
@@ -5207,6 +5231,9 @@ virQEMUCapsNewForBinaryInternal(virArch hostArch,
virQEMUCapsInitHostCPUModel(qemuCaps, hostArch, VIR_DOMAIN_VIRT_KVM);
virQEMUCapsInitHostCPUModel(qemuCaps, hostArch, VIR_DOMAIN_VIRT_QEMU);
+ if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_KVM))
+ qemuCaps->microcodeVersion = microcodeVersion;
+
cleanup:
VIR_FREE(qmperr);
return qemuCaps;
@@ -5228,6 +5255,7 @@ virQEMUCapsNewData(const char *binary,
priv->libDir,
priv->runUid,
priv->runGid,
+ priv->microcodeVersion,
false);
}
@@ -5310,7 +5338,8 @@ virFileCachePtr
virQEMUCapsCacheNew(const char *libDir,
const char *cacheDir,
uid_t runUid,
- gid_t runGid)
+ gid_t runGid,
+ unsigned int microcodeVersion)
{
char *capsCacheDir = NULL;
virFileCachePtr cache = NULL;
@@ -5333,6 +5362,7 @@ virQEMUCapsCacheNew(const char *libDir,
priv->runUid = runUid;
priv->runGid = runGid;
+ priv->microcodeVersion = microcodeVersion;
cleanup:
VIR_FREE(capsCacheDir);
@@ -5810,3 +5840,11 @@ virQEMUCapsFillDomainCaps(virCapsPtr caps,
return -1;
return 0;
}
+
+
+void
+virQEMUCapsSetMicrocodeVersion(virQEMUCapsPtr qemuCaps,
+ unsigned int microcodeVersion)
+{
+ qemuCaps->microcodeVersion = microcodeVersion;
+}
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index 9c92d6b469..eea296c9c3 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -514,8 +514,10 @@ void virQEMUCapsFilterByMachineType(virQEMUCapsPtr qemuCaps,
const char *machineType);
virFileCachePtr virQEMUCapsCacheNew(const char *libDir,
- const char *cacheDir,
- uid_t uid, gid_t gid);
+ const char *cacheDir,
+ uid_t uid,
+ gid_t gid,
+ unsigned int microcodeVersion);
virQEMUCapsPtr virQEMUCapsCacheLookup(virFileCachePtr cache,
const char *binary);
virQEMUCapsPtr virQEMUCapsCacheLookupCopy(virFileCachePtr cache,
diff --git a/src/qemu/qemu_capspriv.h b/src/qemu/qemu_capspriv.h
index d05256bd35..38c14ffa01 100644
--- a/src/qemu/qemu_capspriv.h
+++ b/src/qemu/qemu_capspriv.h
@@ -36,6 +36,7 @@ virQEMUCapsNewForBinaryInternal(virArch hostArch,
const char *libDir,
uid_t runUid,
gid_t runGid,
+ unsigned int microcodeVersion,
bool qmpOnly);
int virQEMUCapsLoadCache(virArch hostArch,
@@ -101,4 +102,9 @@ virQEMUCapsParseHelpStr(const char *qemu,
int
virQEMUCapsParseDeviceStr(virQEMUCapsPtr qemuCaps,
const char *str);
+
+void
+virQEMUCapsSetMicrocodeVersion(virQEMUCapsPtr qemuCaps,
+ unsigned int microcodeVersion);
+
#endif
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 208ccc9bc3..d8dc5388ea 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -631,6 +631,8 @@ qemuStateInitialize(bool privileged,
gid_t run_gid = -1;
char *hugepagePath = NULL;
size_t i;
+ virCPUDefPtr hostCPU = NULL;
+ unsigned int microcodeVersion = 0;
if (VIR_ALLOC(qemu_driver) < 0)
return -1;
@@ -853,10 +855,15 @@ qemuStateInitialize(bool privileged,
run_gid = cfg->group;
}
+ if ((hostCPU = virCPUProbeHost(virArchFromHost())))
+ microcodeVersion = hostCPU->microcodeVersion;
+ virCPUDefFree(hostCPU);
+
qemu_driver->qemuCapsCache = virQEMUCapsCacheNew(cfg->libDir,
cfg->cacheDir,
run_uid,
- run_gid);
+ run_gid,
+ microcodeVersion);
if (!qemu_driver->qemuCapsCache)
goto error;
diff --git a/tests/qemucapabilitiesdata/caps_1.2.2.x86_64.xml b/tests/qemucapabilitiesdata/caps_1.2.2.x86_64.xml
index 956284d5d3..f3f66cd8f5 100644
--- a/tests/qemucapabilitiesdata/caps_1.2.2.x86_64.xml
+++ b/tests/qemucapabilitiesdata/caps_1.2.2.x86_64.xml
@@ -111,6 +111,7 @@
<flag name='query-cpu-definitions'/>
<version>1002002</version>
<kvmVersion>0</kvmVersion>
+ <microcodeVersion>26900</microcodeVersion>
<package></package>
<arch>x86_64</arch>
<cpu type='kvm' name='qemu64'/>
diff --git a/tests/qemucapabilitiesdata/caps_1.3.1.x86_64.xml b/tests/qemucapabilitiesdata/caps_1.3.1.x86_64.xml
index 99384ce5e6..1c4d5ff4a4 100644
--- a/tests/qemucapabilitiesdata/caps_1.3.1.x86_64.xml
+++ b/tests/qemucapabilitiesdata/caps_1.3.1.x86_64.xml
@@ -129,6 +129,7 @@
<flag name='query-cpu-definitions'/>
<version>1003001</version>
<kvmVersion>0</kvmVersion>
+ <microcodeVersion>30198</microcodeVersion>
<package></package>
<arch>x86_64</arch>
<cpu type='kvm' name='qemu64'/>
diff --git a/tests/qemucapabilitiesdata/caps_1.4.2.x86_64.xml b/tests/qemucapabilitiesdata/caps_1.4.2.x86_64.xml
index aea043c57d..a50383c259 100644
--- a/tests/qemucapabilitiesdata/caps_1.4.2.x86_64.xml
+++ b/tests/qemucapabilitiesdata/caps_1.4.2.x86_64.xml
@@ -130,6 +130,7 @@
<flag name='query-cpu-definitions'/>
<version>1004002</version>
<kvmVersion>0</kvmVersion>
+ <microcodeVersion>30915</microcodeVersion>
<package></package>
<arch>x86_64</arch>
<cpu type='kvm' name='Opteron_G5'/>
diff --git a/tests/qemucapabilitiesdata/caps_1.5.3.x86_64.xml b/tests/qemucapabilitiesdata/caps_1.5.3.x86_64.xml
index 6f860e4f25..ad3e122775 100644
--- a/tests/qemucapabilitiesdata/caps_1.5.3.x86_64.xml
+++ b/tests/qemucapabilitiesdata/caps_1.5.3.x86_64.xml
@@ -142,6 +142,7 @@
<flag name='kernel-irqchip'/>
<version>1005003</version>
<kvmVersion>0</kvmVersion>
+ <microcodeVersion>47019</microcodeVersion>
<package></package>
<arch>x86_64</arch>
<cpu type='kvm' name='Opteron_G5'/>
diff --git a/tests/qemucapabilitiesdata/caps_1.6.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_1.6.0.x86_64.xml
index e5dc8360de..7b2324d697 100644
--- a/tests/qemucapabilitiesdata/caps_1.6.0.x86_64.xml
+++ b/tests/qemucapabilitiesdata/caps_1.6.0.x86_64.xml
@@ -147,6 +147,7 @@
<flag name='kernel-irqchip'/>
<version>1006000</version>
<kvmVersion>0</kvmVersion>
+ <microcodeVersion>45248</microcodeVersion>
<package></package>
<arch>x86_64</arch>
<cpu type='kvm' name='Opteron_G5'/>
diff --git a/tests/qemucapabilitiesdata/caps_1.7.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_1.7.0.x86_64.xml
index 86d87eaf0c..4ba509a753 100644
--- a/tests/qemucapabilitiesdata/caps_1.7.0.x86_64.xml
+++ b/tests/qemucapabilitiesdata/caps_1.7.0.x86_64.xml
@@ -149,6 +149,7 @@
<flag name='kernel-irqchip'/>
<version>1007000</version>
<kvmVersion>0</kvmVersion>
+ <microcodeVersion>50692</microcodeVersion>
<package></package>
<arch>x86_64</arch>
<cpu type='kvm' name='Opteron_G5'/>
diff --git a/tests/qemucapabilitiesdata/caps_2.1.1.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.1.1.x86_64.xml
index 2fa551b1a0..416703ac89 100644
--- a/tests/qemucapabilitiesdata/caps_2.1.1.x86_64.xml
+++ b/tests/qemucapabilitiesdata/caps_2.1.1.x86_64.xml
@@ -165,6 +165,7 @@
<flag name='kernel-irqchip'/>
<version>2001001</version>
<kvmVersion>0</kvmVersion>
+ <microcodeVersion>59488</microcodeVersion>
<package></package>
<arch>x86_64</arch>
<cpu type='kvm' name='Opteron_G5'/>
diff --git a/tests/qemucapabilitiesdata/caps_2.4.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.4.0.x86_64.xml
index f97e4cb813..4550139e0c 100644
--- a/tests/qemucapabilitiesdata/caps_2.4.0.x86_64.xml
+++ b/tests/qemucapabilitiesdata/caps_2.4.0.x86_64.xml
@@ -190,6 +190,7 @@
<flag name='virtio-gpu.max_outputs'/>
<version>2004000</version>
<kvmVersion>0</kvmVersion>
+ <microcodeVersion>75653</microcodeVersion>
<package></package>
<arch>x86_64</arch>
<cpu type='kvm' name='Opteron_G5'/>
diff --git a/tests/qemucapabilitiesdata/caps_2.5.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.5.0.x86_64.xml
index 2ba40fc494..6072438688 100644
--- a/tests/qemucapabilitiesdata/caps_2.5.0.x86_64.xml
+++ b/tests/qemucapabilitiesdata/caps_2.5.0.x86_64.xml
@@ -196,6 +196,7 @@
<flag name='virtio-gpu.max_outputs'/>
<version>2005000</version>
<kvmVersion>0</kvmVersion>
+ <microcodeVersion>216775</microcodeVersion>
<package></package>
<arch>x86_64</arch>
<cpu type='kvm' name='Opteron_G5'/>
diff --git a/tests/qemucapabilitiesdata/caps_2.6.0-gicv2.aarch64.xml b/tests/qemucapabilitiesdata/caps_2.6.0-gicv2.aarch64.xml
index 0b34fa30d4..6fc0ab25e0 100644
--- a/tests/qemucapabilitiesdata/caps_2.6.0-gicv2.aarch64.xml
+++ b/tests/qemucapabilitiesdata/caps_2.6.0-gicv2.aarch64.xml
@@ -174,6 +174,7 @@
<flag name='virtio-gpu.max_outputs'/>
<version>2006000</version>
<kvmVersion>0</kvmVersion>
+ <microcodeVersion>228838</microcodeVersion>
<package></package>
<arch>aarch64</arch>
<cpu type='kvm' name='pxa262'/>
diff --git a/tests/qemucapabilitiesdata/caps_2.6.0-gicv3.aarch64.xml b/tests/qemucapabilitiesdata/caps_2.6.0-gicv3.aarch64.xml
index d41d578c7e..1846bf6a7c 100644
--- a/tests/qemucapabilitiesdata/caps_2.6.0-gicv3.aarch64.xml
+++ b/tests/qemucapabilitiesdata/caps_2.6.0-gicv3.aarch64.xml
@@ -174,6 +174,7 @@
<flag name='virtio-gpu.max_outputs'/>
<version>2006000</version>
<kvmVersion>0</kvmVersion>
+ <microcodeVersion>228838</microcodeVersion>
<package></package>
<arch>aarch64</arch>
<cpu type='kvm' name='pxa262'/>
diff --git a/tests/qemucapabilitiesdata/caps_2.6.0.ppc64le.xml b/tests/qemucapabilitiesdata/caps_2.6.0.ppc64le.xml
index f1c9fc98a4..199fc2cd22 100644
--- a/tests/qemucapabilitiesdata/caps_2.6.0.ppc64le.xml
+++ b/tests/qemucapabilitiesdata/caps_2.6.0.ppc64le.xml
@@ -169,6 +169,7 @@
<flag name='virtio-gpu.max_outputs'/>
<version>2006000</version>
<kvmVersion>0</kvmVersion>
+ <microcodeVersion>263602</microcodeVersion>
<package></package>
<arch>ppc64</arch>
<cpu type='kvm' name='default'/>
diff --git a/tests/qemucapabilitiesdata/caps_2.6.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.6.0.x86_64.xml
index bdf006f6be..5897fbc0c9 100644
--- a/tests/qemucapabilitiesdata/caps_2.6.0.x86_64.xml
+++ b/tests/qemucapabilitiesdata/caps_2.6.0.x86_64.xml
@@ -206,6 +206,7 @@
<flag name='virtio-gpu.max_outputs'/>
<version>2006000</version>
<kvmVersion>0</kvmVersion>
+ <microcodeVersion>227579</microcodeVersion>
<package></package>
<arch>x86_64</arch>
<cpu type='kvm' name='Opteron_G5'/>
diff --git a/tests/qemucapabilitiesdata/caps_2.7.0.s390x.xml b/tests/qemucapabilitiesdata/caps_2.7.0.s390x.xml
index fe7bca93b9..4c208008be 100644
--- a/tests/qemucapabilitiesdata/caps_2.7.0.s390x.xml
+++ b/tests/qemucapabilitiesdata/caps_2.7.0.s390x.xml
@@ -136,6 +136,7 @@
<flag name='virtio-gpu.max_outputs'/>
<version>2007000</version>
<kvmVersion>0</kvmVersion>
+ <microcodeVersion>217559</microcodeVersion>
<package></package>
<arch>s390x</arch>
<cpu type='kvm' name='host'/>
diff --git a/tests/qemucapabilitiesdata/caps_2.7.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.7.0.x86_64.xml
index 3fd28f09fe..e3a154806c 100644
--- a/tests/qemucapabilitiesdata/caps_2.7.0.x86_64.xml
+++ b/tests/qemucapabilitiesdata/caps_2.7.0.x86_64.xml
@@ -209,6 +209,7 @@
<flag name='virtio-gpu.max_outputs'/>
<version>2007000</version>
<kvmVersion>0</kvmVersion>
+ <microcodeVersion>239276</microcodeVersion>
<package> (v2.7.0)</package>
<arch>x86_64</arch>
<cpu type='kvm' name='Opteron_G5'/>
diff --git a/tests/qemucapabilitiesdata/caps_2.8.0.s390x.xml b/tests/qemucapabilitiesdata/caps_2.8.0.s390x.xml
index 21bbb820d0..f13c783d44 100644
--- a/tests/qemucapabilitiesdata/caps_2.8.0.s390x.xml
+++ b/tests/qemucapabilitiesdata/caps_2.8.0.s390x.xml
@@ -138,6 +138,7 @@
<flag name='virtio-gpu.max_outputs'/>
<version>2007093</version>
<kvmVersion>0</kvmVersion>
+ <microcodeVersion>242460</microcodeVersion>
<package></package>
<arch>s390x</arch>
<hostCPU type='kvm' model='zEC12.2-base' migratability='no'>
diff --git a/tests/qemucapabilitiesdata/caps_2.8.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.8.0.x86_64.xml
index 761f9d1415..f5bd1d7272 100644
--- a/tests/qemucapabilitiesdata/caps_2.8.0.x86_64.xml
+++ b/tests/qemucapabilitiesdata/caps_2.8.0.x86_64.xml
@@ -211,6 +211,7 @@
<flag name='virtio-gpu.max_outputs'/>
<version>2008000</version>
<kvmVersion>0</kvmVersion>
+ <microcodeVersion>255931</microcodeVersion>
<package> (v2.8.0)</package>
<arch>x86_64</arch>
<cpu type='kvm' name='host' usable='yes'/>
diff --git a/tests/qemucapabilitiesdata/caps_2.9.0.ppc64le.xml b/tests/qemucapabilitiesdata/caps_2.9.0.ppc64le.xml
index 9551907c66..2d1d0f9a89 100644
--- a/tests/qemucapabilitiesdata/caps_2.9.0.ppc64le.xml
+++ b/tests/qemucapabilitiesdata/caps_2.9.0.ppc64le.xml
@@ -175,6 +175,7 @@
<flag name='disk-share-rw'/>
<version>2009000</version>
<kvmVersion>0</kvmVersion>
+ <microcodeVersion>347135</microcodeVersion>
<package> (v2.9.0)</package>
<arch>ppc64</arch>
<cpu type='kvm' name='default'/>
diff --git a/tests/qemucapabilitiesdata/caps_2.9.0.s390x.xml b/tests/qemucapabilitiesdata/caps_2.9.0.s390x.xml
index 0a6fbd0776..3b733801f8 100644
--- a/tests/qemucapabilitiesdata/caps_2.9.0.s390x.xml
+++ b/tests/qemucapabilitiesdata/caps_2.9.0.s390x.xml
@@ -140,6 +140,7 @@
<flag name='disk-share-rw'/>
<version>2009000</version>
<kvmVersion>0</kvmVersion>
+ <microcodeVersion>265878</microcodeVersion>
<package></package>
<arch>s390x</arch>
<hostCPU type='kvm' model='z13.2-base' migratability='no'>
diff --git a/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml
index 1294ebdb31..086594def5 100644
--- a/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml
+++ b/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml
@@ -223,6 +223,7 @@
<flag name='disk-share-rw'/>
<version>2009000</version>
<kvmVersion>0</kvmVersion>
+ <microcodeVersion>321194</microcodeVersion>
<package> (v2.9.0)</package>
<arch>x86_64</arch>
<hostCPU type='kvm' model='base' migratability='yes'>
diff --git a/tests/qemucapabilitiestest.c b/tests/qemucapabilitiestest.c
index 3ae55fc62f..4608fffbb2 100644
--- a/tests/qemucapabilitiestest.c
+++ b/tests/qemucapabilitiestest.c
@@ -61,10 +61,16 @@ testQemuCaps(const void *opaque)
qemuMonitorTestGetMonitor(mon)) < 0)
goto cleanup;
- if (virQEMUCapsGet(capsActual, QEMU_CAPS_KVM) &&
- virQEMUCapsInitQMPMonitorTCG(capsActual,
- qemuMonitorTestGetMonitor(mon)) < 0)
- goto cleanup;
+ if (virQEMUCapsGet(capsActual, QEMU_CAPS_KVM)) {
+ if (virQEMUCapsInitQMPMonitorTCG(capsActual,
+ qemuMonitorTestGetMonitor(mon)) < 0)
+ goto cleanup;
+
+ /* Fill microcodeVersion with a "random" value which is the file
+ * length to provide a reproducible number for testing.
+ */
+ virQEMUCapsSetMicrocodeVersion(capsActual, virFileLength(repliesFile, -1));
+ }
if (!(actual = virQEMUCapsFormatCache(capsActual)))
goto cleanup;
diff --git a/tests/qemucapsprobe.c b/tests/qemucapsprobe.c
index 4b8d6229b4..a5f5a38b16 100644
--- a/tests/qemucapsprobe.c
+++ b/tests/qemucapsprobe.c
@@ -72,7 +72,7 @@ main(int argc, char **argv)
return EXIT_FAILURE;
if (!(caps = virQEMUCapsNewForBinaryInternal(VIR_ARCH_NONE, argv[1], "/tmp",
- -1, -1, true)))
+ -1, -1, 0, true)))
return EXIT_FAILURE;
virObjectUnref(caps);
diff --git a/tests/testutilsqemu.c b/tests/testutilsqemu.c
index 2c7124bf26..f8182033fc 100644
--- a/tests/testutilsqemu.c
+++ b/tests/testutilsqemu.c
@@ -603,7 +603,7 @@ int qemuTestDriverInit(virQEMUDriver *driver)
/* Using /dev/null for libDir and cacheDir automatically produces errors
* upon attempt to use any of them */
- driver->qemuCapsCache = virQEMUCapsCacheNew("/dev/null", "/dev/null", 0, 0);
+ driver->qemuCapsCache = virQEMUCapsCacheNew("/dev/null", "/dev/null", 0, 0, 0);
if (!driver->qemuCapsCache)
goto error;
--
2.17.0
@@ -1,142 +0,0 @@
From ac0e85360cd8f25160b67ee9fb45663d20f82c1d Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Tue, 19 Jun 2018 16:51:13 +0100
Subject: [PATCH 17/19] cpu: add CPU features and model for indirect branch
prediction protection
CVE-2017-5715
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
---
src/cpu/cpu_map.xml | 44 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 44 insertions(+)
diff --git a/src/cpu/cpu_map.xml b/src/cpu/cpu_map.xml
index 8e7ac4973d..c31e7ce36a 100644
--- a/src/cpu/cpu_map.xml
+++ b/src/cpu/cpu_map.xml
@@ -283,6 +283,9 @@
<feature name='avx512-4fmaps'>
<cpuid eax_in='0x07' ecx_in='0x00' edx='0x00000008'/>
</feature>
+ <feature name='spec-ctrl'>
+ <cpuid eax_in='0x07' ecx_in='0x00' edx='0x04000000'/>
+ </feature>
<!-- Processor Extended State Enumeration sub leaf 1 -->
<feature name='xsaveopt'>
@@ -411,6 +414,11 @@
<cpuid eax_in='0x80000007' edx='0x00000100'/>
</feature>
+ <!-- More AMD-specific features -->
+ <feature name='ibpb'>
+ <cpuid eax_in='0x80000008' ebx='0x00001000'/>
+ </feature>
+
<!-- models -->
<model name='486'>
<feature name='fpu'/>
@@ -857,6 +865,10 @@
<feature name='syscall'/>
<feature name='tsc'/>
</model>
+ <model name='Nehalem-IBRS'>
+ <model name='Nehalem'/>
+ <feature name='spec-ctrl'/>
+ </model>
<model name='Westmere'>
<signature family='6' model='44'/>
@@ -894,6 +906,10 @@
<feature name='syscall'/>
<feature name='tsc'/>
</model>
+ <model name='Westmere-IBRS'>
+ <model name='Westmere'/>
+ <feature name='spec-ctrl'/>
+ </model>
<model name='SandyBridge'>
<signature family='6' model='42'/>
@@ -937,6 +953,10 @@
<feature name='x2apic'/>
<feature name='xsave'/>
</model>
+ <model name='SandyBridge-IBRS'>
+ <model name='SandyBridge'/>
+ <feature name='spec-ctrl'/>
+ </model>
<model name='IvyBridge'>
<signature family='6' model='58'/>
@@ -986,6 +1006,10 @@
<feature name='x2apic'/>
<feature name='xsave'/>
</model>
+ <model name='IvyBridge-IBRS'>
+ <model name='IvyBridge'/>
+ <feature name='spec-ctrl'/>
+ </model>
<model name='Haswell-noTSX'>
<signature family='6' model='60'/>
@@ -1039,6 +1063,10 @@
<feature name='x2apic'/>
<feature name='xsave'/>
</model>
+ <model name='Haswell-noTSX-IBRS'>
+ <model name='Haswell-noTSX'/>
+ <feature name='spec-ctrl'/>
+ </model>
<model name='Haswell'>
<signature family='6' model='60'/>
@@ -1094,6 +1122,10 @@
<feature name='x2apic'/>
<feature name='xsave'/>
</model>
+ <model name='Haswell-IBRS'>
+ <model name='Haswell'/>
+ <feature name='spec-ctrl'/>
+ </model>
<model name='Broadwell-noTSX'>
<signature family='6' model='61'/>
@@ -1151,6 +1183,10 @@
<feature name='x2apic'/>
<feature name='xsave'/>
</model>
+ <model name='Broadwell-noTSX-IBRS'>
+ <model name='Broadwell-noTSX'/>
+ <feature name='spec-ctrl'/>
+ </model>
<model name='Broadwell'>
<signature family='6' model='61'/>
@@ -1210,6 +1246,10 @@
<feature name='x2apic'/>
<feature name='xsave'/>
</model>
+ <model name='Broadwell-IBRS'>
+ <model name='Broadwell'/>
+ <feature name='spec-ctrl'/>
+ </model>
<model name='Skylake-Client'>
<signature family='6' model='94'/>
@@ -1278,6 +1318,10 @@
<feature name='xsavec'/>
<feature name='xsaveopt'/>
</model>
+ <model name='Skylake-Client-IBRS'>
+ <model name='Skylake-Client'/>
+ <feature name='spec-ctrl'/>
+ </model>
<!-- AMD CPUs -->
<model name='athlon'>
--
2.17.0
@@ -1,37 +0,0 @@
From 9a252992aa81b4873b22f174de9d345f4289051c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
Date: Mon, 21 May 2018 23:05:07 +0100
Subject: [PATCH 18/19] cpu: define the 'ssbd' CPUID feature bit
(CVE-2018-3639)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
New microcode introduces the "Speculative Store Bypass Disable"
CPUID feature bit. This needs to be exposed to guest OS to allow
them to protect against CVE-2018-3639.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
(cherry picked from commit 1dbca2eccad58d91a5fd33962854f1a653638182)
---
src/cpu/cpu_map.xml | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/cpu/cpu_map.xml b/src/cpu/cpu_map.xml
index c31e7ce36a..87301dc0ef 100644
--- a/src/cpu/cpu_map.xml
+++ b/src/cpu/cpu_map.xml
@@ -286,6 +286,9 @@
<feature name='spec-ctrl'>
<cpuid eax_in='0x07' ecx_in='0x00' edx='0x04000000'/>
</feature>
+ <feature name='ssbd'>
+ <cpuid eax_in='0x07' ecx_in='0x00' edx='0x80000000'/>
+ </feature>
<!-- Processor Extended State Enumeration sub leaf 1 -->
<feature name='xsaveopt'>
--
2.17.0
@@ -1,46 +0,0 @@
From 7774fbbda1c886633eaf0015d6211fc0ad703bc7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
Date: Mon, 21 May 2018 23:05:08 +0100
Subject: [PATCH 19/19] cpu: define the 'virt-ssbd' CPUID feature bit
(CVE-2018-3639)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Some AMD processors only support a non-architectural means of
enabling Speculative Store Bypass Disable. To allow simplified
handling in virtual environments, hypervisors will expose an
architectural definition through CPUID bit 0x80000008_EBX[25].
This needs to be exposed to guest OS running on AMD x86 hosts to
allow them to protect against CVE-2018-3639.
Note that since this CPUID bit won't be present in the host CPUID
results on physical hosts, it will not be enabled automatically
in guests configured with "host-model" CPU unless using QEMU
version >= 2.9.0. Thus for older versions of QEMU, this feature
must be manually enabled using policy=force. Guests using the
"host-passthrough" CPU mode do not need special handling.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
---
src/cpu/cpu_map.xml | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/cpu/cpu_map.xml b/src/cpu/cpu_map.xml
index 87301dc0ef..e31c9ae86c 100644
--- a/src/cpu/cpu_map.xml
+++ b/src/cpu/cpu_map.xml
@@ -421,6 +421,9 @@
<feature name='ibpb'>
<cpuid eax_in='0x80000008' ebx='0x00001000'/>
</feature>
+ <feature name='virt-ssbd'>
+ <cpuid eax_in='0x80000008' ebx='0x02000000'/>
+ </feature>
<!-- models -->
<model name='486'>
--
2.17.0
+1
View File
@@ -0,0 +1 @@
F-11
@@ -0,0 +1,30 @@
From 6e80c60b89728de28267242f7373ecf553e40bc1 Mon Sep 17 00:00:00 2001
From: Daniel P. Berrange <berrange@redhat.com>
Date: Thu, 28 May 2009 13:15:57 +0000
Subject: [PATCH] Avoid broken networking with new QEMU/KVM >= 86
(cherry picked from commit 2afc3bfd8b779ddba974da9d66d6ea337fc91c01)
Fedora-patch: libvirt-0.6.2-avoid-broken-networking-with-newer-qemu.patch
---
src/qemu_conf.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/qemu_conf.c b/src/qemu_conf.c
index fc0e772..99f13c6 100644
--- a/src/qemu_conf.c
+++ b/src/qemu_conf.c
@@ -658,8 +658,8 @@ qemudNetworkIfaceConnect(virConnectPtr conn,
}
snprintf(tapfdstr, sizeof(tapfdstr),
- "tap,fd=%d,script=,vlan=%d,ifname=%s",
- tapfd, vlan, net->ifname);
+ "tap,fd=%d,vlan=%d",
+ tapfd, vlan);
if (!(retval = strdup(tapfdstr)))
goto no_memory;
--
1.6.2.5
@@ -0,0 +1,49 @@
From 6635abc3bbe54e6b0168182805de92cd70d125e4 Mon Sep 17 00:00:00 2001
From: Daniel Veillard <veillard@redhat.com>
Date: Tue, 12 May 2009 15:31:22 +0000
Subject: [PATCH] * src/network_driver.c: enable bridges which are not up without an IP address, patch by Ludwig Nussel
(cherry picked from commit e978774ec67f4b062b1f65e5c76a13193a9430eb)
Fedora-patch: libvirt-0.6.2-bring-up-ipless-bridge.patch
---
src/network_driver.c | 9 +++------
1 files changed, 3 insertions(+), 6 deletions(-)
diff --git a/src/network_driver.c b/src/network_driver.c
index a17a769..a163b15 100644
--- a/src/network_driver.c
+++ b/src/network_driver.c
@@ -836,8 +836,7 @@ static int networkStartNetworkDaemon(virConnectPtr conn,
goto err_delbr;
}
- if (network->def->ipAddress &&
- (err = brSetInterfaceUp(driver->brctl, network->def->bridge, 1))) {
+ if ((err = brSetInterfaceUp(driver->brctl, network->def->bridge, 1))) {
virReportSystemError(conn, err,
_("failed to bring the bridge '%s' up"),
network->def->bridge);
@@ -878,8 +877,7 @@ static int networkStartNetworkDaemon(virConnectPtr conn,
networkRemoveIptablesRules(driver, network);
err_delbr1:
- if (network->def->ipAddress &&
- (err = brSetInterfaceUp(driver->brctl, network->def->bridge, 0))) {
+ if ((err = brSetInterfaceUp(driver->brctl, network->def->bridge, 0))) {
char ebuf[1024];
networkLog(NETWORK_WARN, _("Failed to bring down bridge '%s' : %s\n"),
network->def->bridge, virStrerror(err, ebuf, sizeof ebuf));
@@ -920,8 +918,7 @@ static int networkShutdownNetworkDaemon(virConnectPtr conn,
networkRemoveIptablesRules(driver, network);
char ebuf[1024];
- if (network->def->ipAddress &&
- (err = brSetInterfaceUp(driver->brctl, network->def->bridge, 0))) {
+ if ((err = brSetInterfaceUp(driver->brctl, network->def->bridge, 0))) {
networkLog(NETWORK_WARN, _("Failed to bring down bridge '%s' : %s\n"),
network->def->bridge, virStrerror(err, ebuf, sizeof ebuf));
}
--
1.6.2.5
+33
View File
@@ -0,0 +1,33 @@
From f793cd9b7220145b6df8086d77db4fdc035d680b Mon Sep 17 00:00:00 2001
From: Daniel P. Berrange <berrange@redhat.com>
Date: Tue, 4 Aug 2009 18:13:09 +0100
Subject: [PATCH] Fix escaping of 8-bit high characters
Fix https://bugzilla.redhat.com/show_bug.cgi?id=479517
* src/buf.c: Cast to 'unsigned char' before doing compare to
avoid rejecting 8-bit high characters
(cherry picked from commit 8feb499ba2c3625632210c997b49f5df515c05d4)
Fedora-patch: libvirt-0.6.2-buf-locale-escape.patch
---
src/buf.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/src/buf.c b/src/buf.c
index 259175d..c802aa2 100644
--- a/src/buf.c
+++ b/src/buf.c
@@ -304,7 +304,7 @@ virBufferEscapeString(const virBufferPtr buf, const char *format, const char *st
*out++ = 'o';
*out++ = 's';
*out++ = ';';
- } else if ((*cur >= 0x20) || (*cur == '\n') || (*cur == '\t') ||
+ } else if (((unsigned char)*cur >= 0x20) || (*cur == '\n') || (*cur == '\t') ||
(*cur == '\r')) {
/*
* default case, just copy !
--
1.6.2.5
@@ -0,0 +1,170 @@
From fe3cb2edefceacc76d0dc9c98b8d3b677a495c32 Mon Sep 17 00:00:00 2001
From: Mark McLoughlin <markmc@redhat.com>
Date: Thu, 11 Jun 2009 14:15:49 +0000
Subject: [PATCH] Detect newer qemu-kvm versions
The KVM version string can be one of the following:
- qemu-kvm-x.y.z in stable releases
- kvm-XX for kvm versions up to kvm-85
- qemu-kvm-devel-XX for kvm version kvm-86 and later
There are only a few of places where we need to detect
differences between KVM versions based on 0.9.1:
1) VNET_HDR introduced in kvm-74
2) -incoming tcp introduced in kvm-79
3) -incoming exec introduced in kvm-80
4) -incoming stdio in all earlier kvm versions
With qemu-kvm-0.10.x, we can now assume that (1) is available
if it's a KVM release, (2) and (3) is always available and
(4) is never available.
So, from now on we should only need to check the qemu version
number and the "is_kvm" flag for detecting feature availability.
We only need the KVM version number for older releases.
(cherry picked from commit 04cbe687974b3b46c96fa20180bbb07ffeff69da)
Signed-off-by: Mark McLoughlin <markmc@redhat.com>
Fedora-patch: libvirt-0.6.2-detect-newer-qemu-kvm-versions.patch
---
src/qemu_conf.c | 44 +++++++++++++++++++++++++++++++-------------
1 files changed, 31 insertions(+), 13 deletions(-)
diff --git a/src/qemu_conf.c b/src/qemu_conf.c
index e488d74..d76b2b6 100644
--- a/src/qemu_conf.c
+++ b/src/qemu_conf.c
@@ -416,6 +416,7 @@ virCapsPtr qemudCapsInit(void) {
static unsigned int qemudComputeCmdFlags(const char *help,
unsigned int version,
+ unsigned int is_kvm,
unsigned int kvm_version)
{
unsigned int flags = 0;
@@ -441,7 +442,8 @@ static unsigned int qemudComputeCmdFlags(const char *help,
flags |= QEMUD_CMD_FLAG_DRIVE_BOOT;
if (version >= 9000)
flags |= QEMUD_CMD_FLAG_VNC_COLON;
- if (kvm_version >= 74)
+
+ if (is_kvm && (version >= 10000 || kvm_version >= 74))
flags |= QEMUD_CMD_FLAG_VNET_HDR;
/*
@@ -454,15 +456,15 @@ static unsigned int qemudComputeCmdFlags(const char *help,
* was broken, because it blocked the monitor console
* while waiting for data, so pretend it doesn't exist
*/
- if (kvm_version >= 79) {
+ if (version >= 10000) {
+ flags |= QEMUD_CMD_FLAG_MIGRATE_QEMU_TCP;
+ flags |= QEMUD_CMD_FLAG_MIGRATE_QEMU_EXEC;
+ } else if (kvm_version >= 79) {
flags |= QEMUD_CMD_FLAG_MIGRATE_QEMU_TCP;
if (kvm_version >= 80)
flags |= QEMUD_CMD_FLAG_MIGRATE_QEMU_EXEC;
} else if (kvm_version > 0) {
flags |= QEMUD_CMD_FLAG_MIGRATE_KVM_STDIO;
- } else if (version >= 10000) {
- flags |= QEMUD_CMD_FLAG_MIGRATE_QEMU_TCP;
- flags |= QEMUD_CMD_FLAG_MIGRATE_QEMU_EXEC;
}
return flags;
@@ -472,10 +474,19 @@ static unsigned int qemudComputeCmdFlags(const char *help,
* version number. The first bit is easy, just parse
* 'QEMU PC emulator version x.y.z'.
*
- * With qemu-kvm, however, that is followed by a kvm-XX
- * string in parenthesis.
+ * With qemu-kvm, however, that is followed by a string
+ * in parenthesis as follows:
+ * - qemu-kvm-x.y.z in stable releases
+ * - kvm-XX for kvm versions up to kvm-85
+ * - qemu-kvm-devel-XX for kvm version kvm-86 and later
+ *
+ * For qemu-kvm versions before 0.10.z, we need to detect
+ * the KVM version number for some features. With 0.10.z
+ * and later, we just need the QEMU version number and
+ * whether it is KVM QEMU or mainline QEMU.
*/
#define QEMU_VERSION_STR "QEMU PC emulator version"
+#define QEMU_KVM_VER_PREFIX "(qemu-kvm-"
#define KVM_VER_PREFIX "(kvm-"
#define SKIP_BLANKS(p) do { while ((*(p) == ' ') || (*(p) == '\t')) (p)++; } while (0)
@@ -483,12 +494,13 @@ static unsigned int qemudComputeCmdFlags(const char *help,
static int qemudParseHelpStr(const char *help,
unsigned int *flags,
unsigned int *version,
+ unsigned int *is_kvm,
unsigned int *kvm_version)
{
unsigned major, minor, micro;
const char *p = help;
- *flags = *version = *kvm_version = 0;
+ *flags = *version = *is_kvm = *kvm_version = 0;
if (!STRPREFIX(p, QEMU_VERSION_STR))
goto fail;
@@ -515,9 +527,13 @@ static int qemudParseHelpStr(const char *help,
SKIP_BLANKS(p);
- if (STRPREFIX(p, KVM_VER_PREFIX)) {
+ if (STRPREFIX(p, QEMU_KVM_VER_PREFIX)) {
+ *is_kvm = 1;
+ p += strlen(QEMU_KVM_VER_PREFIX);
+ } else if (STRPREFIX(p, KVM_VER_PREFIX)) {
int ret;
+ *is_kvm = 1;
p += strlen(KVM_VER_PREFIX);
ret = virParseNumber(&p);
@@ -529,12 +545,14 @@ static int qemudParseHelpStr(const char *help,
*version = (major * 1000 * 1000) + (minor * 1000) + micro;
- *flags = qemudComputeCmdFlags(help, *version, *kvm_version);
+ *flags = qemudComputeCmdFlags(help, *version, *is_kvm, *kvm_version);
qemudDebug("Version %u.%u.%u, cooked version %u, flags %u",
major, minor, micro, *version, *flags);
if (*kvm_version)
- qemudDebug("KVM version %u detected", *kvm_version);
+ qemudDebug("KVM version %d detected", *kvm_version);
+ else if (*is_kvm)
+ qemudDebug("qemu-kvm version %u.%u.%u detected", major, minor, micro);
return 0;
@@ -560,7 +578,7 @@ int qemudExtractVersionInfo(const char *qemu,
pid_t child;
int newstdout = -1;
int ret = -1, status;
- unsigned int version, kvm_version;
+ unsigned int version, is_kvm, kvm_version;
unsigned int flags = 0;
if (retflags)
@@ -581,7 +599,7 @@ int qemudExtractVersionInfo(const char *qemu,
goto cleanup2;
}
- if (qemudParseHelpStr(help, &flags, &version, &kvm_version) == -1)
+ if (qemudParseHelpStr(help, &flags, &version, &is_kvm, &kvm_version) == -1)
goto cleanup2;
if (retversion)
--
1.6.2.5
@@ -0,0 +1,208 @@
From 182a3cac2b4339e988802eb02279e7ab4c883c67 Mon Sep 17 00:00:00 2001
From: =?utf-8?q?Guido=20G=C3=BCnther?= <agx@sigxcpu.org>
Date: Thu, 16 Apr 2009 15:56:27 +0000
Subject: [PATCH] Don't log monitor output to domain log file.
It's logged via the logging system already. Prefix monitor debug output with vm
name.
(cherry picked from commit 5caa1e0eb050a12fe8ed02cf635bb672a56cdb6f)
Fedora-patch: libvirt-0.6.2-do-not-log-monitor-output.patch
---
src/qemu_driver.c | 60 +++++++++++++++++++++-------------------------------
1 files changed, 24 insertions(+), 36 deletions(-)
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
index 5ca3d20..cb738b2 100644
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -1706,27 +1706,11 @@ qemudMonitorCommandExtra(const virDomainObjPtr vm,
goto error;
}
}
-
- /* Log, but ignore failures to write logfile for VM */
- if (safewrite(vm->logfile, buf, strlen(buf)) < 0) {
- char ebuf[1024];
- VIR_WARN(_("Unable to log VM console data: %s\n"),
- virStrerror(errno, ebuf, sizeof ebuf));
- }
-
*reply = buf;
return 0;
error:
- if (buf) {
- /* Log, but ignore failures to write logfile for VM */
- if (safewrite(vm->logfile, buf, strlen(buf)) < 0) {
- char ebuf[1024];
- VIR_WARN(_("Unable to log VM console data: %s\n"),
- virStrerror(errno, ebuf, sizeof ebuf));
- }
- VIR_FREE(buf);
- }
+ VIR_FREE(buf);
return -1;
}
@@ -2461,7 +2445,7 @@ static int qemudDomainGetMemoryBalloon(virConnectPtr conn,
goto cleanup;
}
- DEBUG ("balloon reply: '%s'", reply);
+ DEBUG ("%s: balloon reply: '%s'", vm->def->name, reply);
if ((offset = strstr(reply, BALLOON_PREFIX)) != NULL) {
unsigned int memMB;
char *end;
@@ -2515,7 +2499,7 @@ static int qemudDomainSetMemoryBalloon(virConnectPtr conn,
/* If the command failed qemu prints: 'unknown command'
* No message is printed on success it seems */
- DEBUG ("balloon reply: %s", reply);
+ DEBUG ("%s: balloon reply: %s",vm->def->name, reply);
if (strstr(reply, "\nunknown command:")) {
/* Don't set error - it is expected memory balloon fails on many qemu */
ret = 0;
@@ -2810,7 +2794,7 @@ static int qemudDomainSave(virDomainPtr dom,
goto cleanup;
}
- DEBUG ("migrate reply: %s", info);
+ DEBUG ("%s: migrate reply: %s", vm->def->name, info);
/* If the command isn't supported then qemu prints:
* unknown command: migrate" */
@@ -3662,7 +3646,7 @@ static int qemudDomainChangeEjectableMedia(virConnectPtr conn,
/* If the command failed qemu prints:
* device not found, device is locked ...
* No message is printed on success it seems */
- DEBUG ("ejectable media change reply: %s", reply);
+ DEBUG ("%s: ejectable media change reply: %s", vm->def->name, reply);
if (strstr(reply, "\ndevice ")) {
qemudReportError (conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
_("changing cdrom media failed: %s"), reply);
@@ -3723,7 +3707,7 @@ static int qemudDomainAttachPciDiskDevice(virConnectPtr conn,
return -1;
}
- DEBUG ("pci_add reply: %s", reply);
+ DEBUG ("%s: pci_add reply: %s", vm->def->name, reply);
/* If the command succeeds qemu prints:
* OK bus 0... */
#define PCI_ATTACH_OK_MSG "OK bus 0, slot "
@@ -3791,7 +3775,7 @@ static int qemudDomainAttachUsbMassstorageDevice(virConnectPtr conn,
return -1;
}
- DEBUG ("attach_usb reply: %s", reply);
+ DEBUG ("%s: attach_usb reply: %s",vm->def->name, reply);
/* If the command failed qemu prints:
* Could not add ... */
if (strstr(reply, "Could not add ")) {
@@ -3845,7 +3829,7 @@ static int qemudDomainAttachHostDevice(virConnectPtr conn,
return -1;
}
- DEBUG ("attach_usb reply: %s", reply);
+ DEBUG ("%s: attach_usb reply: %s", vm->def->name, reply);
/* If the command failed qemu prints:
* Could not add ... */
if (strstr(reply, "Could not add ")) {
@@ -3984,7 +3968,7 @@ static int qemudDomainDetachPciDiskDevice(virConnectPtr conn,
goto cleanup;
}
- DEBUG ("pci_del reply: %s", reply);
+ DEBUG ("%s: pci_del reply: %s",vm->def->name, reply);
/* If the command fails due to a wrong slot qemu prints: invalid slot,
* nothing is printed on success */
if (strstr(reply, "invalid slot")) {
@@ -4214,7 +4198,7 @@ qemudDomainBlockStats (virDomainPtr dom,
"%s", _("'info blockstats' command failed"));
goto cleanup;
}
- DEBUG ("info blockstats reply: %s", info);
+ DEBUG ("%s: info blockstats reply: %s", vm->def->name, info);
/* If the command isn't supported then qemu prints the supported
* info commands, so the output starts "info ". Since this is
@@ -4255,21 +4239,25 @@ qemudDomainBlockStats (virDomainPtr dom,
if (STRPREFIX (p, "rd_bytes=")) {
p += 9;
if (virStrToLong_ll (p, &dummy, 10, &stats->rd_bytes) == -1)
- DEBUG ("error reading rd_bytes: %s", p);
+ DEBUG ("%s: error reading rd_bytes: %s",
+ vm->def->name, p);
} else if (STRPREFIX (p, "wr_bytes=")) {
p += 9;
if (virStrToLong_ll (p, &dummy, 10, &stats->wr_bytes) == -1)
- DEBUG ("error reading wr_bytes: %s", p);
+ DEBUG ("%s: error reading wr_bytes: %s",
+ vm->def->name, p);
} else if (STRPREFIX (p, "rd_operations=")) {
p += 14;
if (virStrToLong_ll (p, &dummy, 10, &stats->rd_req) == -1)
- DEBUG ("error reading rd_req: %s", p);
+ DEBUG ("%s: error reading rd_req: %s",
+ vm->def->name, p);
} else if (STRPREFIX (p, "wr_operations=")) {
p += 14;
if (virStrToLong_ll (p, &dummy, 10, &stats->wr_req) == -1)
- DEBUG ("error reading wr_req: %s", p);
+ DEBUG ("%s: error reading wr_req: %s",
+ vm->def->name, p);
} else
- DEBUG ("unknown block stat near %s", p);
+ DEBUG ("%s: unknown block stat near %s", vm->def->name, p);
/* Skip to next label. */
p = strchr (p, ' ');
@@ -4481,7 +4469,7 @@ qemudDomainMemoryPeek (virDomainPtr dom,
goto cleanup;
}
- DEBUG ("memsave reply: %s", info);
+ DEBUG ("%s: memsave reply: %s", vm->def->name, info);
/* Read the memory file into buffer. */
if (saferead (fd, buffer, size) == (ssize_t) -1) {
@@ -4798,7 +4786,7 @@ qemudDomainMigratePerform (virDomainPtr dom,
"%s", _("off-line migration specified, but suspend operation failed"));
goto cleanup;
}
- DEBUG ("stop reply: %s", info);
+ DEBUG ("%s: stop reply: %s", vm->def->name, info);
VIR_FREE(info);
paused = 1;
@@ -4815,7 +4803,7 @@ qemudDomainMigratePerform (virDomainPtr dom,
snprintf (cmd, sizeof cmd, "migrate_set_speed %lum", resource);
qemudMonitorCommand (vm, cmd, &info);
- DEBUG ("migrate_set_speed reply: %s", info);
+ DEBUG ("%s: migrate_set_speed reply: %s", vm->def->name, info);
VIR_FREE (info);
}
@@ -4834,7 +4822,7 @@ qemudDomainMigratePerform (virDomainPtr dom,
goto cleanup;
}
- DEBUG ("migrate reply: %s", info);
+ DEBUG ("%s: migrate reply: %s", vm->def->name, info);
/* Now check for "fail" in the output string */
if (strstr(info, "fail") != NULL) {
@@ -4873,7 +4861,7 @@ cleanup:
vm->def->name);
}
else {
- DEBUG ("cont reply: %s", info);
+ DEBUG ("%s: cont reply: %s", vm->def->name, info);
VIR_FREE(info);
}
--
1.6.2.5
@@ -0,0 +1,49 @@
From 2d299525f5de29d11c6dc4810aa41e893535695b Mon Sep 17 00:00:00 2001
From: Mark McLoughlin <markmc@redhat.com>
Date: Fri, 3 Jul 2009 10:27:46 +0000
Subject: [PATCH] Don't unnecessarily try to change a file context
As pointed out by Tim Waugh here:
https://bugzilla.redhat.com/507555
We shouldn't bother trying to set the context of a file if it already
matches what we want.
(Fixed to use STREQ() and not use tabs, as pointed out by danpb)
(cherry picked from commit add254feeaa830dd5af1118c141cb140bf55b5a7)
Fedora-patch: libvirt-0.6.2-do-not-unnecessarily-try-to-change-a-file-context.patch
---
src/security_selinux.c | 11 ++++++++++-
1 files changed, 10 insertions(+), 1 deletions(-)
diff --git a/src/security_selinux.c b/src/security_selinux.c
index 450fce2..8ebe1fe 100644
--- a/src/security_selinux.c
+++ b/src/security_selinux.c
@@ -280,10 +280,19 @@ static int
SELinuxSetFilecon(virConnectPtr conn, const char *path, char *tcon)
{
char ebuf[1024];
+ security_context_t econ;
VIR_INFO("Setting SELinux context on '%s' to '%s'", path, tcon);
- if(setfilecon(path, tcon) < 0) {
+ if (setfilecon(path, tcon) < 0) {
+ if (getfilecon(path, &econ) >= 0) {
+ if (STREQ(tcon, econ)) {
+ freecon(econ);
+ /* It's alright, there's nothing to change anyway. */
+ return 0;
+ }
+ freecon(econ);
+ }
virSecurityReportError(conn, VIR_ERR_ERROR,
_("%s: unable to set security context "
"'\%s\' on %s: %s."), __func__,
--
1.6.2.5
@@ -0,0 +1,48 @@
From 9b41d6550b6bf8d4450bb5b86550eb605cc1fd91 Mon Sep 17 00:00:00 2001
From: Daniel P. Berrange <berrange@redhat.com>
Date: Fri, 8 May 2009 10:07:15 +0000
Subject: [PATCH] Enable save/restore/migrate for QEMU >= 0.10.0
(cherry picked from commit 88e22e4e8cb7fc7e1fa1d132778aa1994f4b55b6)
Fedora-patch: libvirt-0.6.2-enable-qemu-0-10-migration.patch
---
src/qemu_conf.c | 10 +++++-----
1 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/src/qemu_conf.c b/src/qemu_conf.c
index 6f9e610..929fe00 100644
--- a/src/qemu_conf.c
+++ b/src/qemu_conf.c
@@ -472,16 +472,13 @@ int qemudExtractVersionInfo(const char *qemu,
/*
* Handling of -incoming arg with varying features
- * -incoming tcp (kvm >= 79)
- * -incoming exec (kvm >= 80)
+ * -incoming tcp (kvm >= 79, qemu >= 0.10.0)
+ * -incoming exec (kvm >= 80, qemu >= 0.10.0)
* -incoming stdio (all earlier kvm)
*
* NB, there was a pre-kvm-79 'tcp' support, but it
* was broken, because it blocked the monitor console
* while waiting for data, so pretend it doesn't exist
- *
- * XXX when next QEMU release after 0.9.1 arrives,
- * we'll need to add MIGRATE_QEMU_TCP/EXEC here too
*/
if (kvm_version >= 79) {
flags |= QEMUD_CMD_FLAG_MIGRATE_QEMU_TCP;
@@ -489,6 +486,9 @@ int qemudExtractVersionInfo(const char *qemu,
flags |= QEMUD_CMD_FLAG_MIGRATE_QEMU_EXEC;
} else if (kvm_version > 0) {
flags |= QEMUD_CMD_FLAG_MIGRATE_KVM_STDIO;
+ } else if (version >= 10000) {
+ flags |= QEMUD_CMD_FLAG_MIGRATE_QEMU_TCP;
+ flags |= QEMUD_CMD_FLAG_MIGRATE_QEMU_EXEC;
}
if (retversion)
--
1.6.2.5
+147
View File
@@ -0,0 +1,147 @@
From 261ec2c9597b2eb6c7d91589fc66e203f60b6735 Mon Sep 17 00:00:00 2001
From: Daniel P. Berrange <berrange@redhat.com>
Date: Tue, 12 May 2009 16:41:49 +0000
Subject: [PATCH] Fix interrupting of main event thread & protect against accidental uniniitalized variables
(cherry picked from commit 0a31be6ba243066378c344882cc1a32802774edb)
Fedora-patch: libvirt-0.6.2-event-handling-1.patch
---
qemud/event.c | 42 +++++++++++++++++++++++++++++++++++-------
1 files changed, 35 insertions(+), 7 deletions(-)
diff --git a/qemud/event.c b/qemud/event.c
index 0887008..4dc1020 100644
--- a/qemud/event.c
+++ b/qemud/event.c
@@ -83,10 +83,10 @@ struct virEventLoop {
static struct virEventLoop eventLoop;
/* Unique ID for the next FD watch to be registered */
-static int nextWatch = 0;
+static int nextWatch = 1;
/* Unique ID for the next timer to be registered */
-static int nextTimer = 0;
+static int nextTimer = 1;
static void virEventLock(void)
{
@@ -142,15 +142,22 @@ int virEventAddHandleImpl(int fd, int events,
void virEventUpdateHandleImpl(int watch, int events) {
int i;
+ EVENT_DEBUG("Update handle w=%d e=%d", watch, events);
+
+ if (watch <= 0) {
+ VIR_WARN("Ignoring invalid update watch %d", watch);
+ return;
+ }
+
virEventLock();
for (i = 0 ; i < eventLoop.handlesCount ; i++) {
if (eventLoop.handles[i].watch == watch) {
eventLoop.handles[i].events =
virEventHandleTypeToPollEvent(events);
+ virEventInterruptLocked();
break;
}
}
- virEventInterruptLocked();
virEventUnlock();
}
@@ -163,6 +170,12 @@ void virEventUpdateHandleImpl(int watch, int events) {
int virEventRemoveHandleImpl(int watch) {
int i;
EVENT_DEBUG("Remove handle %d", watch);
+
+ if (watch <= 0) {
+ VIR_WARN("Ignoring invalid remove watch %d", watch);
+ return -1;
+ }
+
virEventLock();
for (i = 0 ; i < eventLoop.handlesCount ; i++) {
if (eventLoop.handles[i].deleted)
@@ -171,11 +184,11 @@ int virEventRemoveHandleImpl(int watch) {
if (eventLoop.handles[i].watch == watch) {
EVENT_DEBUG("mark delete %d %d", i, eventLoop.handles[i].fd);
eventLoop.handles[i].deleted = 1;
+ virEventInterruptLocked();
virEventUnlock();
return 0;
}
}
- virEventInterruptLocked();
virEventUnlock();
return -1;
}
@@ -231,6 +244,12 @@ void virEventUpdateTimeoutImpl(int timer, int frequency) {
struct timeval tv;
int i;
EVENT_DEBUG("Updating timer %d timeout with %d ms freq", timer, frequency);
+
+ if (timer <= 0) {
+ VIR_WARN("Ignoring invalid update timer %d", timer);
+ return;
+ }
+
if (gettimeofday(&tv, NULL) < 0) {
return;
}
@@ -243,10 +262,10 @@ void virEventUpdateTimeoutImpl(int timer, int frequency) {
frequency >= 0 ? frequency +
(((unsigned long long)tv.tv_sec)*1000) +
(((unsigned long long)tv.tv_usec)/1000) : 0;
+ virEventInterruptLocked();
break;
}
}
- virEventInterruptLocked();
virEventUnlock();
}
@@ -259,6 +278,12 @@ void virEventUpdateTimeoutImpl(int timer, int frequency) {
int virEventRemoveTimeoutImpl(int timer) {
int i;
EVENT_DEBUG("Remove timer %d", timer);
+
+ if (timer <= 0) {
+ VIR_WARN("Ignoring invalid remove timer %d", timer);
+ return -1;
+ }
+
virEventLock();
for (i = 0 ; i < eventLoop.timeoutsCount ; i++) {
if (eventLoop.timeouts[i].deleted)
@@ -266,11 +291,11 @@ int virEventRemoveTimeoutImpl(int timer) {
if (eventLoop.timeouts[i].timer == timer) {
eventLoop.timeouts[i].deleted = 1;
+ virEventInterruptLocked();
virEventUnlock();
return 0;
}
}
- virEventInterruptLocked();
virEventUnlock();
return -1;
}
@@ -616,9 +641,12 @@ static int virEventInterruptLocked(void)
char c = '\0';
if (!eventLoop.running ||
- pthread_self() == eventLoop.leader)
+ pthread_self() == eventLoop.leader) {
+ VIR_DEBUG("Skip interrupt, %d %d", eventLoop.running, (int)eventLoop.leader);
return 0;
+ }
+ VIR_DEBUG0("Interrupting");
if (safewrite(eventLoop.wakeupfd[1], &c, sizeof(c)) != sizeof(c))
return -1;
return 0;
--
1.6.2.5
+200
View File
@@ -0,0 +1,200 @@
From ef1a3eaa58d83c3367a1addff6c8132f27aa09dd Mon Sep 17 00:00:00 2001
From: Daniel P. Berrange <berrange@redhat.com>
Date: Tue, 12 May 2009 16:43:04 +0000
Subject: [PATCH] Fix watch/timer event deletion
(cherry picked from commit 470317f5c71cbcc6b6d8d83d0978aea3510d3698)
Fedora-patch: libvirt-0.6.2-event-handling-2.patch
---
qemud/event.c | 112 ++++++++++++++++++++++++++-------------------------------
1 files changed, 51 insertions(+), 61 deletions(-)
diff --git a/qemud/event.c b/qemud/event.c
index 4dc1020..8bc7c34 100644
--- a/qemud/event.c
+++ b/qemud/event.c
@@ -312,7 +312,7 @@ static int virEventCalculateTimeout(int *timeout) {
EVENT_DEBUG("Calculate expiry of %d timers", eventLoop.timeoutsCount);
/* Figure out if we need a timeout */
for (i = 0 ; i < eventLoop.timeoutsCount ; i++) {
- if (eventLoop.timeouts[i].deleted || eventLoop.timeouts[i].frequency < 0)
+ if (eventLoop.timeouts[i].frequency < 0)
continue;
EVENT_DEBUG("Got a timeout scheduled for %llu", eventLoop.timeouts[i].expiresAt);
@@ -349,32 +349,26 @@ static int virEventCalculateTimeout(int *timeout) {
* file handles. The caller must free the returned data struct
* returns: the pollfd array, or NULL on error
*/
-static int virEventMakePollFDs(struct pollfd **retfds) {
+static struct pollfd *virEventMakePollFDs(void) {
struct pollfd *fds;
- int i, nfds = 0;
+ int i;
- for (i = 0 ; i < eventLoop.handlesCount ; i++) {
- if (eventLoop.handles[i].deleted)
- continue;
- nfds++;
- }
- *retfds = NULL;
/* Setup the poll file handle data structs */
- if (VIR_ALLOC_N(fds, nfds) < 0)
- return -1;
+ if (VIR_ALLOC_N(fds, eventLoop.handlesCount) < 0)
+ return NULL;
- for (i = 0, nfds = 0 ; i < eventLoop.handlesCount ; i++) {
- if (eventLoop.handles[i].deleted)
- continue;
- fds[nfds].fd = eventLoop.handles[i].fd;
- fds[nfds].events = eventLoop.handles[i].events;
- fds[nfds].revents = 0;
+ for (i = 0 ; i < eventLoop.handlesCount ; i++) {
+ EVENT_DEBUG("Prepare n=%d w=%d, f=%d e=%d", i,
+ eventLoop.handles[i].watch,
+ eventLoop.handles[i].fd,
+ eventLoop.handles[i].events);
+ fds[i].fd = eventLoop.handles[i].fd;
+ fds[i].events = eventLoop.handles[i].events;
+ fds[i].revents = 0;
//EVENT_DEBUG("Wait for %d %d", eventLoop.handles[i].fd, eventLoop.handles[i].events);
- nfds++;
}
- *retfds = fds;
- return nfds;
+ return fds;
}
@@ -434,26 +428,30 @@ static int virEventDispatchTimeouts(void) {
* Returns 0 upon success, -1 if an error occurred
*/
static int virEventDispatchHandles(int nfds, struct pollfd *fds) {
- int i, n;
+ int i;
- for (i = 0, n = 0 ; i < eventLoop.handlesCount && n < nfds ; i++) {
+ /* NB, use nfds not eventLoop.handlesCount, because new
+ * fds might be added on end of list, and they're not
+ * in the fds array we've got */
+ for (i = 0 ; i < nfds ; i++) {
if (eventLoop.handles[i].deleted) {
- EVENT_DEBUG("Skip deleted %d", eventLoop.handles[i].fd);
+ EVENT_DEBUG("Skip deleted n=%d w=%d f=%d", i,
+ eventLoop.handles[i].watch, eventLoop.handles[i].fd);
continue;
}
- if (fds[n].revents) {
+ if (fds[i].revents) {
virEventHandleCallback cb = eventLoop.handles[i].cb;
void *opaque = eventLoop.handles[i].opaque;
- int hEvents = virPollEventToEventHandleType(fds[n].revents);
- EVENT_DEBUG("Dispatch %d %d %p", fds[n].fd,
- fds[n].revents, eventLoop.handles[i].opaque);
+ int hEvents = virPollEventToEventHandleType(fds[i].revents);
+ EVENT_DEBUG("Dispatch n=%d f=%d w=%d e=%d %p", i,
+ fds[i].fd, eventLoop.handles[i].watch,
+ fds[i].revents, eventLoop.handles[i].opaque);
virEventUnlock();
(cb)(eventLoop.handles[i].watch,
- fds[n].fd, hEvents, opaque);
+ fds[i].fd, hEvents, opaque);
virEventLock();
}
- n++;
}
return 0;
@@ -544,22 +542,21 @@ static int virEventCleanupHandles(void) {
* at least one file handle has an event, or a timer expires
*/
int virEventRunOnce(void) {
- struct pollfd *fds;
+ struct pollfd *fds = NULL;
int ret, timeout, nfds;
virEventLock();
eventLoop.running = 1;
eventLoop.leader = pthread_self();
- if ((nfds = virEventMakePollFDs(&fds)) < 0) {
- virEventUnlock();
- return -1;
- }
- if (virEventCalculateTimeout(&timeout) < 0) {
- VIR_FREE(fds);
- virEventUnlock();
- return -1;
- }
+ if (virEventCleanupTimeouts() < 0 ||
+ virEventCleanupHandles() < 0)
+ goto error;
+
+ if (!(fds = virEventMakePollFDs()) ||
+ virEventCalculateTimeout(&timeout) < 0)
+ goto error;
+ nfds = eventLoop.handlesCount;
virEventUnlock();
@@ -571,38 +568,31 @@ int virEventRunOnce(void) {
if (errno == EINTR) {
goto retry;
}
- VIR_FREE(fds);
- return -1;
+ goto error_unlocked;
}
virEventLock();
- if (virEventDispatchTimeouts() < 0) {
- VIR_FREE(fds);
- virEventUnlock();
- return -1;
- }
+ if (virEventDispatchTimeouts() < 0)
+ goto error;
if (ret > 0 &&
- virEventDispatchHandles(nfds, fds) < 0) {
- VIR_FREE(fds);
- virEventUnlock();
- return -1;
- }
- VIR_FREE(fds);
-
- if (virEventCleanupTimeouts() < 0) {
- virEventUnlock();
- return -1;
- }
+ virEventDispatchHandles(nfds, fds) < 0)
+ goto error;
- if (virEventCleanupHandles() < 0) {
- virEventUnlock();
- return -1;
- }
+ if (virEventCleanupTimeouts() < 0 ||
+ virEventCleanupHandles() < 0)
+ goto error;
eventLoop.running = 0;
virEventUnlock();
+ VIR_FREE(fds);
return 0;
+
+error:
+ virEventUnlock();
+error_unlocked:
+ VIR_FREE(fds);
+ return -1;
}
static void virEventHandleWakeup(int watch ATTRIBUTE_UNUSED,
--
1.6.2.5
@@ -0,0 +1,137 @@
From d8bd0cff27c0572e9305e7fdbc6b843f74d9e30f Mon Sep 17 00:00:00 2001
From: Daniel P. Berrange <berrange@redhat.com>
Date: Mon, 29 Jun 2009 10:41:56 +0000
Subject: [PATCH] Fix crash in QEMU driver with bad capabilities data
(cherry picked from commit 39c7e7a6b79bbdfa36928a430d56fa88a204e8fd)
Fedora-patch: libvirt-0.6.2-fix-libvirtd-crash-with-bad-capabilities-data.patch
---
src/qemu_driver.c | 80 +++++++++++++++++++++++++++++++++++-----------------
1 files changed, 54 insertions(+), 26 deletions(-)
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
index cb738b2..3d3675c 100644
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -360,12 +360,43 @@ next:
return 0;
}
+
+static int
+qemudSecurityCapsInit(virSecurityDriverPtr secdrv,
+ virCapsPtr caps)
+{
+ const char *doi, *model;
+
+ doi = virSecurityDriverGetDOI(secdrv);
+ model = virSecurityDriverGetModel(secdrv);
+
+ caps->host.secModel.model = strdup(model);
+ if (!caps->host.secModel.model) {
+ char ebuf[1024];
+ VIR_ERROR(_("Failed to copy secModel model: %s"),
+ virStrerror(errno, ebuf, sizeof ebuf));
+ return -1;
+ }
+
+ caps->host.secModel.doi = strdup(doi);
+ if (!caps->host.secModel.doi) {
+ char ebuf[1024];
+ VIR_ERROR(_("Failed to copy secModel DOI: %s"),
+ virStrerror(errno, ebuf, sizeof ebuf));
+ return -1;
+ }
+
+ VIR_DEBUG("Initialized caps for security driver \"%s\" with "
+ "DOI \"%s\"", model, doi);
+
+ return 0;
+}
+
+
static int
qemudSecurityInit(struct qemud_driver *qemud_drv)
{
int ret;
- const char *doi, *model;
- virCapsPtr caps;
virSecurityDriverPtr security_drv;
ret = virSecurityDriverStartup(&security_drv,
@@ -381,36 +412,17 @@ qemudSecurityInit(struct qemud_driver *qemud_drv)
}
qemud_drv->securityDriver = security_drv;
- doi = virSecurityDriverGetDOI(security_drv);
- model = virSecurityDriverGetModel(security_drv);
- VIR_DEBUG("Initialized security driver \"%s\" with "
- "DOI \"%s\"", model, doi);
+ VIR_INFO("Initialized security driver %s", security_drv->name);
/*
* Add security policy host caps now that the security driver is
* initialized.
*/
- caps = qemud_drv->caps;
-
- caps->host.secModel.model = strdup(model);
- if (!caps->host.secModel.model) {
- char ebuf[1024];
- VIR_ERROR(_("Failed to copy secModel model: %s"),
- virStrerror(errno, ebuf, sizeof ebuf));
- return -1;
- }
+ return qemudSecurityCapsInit(security_drv, qemud_drv->caps);
+}
- caps->host.secModel.doi = strdup(doi);
- if (!caps->host.secModel.doi) {
- char ebuf[1024];
- VIR_ERROR(_("Failed to copy secModel DOI: %s"),
- virStrerror(errno, ebuf, sizeof ebuf));
- return -1;
- }
- return 0;
-}
/**
* qemudStartup:
@@ -1852,13 +1864,29 @@ static int qemudGetNodeInfo(virConnectPtr conn,
static char *qemudGetCapabilities(virConnectPtr conn) {
struct qemud_driver *driver = conn->privateData;
+ virCapsPtr caps;
char *xml = NULL;
qemuDriverLock(driver);
+ if ((caps = qemudCapsInit()) == NULL) {
+ virReportOOMError(conn);
+ goto cleanup;
+ }
+
+ if (qemu_driver->securityDriver &&
+ qemudSecurityCapsInit(qemu_driver->securityDriver, caps) < 0) {
+ virCapabilitiesFree(caps);
+ virReportOOMError(conn);
+ goto cleanup;
+ }
+
virCapabilitiesFree(qemu_driver->caps);
- if ((qemu_driver->caps = qemudCapsInit()) == NULL ||
- (xml = virCapabilitiesFormatXML(driver->caps)) == NULL)
+ qemu_driver->caps = caps;
+
+ if ((xml = virCapabilitiesFormatXML(driver->caps)) == NULL)
virReportOOMError(conn);
+
+cleanup:
qemuDriverUnlock(driver);
return xml;
--
1.6.2.5
+37
View File
@@ -0,0 +1,37 @@
From 99c018831379f23e65860ad4f3628a6d5f1a7d5a Mon Sep 17 00:00:00 2001
From: Mark McLoughlin <markmc@redhat.com>
Date: Fri, 3 Jul 2009 10:29:09 +0000
Subject: [PATCH] Skip labelling if no src path present
Fixes startup of guest's with sourceless cdrom devices.
Patch from Cole Robinson originally posted here:
https://bugzilla.redhat.com/499569
but never sent upstream.
(cherry picked from commit 67d0c6eb9410d5101f4820a7286deacb6398afde)
Fedora-patch: libvirt-0.6.2-fix-nosource-label.patch
---
src/security_selinux.c | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/src/security_selinux.c b/src/security_selinux.c
index 95fa0a6..450fce2 100644
--- a/src/security_selinux.c
+++ b/src/security_selinux.c
@@ -338,6 +338,9 @@ SELinuxSetSecurityImageLabel(virConnectPtr conn,
{
const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
+ if (!disk->src)
+ return 0;
+
if (disk->shared) {
return SELinuxSetFilecon(conn, disk->src, default_image_context);
} else if (disk->readonly) {
--
1.6.2.5
@@ -0,0 +1,85 @@
From 9f6a5f50aee13575331f79f5d93635f701646eb7 Mon Sep 17 00:00:00 2001
From: Daniel P. Berrange <berrange@redhat.com>
Date: Mon, 11 May 2009 15:14:24 +0000
Subject: [PATCH] Fix QEMU ARGV detection with kvm >= 85
(cherry picked from commit 426f9772b84752b4901b72fd382ff6e28e258efd)
Fedora-patch: libvirt-0.6.2-fix-qemu-argv-detection-with-kvm-85.patch
---
src/qemu_conf.c | 18 ++++++++++++++----
src/qemu_driver.c | 12 ++----------
2 files changed, 16 insertions(+), 14 deletions(-)
diff --git a/src/qemu_conf.c b/src/qemu_conf.c
index 929fe00..3e7e32d 100644
--- a/src/qemu_conf.c
+++ b/src/qemu_conf.c
@@ -431,18 +431,28 @@ int qemudExtractVersionInfo(const char *qemu,
return -1;
char *help = NULL;
- enum { MAX_HELP_OUTPUT_SIZE = 8192 };
+ enum { MAX_HELP_OUTPUT_SIZE = 1024*64 };
int len = virFileReadLimFD(newstdout, MAX_HELP_OUTPUT_SIZE, &help);
- if (len < 0)
+ if (len < 0) {
+ virReportSystemError(NULL, errno, "%s",
+ _("Unable to read QEMU help output"));
goto cleanup2;
+ }
if (sscanf(help, "QEMU PC emulator version %u.%u.%u (kvm-%u)",
&major, &minor, &micro, &kvm_version) != 4)
kvm_version = 0;
- if (!kvm_version && sscanf(help, "QEMU PC emulator version %u.%u.%u",
- &major, &minor, &micro) != 3)
+ if (!kvm_version &&
+ sscanf(help, "QEMU PC emulator version %u.%u.%u",
+ &major, &minor, &micro) != 3) {
+ char *eol = strchr(help, '\n');
+ if (eol) *eol = '\0';
+ qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+ _("cannot parse QEMU version number in '%s'"),
+ help);
goto cleanup2;
+ }
version = (major * 1000 * 1000) + (minor * 1000) + micro;
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
index 4752a64..5ca3d20 100644
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -1379,12 +1379,8 @@ static int qemudStartVMDaemon(virConnectPtr conn,
if (qemudExtractVersionInfo(emulator,
NULL,
- &qemuCmdFlags) < 0) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- _("Cannot determine QEMU argv syntax %s"),
- emulator);
+ &qemuCmdFlags) < 0)
goto cleanup;
- }
if (qemuPrepareHostDevices(conn, vm->def) < 0)
goto cleanup;
@@ -3606,12 +3602,8 @@ static int qemudDomainChangeEjectableMedia(virConnectPtr conn,
if (qemudExtractVersionInfo(vm->def->emulator,
NULL,
- &qemuCmdFlags) < 0) {
- qemudReportError(conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
- _("Cannot determine QEMU argv syntax %s"),
- vm->def->emulator);
+ &qemuCmdFlags) < 0)
return -1;
- }
if (qemuCmdFlags & QEMUD_CMD_FLAG_DRIVE) {
if (!(devname = qemudDiskDeviceName(conn, newdisk)))
--
1.6.2.5
+46
View File
@@ -0,0 +1,46 @@
From 0aac99f8e13dfc74b87986908165ae7f44662153 Mon Sep 17 00:00:00 2001
From: Daniel P. Berrange <berrange@redhat.com>
Date: Mon, 6 Jul 2009 16:01:55 +0100
Subject: [PATCH] Fix SELinux denial during hotplug
* src/qemu_driver.c: Relabel disk images *before* running QEMU
hotplug monitor commands
(cherry picked from commit 1795bfe4a177a5eff1b3b0a16d56df6f371c0f8e)
Fedora-patch: libvirt-0.6.2-hotplug-labelling.patch
---
src/qemu_driver.c | 6 ++++--
1 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
index 5fc21a1..f3661f8 100644
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -3934,10 +3934,14 @@ static int qemudDomainAttachDevice(virDomainPtr dom,
switch (dev->data.disk->device) {
case VIR_DOMAIN_DISK_DEVICE_CDROM:
case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
+ if (driver->securityDriver)
+ driver->securityDriver->domainSetSecurityImageLabel(dom->conn, vm, dev->data.disk);
ret = qemudDomainChangeEjectableMedia(dom->conn, vm, dev);
break;
case VIR_DOMAIN_DISK_DEVICE_DISK:
+ if (driver->securityDriver)
+ driver->securityDriver->domainSetSecurityImageLabel(dom->conn, vm, dev->data.disk);
if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_USB) {
ret = qemudDomainAttachUsbMassstorageDevice(dom->conn, vm, dev);
} else if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_SCSI ||
@@ -3949,8 +3953,6 @@ static int qemudDomainAttachDevice(virDomainPtr dom,
virDomainDiskBusTypeToString(dev->data.disk->bus));
goto cleanup;
}
- if (driver->securityDriver)
- driver->securityDriver->domainSetSecurityImageLabel(dom->conn, vm, dev->data.disk);
break;
default:
--
1.6.2.5
+134
View File
@@ -0,0 +1,134 @@
From ae80f9ec15b03d9d3ab6cfa2d48529b459a64fb2 Mon Sep 17 00:00:00 2001
From: Daniel P. Berrange <berrange@redhat.com>
Date: Mon, 6 Jul 2009 15:58:55 +0100
Subject: [PATCH] Fix PCI device hotplug/unplug with newer QEMU
* src/qemu_driver.c: Try new monitor syntax for hotplug first. If
that fails fallback to old KVM specific syntax
(cherry picked from commit 326ecb78145cfeb7706ef0dcd521b19d934950e7)
Fedora-patch: libvirt-0.6.2-hotplug-monitor-syntax.patch
---
src/qemu_driver.c | 56 +++++++++++++++++++++++++++++++++++++++-------------
1 files changed, 42 insertions(+), 14 deletions(-)
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
index f3661f8..8473616 100644
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -3724,6 +3724,7 @@ static int qemudDomainAttachPciDiskDevice(virConnectPtr conn,
char *cmd, *reply, *s;
char *safe_path;
const char* type = virDomainDiskBusTypeToString(dev->data.disk->bus);
+ int tryOldSyntax = 0;
for (i = 0 ; i < vm->def->ndisks ; i++) {
if (STREQ(vm->def->disks[i]->dst, dev->data.disk->dst)) {
@@ -3738,14 +3739,15 @@ static int qemudDomainAttachPciDiskDevice(virConnectPtr conn,
return -1;
}
+try_command:
safe_path = qemudEscapeMonitorArg(dev->data.disk->src);
if (!safe_path) {
virReportOOMError(conn);
return -1;
}
- ret = virAsprintf(&cmd, "pci_add 0 storage file=%s,if=%s",
- safe_path, type);
+ ret = virAsprintf(&cmd, "pci_add %s storage file=%s,if=%s",
+ (tryOldSyntax ? "0": "pci_addr=auto"), safe_path, type);
VIR_FREE(safe_path);
if (ret == -1) {
virReportOOMError(conn);
@@ -3761,17 +3763,27 @@ static int qemudDomainAttachPciDiskDevice(virConnectPtr conn,
DEBUG ("%s: pci_add reply: %s", vm->def->name, reply);
/* If the command succeeds qemu prints:
- * OK bus 0... */
-#define PCI_ATTACH_OK_MSG "OK bus 0, slot "
- if ((s=strstr(reply, PCI_ATTACH_OK_MSG))) {
- char* dummy = s;
- s += strlen(PCI_ATTACH_OK_MSG);
+ * OK bus 0, slot XXX...
+ * or
+ * OK domain 0, bus 0, slot XXX
+ */
+ if ((s = strstr(reply, "OK ")) &&
+ (s = strstr(s, "slot "))) {
+ char *dummy = s;
+ s += strlen("slot ");
if (virStrToLong_i ((const char*)s, &dummy, 10, &dev->data.disk->slotnum) == -1)
VIR_WARN("%s", _("Unable to parse slot number\n"));
+ /* XXX not neccessarily always going to end up in domain 0 / bus 0 :-( */
+ /* XXX this slotnum is not persistant across restarts :-( */
+ } else if (!tryOldSyntax && strstr(reply, "invalid char in expression")) {
+ VIR_FREE(reply);
+ VIR_FREE(cmd);
+ tryOldSyntax = 1;
+ goto try_command;
} else {
qemudReportError (conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
- _("adding %s disk failed"), type);
+ _("adding %s disk failed: %s"), type, reply);
VIR_FREE(reply);
VIR_FREE(cmd);
return -1;
@@ -3990,6 +4002,7 @@ static int qemudDomainDetachPciDiskDevice(virConnectPtr conn,
char *cmd = NULL;
char *reply = NULL;
virDomainDiskDefPtr detach = NULL;
+ int tryOldSyntax = 0;
for (i = 0 ; i < vm->def->ndisks ; i++) {
if (STREQ(vm->def->disks[i]->dst, dev->data.disk->dst)) {
@@ -4011,9 +4024,17 @@ static int qemudDomainDetachPciDiskDevice(virConnectPtr conn,
goto cleanup;
}
- if (virAsprintf(&cmd, "pci_del 0 %d", detach->slotnum) < 0) {
- virReportOOMError(conn);
- goto cleanup;
+try_command:
+ if (tryOldSyntax) {
+ if (virAsprintf(&cmd, "pci_del 0 %d", detach->slotnum) < 0) {
+ virReportOOMError(conn);
+ goto cleanup;
+ }
+ } else {
+ if (virAsprintf(&cmd, "pci_del pci_addr=0:0:%d", detach->slotnum) < 0) {
+ virReportOOMError(conn);
+ goto cleanup;
+ }
}
if (qemudMonitorCommand(vm, cmd, &reply) < 0) {
@@ -4023,12 +4044,19 @@ static int qemudDomainDetachPciDiskDevice(virConnectPtr conn,
}
DEBUG ("%s: pci_del reply: %s",vm->def->name, reply);
+
+ if (!tryOldSyntax &&
+ strstr(reply, "extraneous characters")) {
+ tryOldSyntax = 1;
+ goto try_command;
+ }
/* If the command fails due to a wrong slot qemu prints: invalid slot,
* nothing is printed on success */
- if (strstr(reply, "invalid slot")) {
+ if (strstr(reply, "invalid slot") ||
+ strstr(reply, "Invalid pci address")) {
qemudReportError (conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
- _("failed to detach disk %s: invalid slot %d"),
- detach->dst, detach->slotnum);
+ _("failed to detach disk %s: invalid slot %d: %s"),
+ detach->dst, detach->slotnum, reply);
goto cleanup;
}
--
1.6.2.5
+57
View File
@@ -0,0 +1,57 @@
From 2c42e4c96efd390fa7a6957692a5863d30a10828 Mon Sep 17 00:00:00 2001
From: Daniel P. Berrange <berrange@redhat.com>
Date: Fri, 29 May 2009 14:34:35 +0000
Subject: [PATCH] Avoid double-free in daemon client cleanup code
(cherry picked from commit 6c3ef350649b959215cfc5ccfdaba35bf9560066)
Fedora-patch: libvirt-0.6.2-libvirtd-double-free.patch
---
qemud/qemud.c | 22 +++++++++++++++++-----
1 files changed, 17 insertions(+), 5 deletions(-)
diff --git a/qemud/qemud.c b/qemud/qemud.c
index 4f04355..e299a67 100644
--- a/qemud/qemud.c
+++ b/qemud/qemud.c
@@ -1397,7 +1397,10 @@ static int qemudDispatchServer(struct qemud_server *server, struct qemud_socket
* jobs have finished, then clean it up elsehwere
*/
void qemudDispatchClientFailure(struct qemud_client *client) {
- virEventRemoveHandleImpl(client->watch);
+ if (client->watch != -1) {
+ virEventRemoveHandleImpl(client->watch);
+ client->watch = -1;
+ }
/* Deregister event delivery callback */
if(client->conn) {
@@ -1406,12 +1409,21 @@ void qemudDispatchClientFailure(struct qemud_client *client) {
}
#if HAVE_SASL
- if (client->saslconn) sasl_dispose(&client->saslconn);
+ if (client->saslconn) {
+ sasl_dispose(&client->saslconn);
+ client->saslconn = NULL;
+ }
free(client->saslUsername);
+ client->saslUsername = NULL;
#endif
- if (client->tlssession) gnutls_deinit (client->tlssession);
- close(client->fd);
- client->fd = -1;
+ if (client->tlssession) {
+ gnutls_deinit (client->tlssession);
+ client->tlssession = NULL;
+ }
+ if (client->fd != -1) {
+ close(client->fd);
+ client->fd = -1;
+ }
}
--
1.6.2.5
@@ -0,0 +1,60 @@
From eb2fad7e94ba9bf48787e24542931688b9926ca1 Mon Sep 17 00:00:00 2001
From: Daniel P. Berrange <berrange@redhat.com>
Date: Mon, 6 Jul 2009 15:45:04 +0100
Subject: [PATCH] Fix problem with QEMU monitor welcome prompt confusing libvirt after a libvirtd daemon restart with active guests
* src/qemu_driver: Read and dicard pending monitor data
before issuing new monitor commands.
(cherry picked from commit 2d1f2e706c8b13571e1227df1c69b2302da35d5a)
Fedora-patch: libvirt-0.6.2-monitor-prompt-discard.patch
---
src/qemu_driver.c | 24 ++++++++++++++++++++++++
1 files changed, 24 insertions(+), 0 deletions(-)
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
index 3d3675c..5fc21a1 100644
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -1636,6 +1636,28 @@ cleanup:
qemuDriverUnlock(driver);
}
+
+/* Throw away any data available on the monitor
+ * This is done before executing a command, in order
+ * to allow re-synchronization if something went badly
+ * wrong in the past. it also deals with problem of
+ * QEMU *sometimes* re-printing its initial greeting
+ * when we reconnect to the monitor after restarts.
+ */
+static void
+qemuMonitorDiscardPendingData(virDomainObjPtr vm) {
+ char buf[1024];
+ int ret = 0;
+
+ /* Monitor is non-blocking, so just loop till we
+ * get -1 or 0. Don't bother with detecting
+ * errors, since we'll deal with that better later */
+ do {
+ ret = read(vm->monitor, buf, sizeof (buf)-1);
+ } while (ret > 0);
+}
+
+
static int
qemudMonitorCommandExtra(const virDomainObjPtr vm,
const char *cmd,
@@ -1647,6 +1669,8 @@ qemudMonitorCommandExtra(const virDomainObjPtr vm,
size_t cmdlen = strlen(cmd);
size_t extralen = extra ? strlen(extra) : 0;
+ qemuMonitorDiscardPendingData(vm);
+
if (safewrite(vm->monitor, cmd, cmdlen) != cmdlen)
return -1;
if (safewrite(vm->monitor, "\r", 1) != 1)
--
1.6.2.5
+159
View File
@@ -0,0 +1,159 @@
From 3cf2f90a4747547f9877b15c1f573f8a771098e8 Mon Sep 17 00:00:00 2001
From: Daniel P. Berrange <berrange@redhat.com>
Date: Mon, 29 Jun 2009 10:41:56 +0000
Subject: [PATCH] Fix crash in QEMU driver with bad capabilities data
(cherry picked from commit 39c7e7a6b79bbdfa36928a430d56fa88a204e8fd)
Fedora-patch: libvirt-0.6.2-numa-ignore-fail.patch
---
src/capabilities.c | 16 +++++++++++++---
src/capabilities.h | 3 +++
src/libvirt_private.syms | 1 +
src/lxc_conf.c | 11 +++++++++--
src/qemu_conf.c | 10 ++++++++--
src/uml_conf.c | 11 +++++++++--
6 files changed, 43 insertions(+), 9 deletions(-)
diff --git a/src/capabilities.c b/src/capabilities.c
index d6e3478..8dc32a1 100644
--- a/src/capabilities.c
+++ b/src/capabilities.c
@@ -122,6 +122,18 @@ virCapabilitiesFreeGuest(virCapsGuestPtr guest)
}
+void
+virCapabilitiesFreeNUMAInfo(virCapsPtr caps)
+{
+ int i;
+
+ for (i = 0 ; i < caps->host.nnumaCell ; i++)
+ virCapabilitiesFreeHostNUMACell(caps->host.numaCell[i]);
+ VIR_FREE(caps->host.numaCell);
+ caps->host.nnumaCell = 0;
+}
+
+
/**
* virCapabilitiesFree:
* @caps: object to free
@@ -141,9 +153,7 @@ virCapabilitiesFree(virCapsPtr caps) {
for (i = 0 ; i < caps->host.nfeatures ; i++)
VIR_FREE(caps->host.features[i]);
VIR_FREE(caps->host.features);
- for (i = 0 ; i < caps->host.nnumaCell ; i++)
- virCapabilitiesFreeHostNUMACell(caps->host.numaCell[i]);
- VIR_FREE(caps->host.numaCell);
+ virCapabilitiesFreeNUMAInfo(caps);
for (i = 0 ; i < caps->host.nmigrateTrans ; i++)
VIR_FREE(caps->host.migrateTrans[i]);
diff --git a/src/capabilities.h b/src/capabilities.h
index 5b0bbab..1b49666 100644
--- a/src/capabilities.h
+++ b/src/capabilities.h
@@ -118,6 +118,9 @@ extern void
virCapabilitiesFree(virCapsPtr caps);
extern void
+virCapabilitiesFreeNUMAInfo(virCapsPtr caps);
+
+extern void
virCapabilitiesSetMacPrefix(virCapsPtr caps,
unsigned char *prefix);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 350a931..9249a1a 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -24,6 +24,7 @@ virCapabilitiesDefaultGuestEmulator;
virCapabilitiesDefaultGuestMachine;
virCapabilitiesFormatXML;
virCapabilitiesFree;
+virCapabilitiesFreeNUMAInfo;
virCapabilitiesNew;
virCapabilitiesSetMacPrefix;
virCapabilitiesGenerateMac;
diff --git a/src/lxc_conf.c b/src/lxc_conf.c
index 34c8aea..fe721e3 100644
--- a/src/lxc_conf.c
+++ b/src/lxc_conf.c
@@ -30,6 +30,7 @@
#include "lxc_conf.h"
#include "nodeinfo.h"
#include "virterror_internal.h"
+#include "logging.h"
#define VIR_FROM_THIS VIR_FROM_LXC
@@ -46,8 +47,14 @@ virCapsPtr lxcCapsInit(void)
0, 0)) == NULL)
goto no_memory;
- if (virCapsInitNUMA(caps) < 0)
- goto no_memory;
+ /* Some machines have problematic NUMA toplogy causing
+ * unexpected failures. We don't want to break the QEMU
+ * driver in this scenario, so log errors & carry on
+ */
+ if (virCapsInitNUMA(caps) < 0) {
+ virCapabilitiesFreeNUMAInfo(caps);
+ VIR_WARN0("Failed to query host NUMA topology, disabling NUMA capabilities");
+ }
/* XXX shouldn't 'borrow' KVM's prefix */
virCapabilitiesSetMacPrefix(caps, (unsigned char []){ 0x52, 0x54, 0x00 });
diff --git a/src/qemu_conf.c b/src/qemu_conf.c
index 99f13c6..1194e36 100644
--- a/src/qemu_conf.c
+++ b/src/qemu_conf.c
@@ -376,8 +376,14 @@ virCapsPtr qemudCapsInit(void) {
/* Using KVM's mac prefix for QEMU too */
virCapabilitiesSetMacPrefix(caps, (unsigned char[]){ 0x52, 0x54, 0x00 });
- if (virCapsInitNUMA(caps) < 0)
- goto no_memory;
+ /* Some machines have problematic NUMA toplogy causing
+ * unexpected failures. We don't want to break the QEMU
+ * driver in this scenario, so log errors & carry on
+ */
+ if (virCapsInitNUMA(caps) < 0) {
+ virCapabilitiesFreeNUMAInfo(caps);
+ VIR_WARN0("Failed to query host NUMA topology, disabling NUMA capabilities");
+ }
/* First the pure HVM guests */
for (i = 0 ; i < ARRAY_CARDINALITY(arch_info_hvm) ; i++)
diff --git a/src/uml_conf.c b/src/uml_conf.c
index c0d086e..9dd4967 100644
--- a/src/uml_conf.c
+++ b/src/uml_conf.c
@@ -44,6 +44,7 @@
#include "memory.h"
#include "nodeinfo.h"
#include "verify.h"
+#include "logging.h"
#define VIR_FROM_THIS VIR_FROM_UML
@@ -62,8 +63,14 @@ virCapsPtr umlCapsInit(void) {
0, 0)) == NULL)
goto no_memory;
- if (virCapsInitNUMA(caps) < 0)
- goto no_memory;
+ /* Some machines have problematic NUMA toplogy causing
+ * unexpected failures. We don't want to break the QEMU
+ * driver in this scenario, so log errors & carry on
+ */
+ if (virCapsInitNUMA(caps) < 0) {
+ virCapabilitiesFreeNUMAInfo(caps);
+ VIR_WARN0("Failed to query host NUMA topology, disabling NUMA capabilities");
+ }
if ((guest = virCapabilitiesAddGuest(caps,
"uml",
--
1.6.2.5
+31
View File
@@ -0,0 +1,31 @@
From d5d67ea357d92759d4a9ecb213e577835f961eed Mon Sep 17 00:00:00 2001
From: Daniel P. Berrange <berrange@redhat.com>
Date: Thu, 16 Jul 2009 13:23:32 +0100
Subject: [PATCH] Fix free of unitialized data upon PCI open fail
(cherry picked from commit 4a7acedd3c59a6a750576cb8680bc3f08fe0b52c)
Fedora-patch: libvirt-0.6.2-pci-device-crash.patch
---
src/pci.c | 4 +---
1 files changed, 1 insertions(+), 3 deletions(-)
diff --git a/src/pci.c b/src/pci.c
index ed64d68..68a380d 100644
--- a/src/pci.c
+++ b/src/pci.c
@@ -829,10 +829,8 @@ pciReadDeviceID(pciDevice *dev, const char *id_name)
dev->name, id_name);
/* ID string is '0xNNNN\n' ... i.e. 7 bytes */
- if (virFileReadAll(path, 7, &id_str) < 7) {
- VIR_FREE(id_str);
+ if (virFileReadAll(path, 7, &id_str) < 0)
return NULL;
- }
/* Check for 0x suffix */
if (id_str[0] != '0' || id_str[1] != 'x') {
--
1.6.2.5
+31
View File
@@ -0,0 +1,31 @@
From bf7b58a2471a07111f8022c0176f45ee5dc5fe71 Mon Sep 17 00:00:00 2001
From: Mark McLoughlin <markmc@redhat.com>
Date: Thu, 16 Apr 2009 14:21:35 +0000
Subject: [PATCH] qemu -drive takes format= not fmt=
Seems like a simple typo - it has been "format=" since the flag
was introduced, but we added it as "fmt=".
(cherry picked from commit 9fa79000ecc883c699a6cb1ce7f00c34881bc8fe)
Fedora-patch: libvirt-0.6.2-qemu-drive-format.patch
---
src/qemu_conf.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/src/qemu_conf.c b/src/qemu_conf.c
index f36c927..6f9e610 100644
--- a/src/qemu_conf.c
+++ b/src/qemu_conf.c
@@ -1135,7 +1135,7 @@ int qemudBuildCommandLine(virConnectPtr conn,
disk->device == VIR_DOMAIN_DISK_DEVICE_DISK)
virBufferAddLit(&opt, ",boot=on");
if (disk->driverType)
- virBufferVSprintf(&opt, ",fmt=%s", disk->driverType);
+ virBufferVSprintf(&opt, ",format=%s", disk->driverType);
if (disk->cachemode) {
const char *mode =
--
1.6.2.5
+176
View File
@@ -0,0 +1,176 @@
From 1f1a0ca63c5492c7d41a0cdbd452a2743f314ebc Mon Sep 17 00:00:00 2001
From: Daniel P. Berrange <berrange@redhat.com>
Date: Fri, 8 May 2009 10:11:14 +0000
Subject: [PATCH] Improve name & UUID uniqueness checking in QEMU driver
(cherry picked from commit 54ebbde1e18ec831ff2fddb44ec27ed5dde7874a)
Fedora-patch: libvirt-0.6.2-qemu-name-uniqueness.patch
---
src/qemu_driver.c | 103 ++++++++++++++++++++++++++++++++++++++++++----------
1 files changed, 83 insertions(+), 20 deletions(-)
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
index 8473616..dfd19c5 100644
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -2174,22 +2174,37 @@ static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml,
if (virSecurityDriverVerify(conn, def) < 0)
goto cleanup;
- vm = virDomainFindByName(&driver->domains, def->name);
- if (vm) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
- _("domain '%s' is already defined"),
- def->name);
- goto cleanup;
- }
+ /* See if a VM with matching UUID already exists */
vm = virDomainFindByUUID(&driver->domains, def->uuid);
if (vm) {
- char uuidstr[VIR_UUID_STRING_BUFLEN];
+ /* UUID matches, but if names don't match, refuse it */
+ if (STRNEQ(vm->def->name, def->name)) {
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(vm->def->uuid, uuidstr);
+ qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
+ _("domain '%s' is already defined with uuid %s"),
+ vm->def->name, uuidstr);
+ goto cleanup;
+ }
- virUUIDFormat(def->uuid, uuidstr);
- qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
- _("domain with uuid '%s' is already defined"),
- uuidstr);
- goto cleanup;
+ /* UUID & name match, but if VM is already active, refuse it */
+ if (virDomainIsActive(vm)) {
+ qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
+ _("domain is already active as '%s'"), vm->def->name);
+ goto cleanup;
+ }
+ virDomainObjUnlock(vm);
+ } else {
+ /* UUID does not match, but if a name matches, refuse it */
+ vm = virDomainFindByName(&driver->domains, def->name);
+ if (vm) {
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(vm->def->uuid, uuidstr);
+ qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
+ _("domain '%s' is already defined with uuid %s"),
+ def->name, uuidstr);
+ goto cleanup;
+ }
}
if (!(vm = virDomainAssignDef(conn,
@@ -2368,6 +2383,11 @@ static int qemudDomainDestroy(virDomainPtr dom) {
_("no domain with matching id %d"), dom->id);
goto cleanup;
}
+ if (!virDomainIsActive(vm)) {
+ qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
+ "%s", _("domain is not running"));
+ goto cleanup;
+ }
qemudShutdownVMDaemon(dom->conn, driver, vm);
event = virDomainEventNewFromObj(vm,
@@ -3272,17 +3292,36 @@ static int qemudDomainRestore(virConnectPtr conn,
goto cleanup;
}
- /* Ensure the name and UUID don't already exist in an active VM */
+ /* See if a VM with matching UUID already exists */
vm = virDomainFindByUUID(&driver->domains, def->uuid);
- if (!vm)
- vm = virDomainFindByName(&driver->domains, def->name);
if (vm) {
+ /* UUID matches, but if names don't match, refuse it */
+ if (STRNEQ(vm->def->name, def->name)) {
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(vm->def->uuid, uuidstr);
+ qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
+ _("domain '%s' is already defined with uuid %s"),
+ vm->def->name, uuidstr);
+ goto cleanup;
+ }
+
+ /* UUID & name match, but if VM is already active, refuse it */
if (virDomainIsActive(vm)) {
qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
_("domain is already active as '%s'"), vm->def->name);
goto cleanup;
- } else {
- virDomainObjUnlock(vm);
+ }
+ virDomainObjUnlock(vm);
+ } else {
+ /* UUID does not match, but if a name matches, refuse it */
+ vm = virDomainFindByName(&driver->domains, def->name);
+ if (vm) {
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(vm->def->uuid, uuidstr);
+ qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
+ _("domain '%s' is already defined with uuid %s"),
+ def->name, uuidstr);
+ goto cleanup;
}
}
@@ -3470,18 +3509,41 @@ static virDomainPtr qemudDomainDefine(virConnectPtr conn, const char *xml) {
if (virSecurityDriverVerify(conn, def) < 0)
goto cleanup;
- vm = virDomainFindByName(&driver->domains, def->name);
+ /* See if a VM with matching UUID already exists */
+ vm = virDomainFindByUUID(&driver->domains, def->uuid);
if (vm) {
+ /* UUID matches, but if names don't match, refuse it */
+ if (STRNEQ(vm->def->name, def->name)) {
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(vm->def->uuid, uuidstr);
+ qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
+ _("domain '%s' is already defined with uuid %s"),
+ vm->def->name, uuidstr);
+ goto cleanup;
+ }
+
+ /* UUID & name match */
virDomainObjUnlock(vm);
newVM = 0;
+ } else {
+ /* UUID does not match, but if a name matches, refuse it */
+ vm = virDomainFindByName(&driver->domains, def->name);
+ if (vm) {
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(vm->def->uuid, uuidstr);
+ qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
+ _("domain '%s' is already defined with uuid %s"),
+ def->name, uuidstr);
+ goto cleanup;
+ }
}
if (!(vm = virDomainAssignDef(conn,
&driver->domains,
def))) {
- virDomainDefFree(def);
goto cleanup;
}
+ def = NULL;
vm->persistent = 1;
if (virDomainSaveConfig(conn,
@@ -3503,6 +3565,7 @@ static virDomainPtr qemudDomainDefine(virConnectPtr conn, const char *xml) {
if (dom) dom->id = vm->def->id;
cleanup:
+ virDomainDefFree(def);
if (vm)
virDomainObjUnlock(vm);
if (event)
--
1.6.2.5
+56
View File
@@ -0,0 +1,56 @@
From 5c1ff776a3194bcc5d593aedd36cd676f1fcab64 Mon Sep 17 00:00:00 2001
From: Daniel Veillard <veillard@redhat.com>
Date: Fri, 29 May 2009 13:32:06 +0000
Subject: [PATCH] PPC Qemu Machine Type update * src/qemu_conf.c docs/schemas/domain.rng tests/capabilityschemadata/caps-qemu-kvm.xml: PPC Qemu Machine Type changed from g3bw to g3beige some time ago, patch by Thomas Baker
(cherry picked from commit 525c3d40a97a1ccce7c4dc314d2dd9e780b50d41)
Fedora-patch: libvirt-0.6.2-qemu-ppc-machine-type.patch
---
docs/schemas/domain.rng | 2 +-
src/qemu_conf.c | 2 +-
tests/capabilityschemadata/caps-qemu-kvm.xml | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng
index 2f784e1..b29079a 100644
--- a/docs/schemas/domain.rng
+++ b/docs/schemas/domain.rng
@@ -184,7 +184,7 @@
</attribute>
<attribute name="machine">
<choice>
- <value>g3bw</value>
+ <value>g3beige</value>
<value>mac99</value>
<value>prep</value>
</choice>
diff --git a/src/qemu_conf.c b/src/qemu_conf.c
index 3e7e32d..fc0e772 100644
--- a/src/qemu_conf.c
+++ b/src/qemu_conf.c
@@ -192,7 +192,7 @@ static const char *const arch_info_hvm_sparc_machines[] = {
"sun4m"
};
static const char *const arch_info_hvm_ppc_machines[] = {
- "g3bw", "mac99", "prep"
+ "g3beige", "mac99", "prep"
};
static const char *const arch_info_xen_x86_machines[] = {
diff --git a/tests/capabilityschemadata/caps-qemu-kvm.xml b/tests/capabilityschemadata/caps-qemu-kvm.xml
index fd8523e..893f9ed 100644
--- a/tests/capabilityschemadata/caps-qemu-kvm.xml
+++ b/tests/capabilityschemadata/caps-qemu-kvm.xml
@@ -81,7 +81,7 @@
<arch name='ppc'>
<wordsize>32</wordsize>
<emulator>/usr/bin/qemu-system-ppc</emulator>
- <machine>g3bw</machine>
+ <machine>g3beige</machine>
<machine>mac99</machine>
<machine>prep</machine>
<domain type='qemu'>
--
1.6.2.5
@@ -0,0 +1,224 @@
From 266df161bfd87220bac68918613a2ce9323c8238 Mon Sep 17 00:00:00 2001
From: Mark McLoughlin <markmc@redhat.com>
Date: Thu, 11 Jun 2009 14:12:30 +0000
Subject: [PATCH] Re-factor qemu version parsing
This patch is purely re-factoring without any functional changes
to make way for the next patch.
The main thing achieved by the refactoring is that we now have
easier access to the parenthesised string that KVM folks seem
to delight in changing.
(cherry picked from commit 56ecebf22dd5a235503028e20bf936229037664b)
Signed-off-by: Mark McLoughlin <markmc@redhat.com>
Fedora-patch: libvirt-0.6.2-refactor-qemu-version-parsing.patch
---
src/qemu_conf.c | 174 +++++++++++++++++++++++++++++++++++++++----------------
1 files changed, 123 insertions(+), 51 deletions(-)
diff --git a/src/qemu_conf.c b/src/qemu_conf.c
index 1194e36..e488d74 100644
--- a/src/qemu_conf.c
+++ b/src/qemu_conf.c
@@ -414,54 +414,12 @@ virCapsPtr qemudCapsInit(void) {
return NULL;
}
-
-int qemudExtractVersionInfo(const char *qemu,
- unsigned int *retversion,
- unsigned int *retflags) {
- const char *const qemuarg[] = { qemu, "-help", NULL };
- const char *const qemuenv[] = { "LC_ALL=C", NULL };
- pid_t child;
- int newstdout = -1;
- int ret = -1, status;
- unsigned int major, minor, micro;
- unsigned int version, kvm_version;
+static unsigned int qemudComputeCmdFlags(const char *help,
+ unsigned int version,
+ unsigned int kvm_version)
+{
unsigned int flags = 0;
- if (retflags)
- *retflags = 0;
- if (retversion)
- *retversion = 0;
-
- if (virExec(NULL, qemuarg, qemuenv, NULL,
- &child, -1, &newstdout, NULL, VIR_EXEC_NONE) < 0)
- return -1;
-
- char *help = NULL;
- enum { MAX_HELP_OUTPUT_SIZE = 1024*64 };
- int len = virFileReadLimFD(newstdout, MAX_HELP_OUTPUT_SIZE, &help);
- if (len < 0) {
- virReportSystemError(NULL, errno, "%s",
- _("Unable to read QEMU help output"));
- goto cleanup2;
- }
-
- if (sscanf(help, "QEMU PC emulator version %u.%u.%u (kvm-%u)",
- &major, &minor, &micro, &kvm_version) != 4)
- kvm_version = 0;
-
- if (!kvm_version &&
- sscanf(help, "QEMU PC emulator version %u.%u.%u",
- &major, &minor, &micro) != 3) {
- char *eol = strchr(help, '\n');
- if (eol) *eol = '\0';
- qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- _("cannot parse QEMU version number in '%s'"),
- help);
- goto cleanup2;
- }
-
- version = (major * 1000 * 1000) + (minor * 1000) + micro;
-
if (strstr(help, "-no-kqemu"))
flags |= QEMUD_CMD_FLAG_KQEMU;
if (strstr(help, "-no-kvm"))
@@ -507,6 +465,125 @@ int qemudExtractVersionInfo(const char *qemu,
flags |= QEMUD_CMD_FLAG_MIGRATE_QEMU_EXEC;
}
+ return flags;
+}
+
+/* We parse the output of 'qemu -help' to get the QEMU
+ * version number. The first bit is easy, just parse
+ * 'QEMU PC emulator version x.y.z'.
+ *
+ * With qemu-kvm, however, that is followed by a kvm-XX
+ * string in parenthesis.
+ */
+#define QEMU_VERSION_STR "QEMU PC emulator version"
+#define KVM_VER_PREFIX "(kvm-"
+
+#define SKIP_BLANKS(p) do { while ((*(p) == ' ') || (*(p) == '\t')) (p)++; } while (0)
+
+static int qemudParseHelpStr(const char *help,
+ unsigned int *flags,
+ unsigned int *version,
+ unsigned int *kvm_version)
+{
+ unsigned major, minor, micro;
+ const char *p = help;
+
+ *flags = *version = *kvm_version = 0;
+
+ if (!STRPREFIX(p, QEMU_VERSION_STR))
+ goto fail;
+
+ p += strlen(QEMU_VERSION_STR);
+
+ SKIP_BLANKS(p);
+
+ major = virParseNumber(&p);
+ if (major == -1 || *p != '.')
+ goto fail;
+
+ ++p;
+
+ minor = virParseNumber(&p);
+ if (major == -1 || *p != '.')
+ goto fail;
+
+ ++p;
+
+ micro = virParseNumber(&p);
+ if (major == -1)
+ goto fail;
+
+ SKIP_BLANKS(p);
+
+ if (STRPREFIX(p, KVM_VER_PREFIX)) {
+ int ret;
+
+ p += strlen(KVM_VER_PREFIX);
+
+ ret = virParseNumber(&p);
+ if (ret == -1)
+ goto fail;
+
+ *kvm_version = ret;
+ }
+
+ *version = (major * 1000 * 1000) + (minor * 1000) + micro;
+
+ *flags = qemudComputeCmdFlags(help, *version, *kvm_version);
+
+ qemudDebug("Version %u.%u.%u, cooked version %u, flags %u",
+ major, minor, micro, *version, *flags);
+ if (*kvm_version)
+ qemudDebug("KVM version %u detected", *kvm_version);
+
+ return 0;
+
+fail:
+ p = strchr(help, '\n');
+ if (p)
+ p = strndup(help, p - help);
+
+ qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+ _("cannot parse QEMU version number in '%s'"),
+ p ? p : help);
+
+ VIR_FREE(p);
+
+ return -1;
+}
+
+int qemudExtractVersionInfo(const char *qemu,
+ unsigned int *retversion,
+ unsigned int *retflags) {
+ const char *const qemuarg[] = { qemu, "-help", NULL };
+ const char *const qemuenv[] = { "LC_ALL=C", NULL };
+ pid_t child;
+ int newstdout = -1;
+ int ret = -1, status;
+ unsigned int version, kvm_version;
+ unsigned int flags = 0;
+
+ if (retflags)
+ *retflags = 0;
+ if (retversion)
+ *retversion = 0;
+
+ if (virExec(NULL, qemuarg, qemuenv, NULL,
+ &child, -1, &newstdout, NULL, VIR_EXEC_NONE) < 0)
+ return -1;
+
+ char *help = NULL;
+ enum { MAX_HELP_OUTPUT_SIZE = 1024*64 };
+ int len = virFileReadLimFD(newstdout, MAX_HELP_OUTPUT_SIZE, &help);
+ if (len < 0) {
+ virReportSystemError(NULL, errno, "%s",
+ _("Unable to read QEMU help output"));
+ goto cleanup2;
+ }
+
+ if (qemudParseHelpStr(help, &flags, &version, &kvm_version) == -1)
+ goto cleanup2;
+
if (retversion)
*retversion = version;
if (retflags)
@@ -514,11 +591,6 @@ int qemudExtractVersionInfo(const char *qemu,
ret = 0;
- qemudDebug("Version %d %d %d Cooked version: %d, with flags ? %d",
- major, minor, micro, version, flags);
- if (kvm_version)
- qemudDebug("KVM version %d detected", kvm_version);
-
cleanup2:
VIR_FREE(help);
if (close(newstdout) < 0)
--
1.6.2.5
+100
View File
@@ -0,0 +1,100 @@
From 36cf92efa2b22f275bdc56411d9704e530cdb3fa Mon Sep 17 00:00:00 2001
From: Mark McLoughlin <markmc@redhat.com>
Date: Fri, 3 Jul 2009 10:26:37 +0000
Subject: [PATCH] Re-label shared and readonly images
This patch was posted ages ago here:
https://bugzilla.redhat.com/493692
But was never posted upstream AFAICT.
Patch from Dan Berrange
(cherry picked from commit 547147084d03ebf30d09d242a5a721a4df664ffe)
Fedora-patch: libvirt-0.6.2-shared-readonly-label.patch
---
src/security_selinux.c | 26 +++++++++++++++++++-------
1 files changed, 19 insertions(+), 7 deletions(-)
diff --git a/src/security_selinux.c b/src/security_selinux.c
index ac317d7..95fa0a6 100644
--- a/src/security_selinux.c
+++ b/src/security_selinux.c
@@ -24,11 +24,12 @@
#include "virterror_internal.h"
#include "util.h"
#include "memory.h"
-
+#include "logging.h"
#define VIR_FROM_THIS VIR_FROM_SECURITY
static char default_domain_context[1024];
+static char default_content_context[1024];
static char default_image_context[1024];
#define SECURITY_SELINUX_VOID_DOI "0"
#define SECURITY_SELINUX_NAME "selinux"
@@ -148,8 +149,13 @@ SELinuxInitialize(virConnectPtr conn)
close(fd);
ptr = strchrnul(default_image_context, '\n');
- *ptr = '\0';
-
+ if (*ptr == '\n') {
+ *ptr = '\0';
+ strcpy(default_content_context, ptr+1);
+ ptr = strchrnul(default_content_context, '\n');
+ if (*ptr == '\n')
+ *ptr = '\0';
+ }
return 0;
}
@@ -275,6 +281,8 @@ SELinuxSetFilecon(virConnectPtr conn, const char *path, char *tcon)
{
char ebuf[1024];
+ VIR_INFO("Setting SELinux context on '%s' to '%s'", path, tcon);
+
if(setfilecon(path, tcon) < 0) {
virSecurityReportError(conn, VIR_ERR_ERROR,
_("%s: unable to set security context "
@@ -299,6 +307,8 @@ SELinuxRestoreSecurityImageLabel(virConnectPtr conn,
char *newpath = NULL;
const char *path = disk->src;
+ /* Don't restore labels on readoly/shared disks, because
+ * other VMs may still be accessing these */
if (disk->readonly || disk->shared)
return 0;
@@ -328,8 +338,13 @@ SELinuxSetSecurityImageLabel(virConnectPtr conn,
{
const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
- if (secdef->imagelabel)
+ if (disk->shared) {
+ return SELinuxSetFilecon(conn, disk->src, default_image_context);
+ } else if (disk->readonly) {
+ return SELinuxSetFilecon(conn, disk->src, default_content_context);
+ } else if (secdef->imagelabel) {
return SELinuxSetFilecon(conn, disk->src, secdef->imagelabel);
+ }
return 0;
}
@@ -403,9 +418,6 @@ SELinuxSetSecurityLabel(virConnectPtr conn,
if (secdef->imagelabel) {
for (i = 0 ; i < vm->def->ndisks ; i++) {
- if (vm->def->disks[i]->readonly ||
- vm->def->disks[i]->shared) continue;
-
if (SELinuxSetSecurityImageLabel(conn, vm, vm->def->disks[i]) < 0)
return -1;
}
--
1.6.2.5
+51
View File
@@ -0,0 +1,51 @@
From 2fcd18b6a39f495d84eb3ef56a49994621c8f7d3 Mon Sep 17 00:00:00 2001
From: Daniel P. Berrange <berrange@redhat.com>
Date: Mon, 17 Aug 2009 08:52:30 +0100
Subject: [PATCH] Disable sound cards when running sVirt
Temporary hack till PulseAudio autostart problems are sorted out when
SELinux enforcing (bz 486112)
Fedora-patch: libvirt-0.6.2-svirt-sound.patch
---
src/qemu_conf.c | 17 ++++++++++++++++-
1 files changed, 16 insertions(+), 1 deletions(-)
diff --git a/src/qemu_conf.c b/src/qemu_conf.c
index d76b2b6..22c5363 100644
--- a/src/qemu_conf.c
+++ b/src/qemu_conf.c
@@ -885,6 +885,20 @@ int qemudBuildCommandLine(virConnectPtr conn,
char domid[50];
char *pidfile;
const char *cpu = NULL;
+ int skipSound = 0;
+
+ if (driver->securityDriver &&
+ driver->securityDriver->name &&
+ STREQ(driver->securityDriver->name, "selinux") &&
+ getuid() == 0) {
+ static int soundWarned = 0;
+ skipSound = 1;
+ if (vm->def->nsounds &&
+ !soundWarned) {
+ soundWarned = 1;
+ VIR_WARN0("Sound cards for VMs are disabled while SELinux security model is active");
+ }
+ }
uname_normalize(&ut);
@@ -1531,7 +1545,8 @@ int qemudBuildCommandLine(virConnectPtr conn,
}
/* Add sound hardware */
- if (vm->def->nsounds) {
+ if (vm->def->nsounds &&
+ !skipSound) {
int size = 100;
char *modstr;
if (VIR_ALLOC_N(modstr, size+1) < 0)
--
1.6.2.5
@@ -0,0 +1,49 @@
From a7d81a2f9e80942c9951c1d16ad69c66b9a47bbb Mon Sep 17 00:00:00 2001
From: Daniel Veillard <veillard@redhat.com>
Date: Wed, 13 May 2009 16:19:59 +0000
Subject: [PATCH] * src/buf.c: avoid an XML attribute escaping bug #499791 daniel
(cherry picked from commit 7afe94e7e236ec465d838e7d60e961975c526ab2)
Fedora-patch: libvirt-0.6.2-xml-attribute-escaping.patch
---
src/buf.c | 16 +++++++++++++++-
1 files changed, 15 insertions(+), 1 deletions(-)
diff --git a/src/buf.c b/src/buf.c
index cdcdac9..259175d 100644
--- a/src/buf.c
+++ b/src/buf.c
@@ -266,7 +266,7 @@ virBufferEscapeString(const virBufferPtr buf, const char *format, const char *st
return;
len = strlen(str);
- if (VIR_ALLOC_N(escaped, 5 * len + 1) < 0) {
+ if (VIR_ALLOC_N(escaped, 6 * len + 1) < 0) {
virBufferNoMemory(buf);
return;
}
@@ -290,6 +290,20 @@ virBufferEscapeString(const virBufferPtr buf, const char *format, const char *st
*out++ = 'm';
*out++ = 'p';
*out++ = ';';
+ } else if (*cur == '"') {
+ *out++ = '&';
+ *out++ = 'q';
+ *out++ = 'u';
+ *out++ = 'o';
+ *out++ = 't';
+ *out++ = ';';
+ } else if (*cur == '\'') {
+ *out++ = '&';
+ *out++ = 'a';
+ *out++ = 'p';
+ *out++ = 'o';
+ *out++ = 's';
+ *out++ = ';';
} else if ((*cur >= 0x20) || (*cur == '\n') || (*cur == '\t') ||
(*cur == '\r')) {
/*
--
1.6.2.5
+47
View File
@@ -0,0 +1,47 @@
From b3f02d5528c121bcf7b9ac5c4284517e71a5e2f2 Mon Sep 17 00:00:00 2001
From: Mark McLoughlin <markmc@redhat.com>
Date: Wed, 6 May 2009 15:56:20 +0000
Subject: [PATCH] Fix qemu driver's interpretation of <hostdev managed='yes'/>
This change:
Tue Mar 3 08:55:13 GMT 2009 Daniel P. Berrange <berrange@redhat.com>
Don't try to detach & reset PCI devices while running test
suite for XML-> ARGV conversion.
* src/qemu_driver.c: Add qemuPrepareHostDevices() helper to
detach and reset PCI devices.
* src/qemu_conf.c: Don't detach & reset PCI devices while
building the command line argv
accidentally did this:
- if (hostdev->managed) {
+ if (!hostdev->managed) {
Which results in managed='yes' not causing the device to be
detached when the guest is starting.
(cherry picked from commit 1d6c713b18741f1a0e3d0ccd094275a11aef138c)
Fedora-patch: libvirt-0.6.3-hostdev-managed.patch
---
src/qemu_driver.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
index 79ee072..162d072 100644
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -1215,7 +1215,7 @@ static int qemuPrepareHostDevices(virConnectPtr conn,
if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
continue;
- if (!hostdev->managed) {
+ if (hostdev->managed) {
pciDevice *dev = pciGetDevice(conn,
hostdev->source.subsys.u.pci.domain,
hostdev->source.subsys.u.pci.bus,
--
1.6.2.5
+85
View File
@@ -0,0 +1,85 @@
From a521796bac21f0c8af38a8551a420d87b61c7a9a Mon Sep 17 00:00:00 2001
From: Cole Robinson <crobinso@redhat.com>
Date: Wed, 6 May 2009 14:20:34 +0000
Subject: [PATCH] Refresh QEMU driver capabilities for each getCapabilities call.
Also fix up a couple issues where caps are accessed without locking
the driver structure.
(cherry picked from commit 4f107590243631869677ddea2bb667db4a1282a6)
Fedora-patch: libvirt-0.6.3-refresh-qemu-caps.patch
---
src/qemu_driver.c | 28 ++++++++++++++++++++--------
1 files changed, 20 insertions(+), 8 deletions(-)
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
index 162d072..4752a64 100644
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -1872,10 +1872,12 @@ static int qemudGetNodeInfo(virConnectPtr conn,
static char *qemudGetCapabilities(virConnectPtr conn) {
struct qemud_driver *driver = conn->privateData;
- char *xml;
+ char *xml = NULL;
qemuDriverLock(driver);
- if ((xml = virCapabilitiesFormatXML(driver->caps)) == NULL)
+ virCapabilitiesFree(qemu_driver->caps);
+ if ((qemu_driver->caps = qemudCapsInit()) == NULL ||
+ (xml = virCapabilitiesFormatXML(driver->caps)) == NULL)
virReportOOMError(conn);
qemuDriverUnlock(driver);
@@ -3142,20 +3144,26 @@ cleanup:
return ret;
}
-static int qemudNodeGetSecurityModel(virConnectPtr conn, virSecurityModelPtr secmodel)
+static int qemudNodeGetSecurityModel(virConnectPtr conn,
+ virSecurityModelPtr secmodel)
{
struct qemud_driver *driver = (struct qemud_driver *)conn->privateData;
char *p;
+ int ret = 0;
- if (!driver->securityDriver)
- return -2;
+ qemuDriverLock(driver);
+ if (!driver->securityDriver) {
+ ret = -2;
+ goto cleanup;
+ }
p = driver->caps->host.secModel.model;
if (strlen(p) >= VIR_SECURITY_MODEL_BUFLEN-1) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("security model string exceeds max %d bytes"),
VIR_SECURITY_MODEL_BUFLEN-1);
- return -1;
+ ret = -1;
+ goto cleanup;
}
strcpy(secmodel->model, p);
@@ -3164,10 +3172,14 @@ static int qemudNodeGetSecurityModel(virConnectPtr conn, virSecurityModelPtr sec
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("security DOI string exceeds max %d bytes"),
VIR_SECURITY_DOI_BUFLEN-1);
- return -1;
+ ret = -1;
+ goto cleanup;
}
strcpy(secmodel->doi, p);
- return 0;
+
+cleanup:
+ qemuDriverUnlock(driver);
+ return ret;
}
/* TODO: check seclabel restore */
--
1.6.2.5
@@ -0,0 +1,60 @@
From b77d11b221862343d304e11ed878e2f176101f24 Mon Sep 17 00:00:00 2001
From: Daniel P. Berrange <berrange@redhat.com>
Date: Tue, 28 Apr 2009 10:55:45 +0000
Subject: [PATCH] Cosmetic change to 'virsh nodedev-list --tree' output
Maybe it's just me, but I try to select an item from the tree using
double-click and get annoyed when "+-" gets included in the selection.
* src/virsh.c: add a space between "+-" and the node device name
in 'virsh nodedev-list --tree'
(cherry picked from commit cb4a6614fae48d05f09b7b15328ea6ef4071ccb3)
(cherry picked from commit 097c818bf00b3777778ffc32fea3a6ed1e741e2b)
Fedora-patch: libvirt-add-space-to-nodedev-list-tree.patch
---
src/virsh.c | 10 ++++++----
1 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/src/virsh.c b/src/virsh.c
index 26764a7..c92bb8f 100644
--- a/src/virsh.c
+++ b/src/virsh.c
@@ -4460,10 +4460,12 @@ cmdNodeListDevicesPrint(vshControl *ctl,
if (depth && depth < MAX_DEPTH) {
indentBuf[indentIdx] = '+';
indentBuf[indentIdx+1] = '-';
+ indentBuf[indentIdx+2] = ' ';
+ indentBuf[indentIdx+3] = '\0';
}
/* Print this device */
- vshPrint(ctl, indentBuf);
+ vshPrint(ctl, "%s", indentBuf);
vshPrint(ctl, "%s\n", devices[devid]);
@@ -4487,8 +4489,8 @@ cmdNodeListDevicesPrint(vshControl *ctl,
/* If there is a child device, then print another blank line */
if (nextlastdev != -1) {
- vshPrint(ctl, indentBuf);
- vshPrint(ctl, " |\n");
+ vshPrint(ctl, "%s", indentBuf);
+ vshPrint(ctl, " |\n");
}
/* Finally print all children */
@@ -4511,7 +4513,7 @@ cmdNodeListDevicesPrint(vshControl *ctl,
/* If there was no child device, and we're the last in
* a list of devices, then print another blank line */
if (nextlastdev == -1 && devid == lastdev) {
- vshPrint(ctl, indentBuf);
+ vshPrint(ctl, "%s", indentBuf);
vshPrint(ctl, "\n");
}
}
--
1.6.2.5
@@ -0,0 +1,812 @@
From 6878a049e27f2eaea7bd3d5c266a2d2b39e444f1 Mon Sep 17 00:00:00 2001
From: Mark McLoughlin <markmc@redhat.com>
Date: Mon, 17 Aug 2009 15:05:23 +0100
Subject: [PATCH] Maintain a list of active PCI hostdevs and use it in pciResetDevice()
https://bugzilla.redhat.com/499678
First we add a pciDeviceList type and add a qemuGetPciHostDeviceList()
function to build a list from a domain definition. Use this in
prepare/re-attach to simplify things and eliminate the multiple
pciGetDevice() calls.
Then, as we start/shutdown guests we can add or delete devices as
appropriate from a list of active devices.
Finally, in pciReset(), we can use this to determine whether its safe to
reset a device as a side effect of resetting another device.
(cherry picked from commit 78675b228b76a83f83d64856bfb63b9e14c103a0)
(cherry picked from commit e8ad33931296c67de0538e78d12e21706a826d37)
Fedora-patch: libvirt-allow-pci-hostdev-reset-to-reset-other-devices.patch
---
src/libvirt_private.syms | 7 +-
src/pci.c | 211 +++++++++++++++++++++++++++++++++--------
src/pci.h | 23 +++++-
src/qemu_conf.h | 3 +
src/qemu_driver.c | 237 +++++++++++++++++++++++++++-------------------
src/xen_unified.c | 2 +-
6 files changed, 339 insertions(+), 144 deletions(-)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 9249a1a..75ddda8 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -240,7 +240,12 @@ pciFreeDevice;
pciDettachDevice;
pciReAttachDevice;
pciResetDevice;
-
+pciDeviceSetManaged;
+pciDeviceGetManaged;
+pciDeviceListNew;
+pciDeviceListFree;
+pciDeviceListAdd;
+pciDeviceListDel;
# qparams.h
qparam_get_query;
diff --git a/src/pci.c b/src/pci.c
index 1dddb08..1e68261 100644
--- a/src/pci.c
+++ b/src/pci.c
@@ -58,6 +58,7 @@ struct _pciDevice {
unsigned pci_pm_cap_pos;
unsigned has_flr : 1;
unsigned has_pm_reset : 1;
+ unsigned managed : 1;
};
/* For virReportOOMError() and virReportSystemError() */
@@ -220,7 +221,7 @@ pciWrite32(pciDevice *dev, unsigned pos, uint32_t val)
pciWrite(dev, pos, &buf[0], sizeof(buf));
}
-typedef int (*pciIterPredicate)(pciDevice *, pciDevice *);
+typedef int (*pciIterPredicate)(pciDevice *, pciDevice *, void *);
/* Iterate over available PCI devices calling @predicate
* to compare each one to @dev.
@@ -231,7 +232,8 @@ static int
pciIterDevices(virConnectPtr conn,
pciIterPredicate predicate,
pciDevice *dev,
- pciDevice **matched)
+ pciDevice **matched,
+ void *data)
{
DIR *dir;
struct dirent *entry;
@@ -249,7 +251,7 @@ pciIterDevices(virConnectPtr conn,
while ((entry = readdir(dir))) {
unsigned domain, bus, slot, function;
- pciDevice *try;
+ pciDevice *check;
/* Ignore '.' and '..' */
if (entry->d_name[0] == '.')
@@ -261,18 +263,18 @@ pciIterDevices(virConnectPtr conn,
continue;
}
- try = pciGetDevice(conn, domain, bus, slot, function);
- if (!try) {
+ check = pciGetDevice(conn, domain, bus, slot, function);
+ if (!check) {
ret = -1;
break;
}
- if (predicate(try, dev)) {
- VIR_DEBUG("%s %s: iter matched on %s", dev->id, dev->name, try->name);
- *matched = try;
+ if (predicate(dev, check, data)) {
+ VIR_DEBUG("%s %s: iter matched on %s", dev->id, dev->name, check->name);
+ *matched = check;
break;
}
- pciFreeDevice(conn, try);
+ pciFreeDevice(conn, check);
}
closedir(dir);
return ret;
@@ -374,63 +376,70 @@ pciDetectPowerManagementReset(pciDevice *dev)
return 0;
}
-/* Any devices other than the one supplied on the same domain/bus ? */
+/* Any active devices other than the one supplied on the same domain/bus ? */
static int
-pciSharesBus(pciDevice *a, pciDevice *b)
+pciSharesBusWithActive(pciDevice *dev, pciDevice *check, void *data)
{
- return
- a->domain == b->domain &&
- a->bus == b->bus &&
- (a->slot != b->slot ||
- a->function != b->function);
-}
+ pciDeviceList *activeDevs = data;
-static int
-pciBusContainsOtherDevices(virConnectPtr conn, pciDevice *dev)
-{
- pciDevice *matched = NULL;
- if (pciIterDevices(conn, pciSharesBus, dev, &matched) < 0)
- return 1;
- if (!matched)
+ if (dev->domain != check->domain ||
+ dev->bus != check->bus ||
+ (check->slot == check->slot &&
+ check->function == check->function))
+ return 0;
+
+ if (activeDevs && !pciDeviceListFind(activeDevs, check))
return 0;
- pciFreeDevice(conn, matched);
+
return 1;
}
-/* Is @a the parent of @b ? */
+static pciDevice *
+pciBusContainsActiveDevices(virConnectPtr conn,
+ pciDevice *dev,
+ pciDeviceList *activeDevs)
+{
+ pciDevice *active = NULL;
+ if (pciIterDevices(conn, pciSharesBusWithActive,
+ dev, &active, activeDevs) < 0)
+ return NULL;
+ return active;
+}
+
+/* Is @check the parent of @dev ? */
static int
-pciIsParent(pciDevice *a, pciDevice *b)
+pciIsParent(pciDevice *dev, pciDevice *check, void *data ATTRIBUTE_UNUSED)
{
uint16_t device_class;
uint8_t header_type, secondary, subordinate;
- if (a->domain != b->domain)
+ if (dev->domain != check->domain)
return 0;
/* Is it a bridge? */
- device_class = pciRead16(a, PCI_CLASS_DEVICE);
+ device_class = pciRead16(check, PCI_CLASS_DEVICE);
if (device_class != PCI_CLASS_BRIDGE_PCI)
return 0;
/* Is it a plane? */
- header_type = pciRead8(a, PCI_HEADER_TYPE);
+ header_type = pciRead8(check, PCI_HEADER_TYPE);
if ((header_type & PCI_HEADER_TYPE_MASK) != PCI_HEADER_TYPE_BRIDGE)
return 0;
- secondary = pciRead8(a, PCI_SECONDARY_BUS);
- subordinate = pciRead8(a, PCI_SUBORDINATE_BUS);
+ secondary = pciRead8(check, PCI_SECONDARY_BUS);
+ subordinate = pciRead8(check, PCI_SUBORDINATE_BUS);
- VIR_DEBUG("%s %s: found parent device %s\n", b->id, b->name, a->name);
+ VIR_DEBUG("%s %s: found parent device %s\n", dev->id, dev->name, check->name);
/* No, it's superman! */
- return (b->bus >= secondary && b->bus <= subordinate);
+ return (dev->bus >= secondary && dev->bus <= subordinate);
}
static pciDevice *
pciGetParentDevice(virConnectPtr conn, pciDevice *dev)
{
pciDevice *parent = NULL;
- pciIterDevices(conn, pciIsParent, dev, &parent);
+ pciIterDevices(conn, pciIsParent, dev, &parent, NULL);
return parent;
}
@@ -438,9 +447,11 @@ pciGetParentDevice(virConnectPtr conn, pciDevice *dev)
* devices behind a bus.
*/
static int
-pciTrySecondaryBusReset(virConnectPtr conn, pciDevice *dev)
+pciTrySecondaryBusReset(virConnectPtr conn,
+ pciDevice *dev,
+ pciDeviceList *activeDevs)
{
- pciDevice *parent;
+ pciDevice *parent, *conflict;
uint8_t config_space[PCI_CONF_LEN];
uint16_t ctl;
int ret = -1;
@@ -450,10 +461,10 @@ pciTrySecondaryBusReset(virConnectPtr conn, pciDevice *dev)
* In future, we could allow it so long as those devices
* are not in use by the host or other guests.
*/
- if (pciBusContainsOtherDevices(conn, dev)) {
+ if ((conflict = pciBusContainsActiveDevices(conn, dev, activeDevs))) {
pciReportError(conn, VIR_ERR_NO_SUPPORT,
- _("Other devices on bus with %s, not doing bus reset"),
- dev->name);
+ _("Active %s devices on bus with %s, not doing bus reset"),
+ conflict->name, dev->name);
return -1;
}
@@ -567,10 +578,18 @@ pciInitDevice(virConnectPtr conn, pciDevice *dev)
}
int
-pciResetDevice(virConnectPtr conn, pciDevice *dev)
+pciResetDevice(virConnectPtr conn,
+ pciDevice *dev,
+ pciDeviceList *activeDevs)
{
int ret = -1;
+ if (activeDevs && pciDeviceListFind(activeDevs, dev)) {
+ pciReportError(conn, VIR_ERR_INTERNAL_ERROR,
+ _("Not resetting active device %s"), dev->name);
+ return -1;
+ }
+
if (!dev->initted && pciInitDevice(conn, dev) < 0)
return -1;
@@ -589,7 +608,7 @@ pciResetDevice(virConnectPtr conn, pciDevice *dev)
/* Bus reset is not an option with the root bus */
if (ret < 0 && dev->bus != 0)
- ret = pciTrySecondaryBusReset(conn, dev);
+ ret = pciTrySecondaryBusReset(conn, dev, activeDevs);
if (ret < 0) {
virErrorPtr err = virGetLastError();
@@ -885,8 +904,116 @@ pciGetDevice(virConnectPtr conn,
void
pciFreeDevice(virConnectPtr conn ATTRIBUTE_UNUSED, pciDevice *dev)
{
+ if (!dev)
+ return;
VIR_DEBUG("%s %s: freeing", dev->id, dev->name);
if (dev->fd >= 0)
close(dev->fd);
VIR_FREE(dev);
}
+
+void pciDeviceSetManaged(pciDevice *dev, unsigned managed)
+{
+ dev->managed = !!managed;
+}
+
+unsigned pciDeviceGetManaged(pciDevice *dev)
+{
+ return dev->managed;
+}
+
+pciDeviceList *
+pciDeviceListNew(virConnectPtr conn)
+{
+ pciDeviceList *list;
+
+ if (VIR_ALLOC(list) < 0) {
+ virReportOOMError(conn);
+ return NULL;
+ }
+
+ return list;
+}
+
+void
+pciDeviceListFree(virConnectPtr conn,
+ pciDeviceList *list)
+{
+ int i;
+
+ if (!list)
+ return;
+
+ for (i = 0; i < list->count; i++) {
+ pciFreeDevice(conn, list->devs[i]);
+ list->devs[i] = NULL;
+ }
+
+ list->count = 0;
+ VIR_FREE(list->devs);
+ VIR_FREE(list);
+}
+
+int
+pciDeviceListAdd(virConnectPtr conn,
+ pciDeviceList *list,
+ pciDevice *dev)
+{
+ if (pciDeviceListFind(list, dev)) {
+ pciReportError(conn, VIR_ERR_INTERNAL_ERROR,
+ _("Device %s is already in use"), dev->name);
+ return -1;
+ }
+
+ if (VIR_REALLOC_N(list->devs, list->count+1) < 0) {
+ virReportOOMError(conn);
+ return -1;
+ }
+
+ list->devs[list->count++] = dev;
+
+ return 0;
+}
+
+void
+pciDeviceListDel(virConnectPtr conn ATTRIBUTE_UNUSED,
+ pciDeviceList *list,
+ pciDevice *dev)
+{
+ int i;
+
+ for (i = 0; i < list->count; i++) {
+ if (list->devs[i]->domain != dev->domain ||
+ list->devs[i]->bus != dev->bus ||
+ list->devs[i]->slot != dev->slot ||
+ list->devs[i]->function != dev->function)
+ continue;
+
+ pciFreeDevice(conn, list->devs[i]);
+
+ if (i != --list->count)
+ memmove(&list->devs[i],
+ &list->devs[i+1],
+ sizeof(*list->devs) * (list->count-i));
+
+ if (VIR_REALLOC_N(list->devs, list->count) < 0) {
+ ; /* not fatal */
+ }
+
+ break;
+ }
+}
+
+pciDevice *
+pciDeviceListFind(pciDeviceList *list, pciDevice *dev)
+{
+ int i;
+
+ for (i = 0; i < list->count; i++)
+ if (list->devs[i]->domain == dev->domain &&
+ list->devs[i]->bus == dev->bus &&
+ list->devs[i]->slot == dev->slot &&
+ list->devs[i]->function == dev->function)
+ return list->devs[i];
+ return NULL;
+}
diff --git a/src/pci.h b/src/pci.h
index 47882ef..685b0af 100644
--- a/src/pci.h
+++ b/src/pci.h
@@ -27,6 +27,11 @@
typedef struct _pciDevice pciDevice;
+typedef struct {
+ unsigned count;
+ pciDevice **devs;
+} pciDeviceList;
+
pciDevice *pciGetDevice (virConnectPtr conn,
unsigned domain,
unsigned bus,
@@ -39,6 +44,22 @@ int pciDettachDevice (virConnectPtr conn,
int pciReAttachDevice (virConnectPtr conn,
pciDevice *dev);
int pciResetDevice (virConnectPtr conn,
- pciDevice *dev);
+ pciDevice *dev,
+ pciDeviceList *activeDevs);
+void pciDeviceSetManaged(pciDevice *dev,
+ unsigned managed);
+unsigned pciDeviceGetManaged(pciDevice *dev);
+
+pciDeviceList *pciDeviceListNew (virConnectPtr conn);
+void pciDeviceListFree (virConnectPtr conn,
+ pciDeviceList *list);
+int pciDeviceListAdd (virConnectPtr conn,
+ pciDeviceList *list,
+ pciDevice *dev);
+void pciDeviceListDel (virConnectPtr conn,
+ pciDeviceList *list,
+ pciDevice *dev);
+pciDevice * pciDeviceListFind (pciDeviceList *list,
+ pciDevice *dev);
#endif /* __VIR_PCI_H__ */
diff --git a/src/qemu_conf.h b/src/qemu_conf.h
index 70fe9c8..cde326d 100644
--- a/src/qemu_conf.h
+++ b/src/qemu_conf.h
@@ -34,6 +34,7 @@
#include "domain_event.h"
#include "threads.h"
#include "security.h"
+#include "pci.h"
#define qemudDebug(fmt, ...) do {} while(0)
@@ -90,6 +91,8 @@ struct qemud_driver {
char *securityDriverName;
virSecurityDriverPtr securityDriver;
+
+ pciDeviceList *activePciHostdevs;
};
/* Status needed to reconenct to running VMs */
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
index 9f87d2a..7dbf4a2 100644
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -126,6 +126,9 @@ static int qemudDomainSetMemoryBalloon(virConnectPtr conn,
virDomainObjPtr vm,
unsigned long newmem);
+static int qemuUpdateActivePciHostdevs(struct qemud_driver *driver,
+ virDomainDefPtr def);
+
static struct qemud_driver *qemu_driver = NULL;
@@ -334,6 +337,10 @@ qemudReconnectVMs(struct qemud_driver *driver)
if ((vm->logfile = qemudLogFD(NULL, driver->logDir, vm->def->name)) < 0)
goto next_error;
+ if (qemuUpdateActivePciHostdevs(driver, vm->def) < 0) {
+ goto next_error;
+ }
+
if (vm->def->id >= driver->nextvmid)
driver->nextvmid = vm->def->id + 1;
@@ -515,6 +522,9 @@ qemudStartup(void) {
if ((qemu_driver->caps = qemudCapsInit()) == NULL)
goto out_of_memory;
+ if ((qemu_driver->activePciHostdevs = pciDeviceListNew(NULL)) == NULL)
+ goto error;
+
if (qemudLoadDriverConfig(qemu_driver, driverConf) < 0) {
goto error;
}
@@ -627,6 +637,7 @@ qemudShutdown(void) {
return -1;
qemuDriverLock(qemu_driver);
+ pciDeviceListFree(NULL, qemu_driver->activePciHostdevs);
virCapabilitiesFree(qemu_driver->caps);
virDomainObjListFree(&qemu_driver->domains);
@@ -1209,48 +1220,16 @@ static int qemudNextFreeVNCPort(struct qemud_driver *driver ATTRIBUTE_UNUSED) {
return -1;
}
-static int qemuPrepareHostDevices(virConnectPtr conn,
- virDomainDefPtr def) {
+static pciDeviceList *
+qemuGetPciHostDeviceList(virConnectPtr conn,
+ virDomainDefPtr def)
+{
+ pciDeviceList *list;
int i;
- /* We have to use 2 loops here. *All* devices must
- * be detached before we reset any of them, because
- * in some cases you have to reset the whole PCI,
- * which impacts all devices on it
- */
-
- for (i = 0 ; i < def->nhostdevs ; i++) {
- virDomainHostdevDefPtr hostdev = def->hostdevs[i];
-
- if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
- continue;
- if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
- continue;
-
- if (hostdev->managed) {
- pciDevice *dev = pciGetDevice(conn,
- hostdev->source.subsys.u.pci.domain,
- hostdev->source.subsys.u.pci.bus,
- hostdev->source.subsys.u.pci.slot,
- hostdev->source.subsys.u.pci.function);
- if (!dev)
- goto error;
-
- if (pciDettachDevice(conn, dev) < 0) {
- pciFreeDevice(conn, dev);
- goto error;
- }
-
- pciFreeDevice(conn, dev);
- } /* else {
- XXX validate that non-managed device isn't in use, eg
- by checking that device is either un-bound, or bound
- to pci-stub.ko
- } */
- }
+ if (!(list = pciDeviceListNew(conn)))
+ return NULL;
- /* Now that all the PCI hostdevs have be dettached, we can safely
- * reset them */
for (i = 0 ; i < def->nhostdevs ; i++) {
virDomainHostdevDefPtr hostdev = def->hostdevs[i];
pciDevice *dev;
@@ -1265,95 +1244,151 @@ static int qemuPrepareHostDevices(virConnectPtr conn,
hostdev->source.subsys.u.pci.bus,
hostdev->source.subsys.u.pci.slot,
hostdev->source.subsys.u.pci.function);
- if (!dev)
- goto error;
+ if (!dev) {
+ pciDeviceListFree(conn, list);
+ return NULL;
+ }
- if (pciResetDevice(conn, dev) < 0) {
+ if (pciDeviceListAdd(conn, list, dev) < 0) {
pciFreeDevice(conn, dev);
- goto error;
+ pciDeviceListFree(conn, list);
+ return NULL;
}
- pciFreeDevice(conn, dev);
+ pciDeviceSetManaged(dev, hostdev->managed);
}
- return 0;
+ return list;
+}
-error:
- return -1;
+static int
+qemuUpdateActivePciHostdevs(struct qemud_driver *driver,
+ virDomainDefPtr def)
+{
+ pciDeviceList *pcidevs;
+ int i, ret;
+
+ if (!def->nhostdevs)
+ return 0;
+
+ if (!(pcidevs = qemuGetPciHostDeviceList(NULL, def)))
+ return -1;
+
+ ret = 0;
+
+ for (i = 0; i < pcidevs->count; i++) {
+ if (pciDeviceListAdd(NULL,
+ driver->activePciHostdevs,
+ pcidevs->devs[i]) < 0) {
+ ret = -1;
+ break;
+ }
+ pcidevs->devs[i] = NULL;
+ }
+
+ pciDeviceListFree(NULL, pcidevs);
+ return ret;
}
-static void
-qemuDomainReAttachHostDevices(virConnectPtr conn, virDomainDefPtr def)
+static int
+qemuPrepareHostDevices(virConnectPtr conn,
+ struct qemud_driver *driver,
+ virDomainDefPtr def)
{
+ pciDeviceList *pcidevs;
int i;
- /* Again 2 loops; reset all the devices before re-attach */
+ if (!def->nhostdevs)
+ return 0;
- for (i = 0 ; i < def->nhostdevs ; i++) {
- virDomainHostdevDefPtr hostdev = def->hostdevs[i];
- pciDevice *dev;
+ if (!(pcidevs = qemuGetPciHostDeviceList(conn, def)))
+ return -1;
- if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
- continue;
- if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
- continue;
+ /* We have to use 3 loops here. *All* devices must
+ * be detached before we reset any of them, because
+ * in some cases you have to reset the whole PCI,
+ * which impacts all devices on it. Also, all devices
+ * must be reset before being marked as active.
+ */
- dev = pciGetDevice(conn,
- hostdev->source.subsys.u.pci.domain,
- hostdev->source.subsys.u.pci.bus,
- hostdev->source.subsys.u.pci.slot,
- hostdev->source.subsys.u.pci.function);
- if (!dev) {
- virErrorPtr err = virGetLastError();
- VIR_ERROR(_("Failed to allocate pciDevice: %s\n"),
- err ? err->message : "");
- virResetError(err);
- continue;
- }
+ /* XXX validate that non-managed device isn't in use, eg
+ * by checking that device is either un-bound, or bound
+ * to pci-stub.ko
+ */
- if (pciResetDevice(conn, dev) < 0) {
- virErrorPtr err = virGetLastError();
- VIR_ERROR(_("Failed to reset PCI device: %s\n"),
- err ? err->message : "");
- virResetError(err);
- }
+ for (i = 0; i < pcidevs->count; i++)
+ if (pciDeviceGetManaged(pcidevs->devs[i]) &&
+ pciDettachDevice(conn, pcidevs->devs[i]) < 0)
+ goto error;
+
+ /* Now that all the PCI hostdevs have be dettached, we can safely
+ * reset them */
+ for (i = 0; i < pcidevs->count; i++)
+ if (pciResetDevice(conn, pcidevs->devs[i],
+ driver->activePciHostdevs) < 0)
+ goto error;
- pciFreeDevice(conn, dev);
+ /* Now mark all the devices as active */
+ for (i = 0; i < pcidevs->count; i++) {
+ if (pciDeviceListAdd(conn,
+ driver->activePciHostdevs,
+ pcidevs->devs[i]) < 0)
+ goto error;
+ pcidevs->devs[i] = NULL;
}
- for (i = 0 ; i < def->nhostdevs ; i++) {
- virDomainHostdevDefPtr hostdev = def->hostdevs[i];
- pciDevice *dev;
+ pciDeviceListFree(conn, pcidevs);
+ return 0;
- if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
- continue;
- if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
- continue;
- if (!hostdev->managed)
- continue;
+error:
+ pciDeviceListFree(conn, pcidevs);
+ return -1;
+}
- dev = pciGetDevice(conn,
- hostdev->source.subsys.u.pci.domain,
- hostdev->source.subsys.u.pci.bus,
- hostdev->source.subsys.u.pci.slot,
- hostdev->source.subsys.u.pci.function);
- if (!dev) {
+static void
+qemuDomainReAttachHostDevices(virConnectPtr conn,
+ struct qemud_driver *driver,
+ virDomainDefPtr def)
+{
+ pciDeviceList *pcidevs;
+ int i;
+
+ if (!def->nhostdevs)
+ return;
+
+ if (!(pcidevs = qemuGetPciHostDeviceList(conn, def))) {
+ virErrorPtr err = virGetLastError();
+ VIR_ERROR(_("Failed to allocate pciDeviceList: %s\n"),
+ err ? err->message : "");
+ virResetError(err);
+ return;
+ }
+
+ /* Again 3 loops; mark all devices as inactive before reset
+ * them and reset all the devices before re-attach */
+
+ for (i = 0; i < pcidevs->count; i++)
+ pciDeviceListDel(conn, driver->activePciHostdevs, pcidevs->devs[i]);
+
+ for (i = 0; i < pcidevs->count; i++)
+ if (pciResetDevice(conn, pcidevs->devs[i],
+ driver->activePciHostdevs) < 0) {
virErrorPtr err = virGetLastError();
- VIR_ERROR(_("Failed to allocate pciDevice: %s\n"),
+ VIR_ERROR(_("Failed to reset PCI device: %s\n"),
err ? err->message : "");
virResetError(err);
- continue;
}
- if (pciReAttachDevice(conn, dev) < 0) {
+ for (i = 0; i < pcidevs->count; i++)
+ if (pciDeviceGetManaged(pcidevs->devs[i]) &&
+ pciReAttachDevice(conn, pcidevs->devs[i]) < 0) {
virErrorPtr err = virGetLastError();
VIR_ERROR(_("Failed to re-attach PCI device: %s\n"),
err ? err->message : "");
virResetError(err);
}
- pciFreeDevice(conn, dev);
- }
+ pciDeviceListFree(conn, pcidevs);
}
static int qemudDomainSetSecurityLabel(virConnectPtr conn, struct qemud_driver *driver, virDomainObjPtr vm)
@@ -1468,7 +1503,7 @@ static int qemudStartVMDaemon(virConnectPtr conn,
&qemuCmdFlags) < 0)
goto cleanup;
- if (qemuPrepareHostDevices(conn, vm->def) < 0)
+ if (qemuPrepareHostDevices(conn, driver, vm->def) < 0)
goto cleanup;
vm->def->id = driver->nextvmid++;
@@ -1634,7 +1669,7 @@ static void qemudShutdownVMDaemon(virConnectPtr conn ATTRIBUTE_UNUSED,
VIR_FREE(vm->def->seclabel.imagelabel);
}
- qemuDomainReAttachHostDevices(conn, vm->def);
+ qemuDomainReAttachHostDevices(conn, driver, vm->def);
if (qemudRemoveDomainStatus(conn, driver, vm) < 0) {
VIR_WARN(_("Failed to remove domain status for %s"),
@@ -5247,6 +5282,7 @@ out:
static int
qemudNodeDeviceReset (virNodeDevicePtr dev)
{
+ struct qemud_driver *driver = dev->conn->privateData;
pciDevice *pci;
unsigned domain, bus, slot, function;
int ret = -1;
@@ -5258,11 +5294,14 @@ qemudNodeDeviceReset (virNodeDevicePtr dev)
if (!pci)
return -1;
- if (pciResetDevice(dev->conn, pci) < 0)
+ qemuDriverLock(driver);
+
+ if (pciResetDevice(dev->conn, pci, driver->activePciHostdevs) < 0)
goto out;
ret = 0;
out:
+ qemuDriverUnlock(driver);
pciFreeDevice(dev->conn, pci);
return ret;
}
diff --git a/src/xen_unified.c b/src/xen_unified.c
index e708980..ba8c769 100644
--- a/src/xen_unified.c
+++ b/src/xen_unified.c
@@ -1529,7 +1529,7 @@ xenUnifiedNodeDeviceReset (virNodeDevicePtr dev)
if (!pci)
return -1;
- if (pciResetDevice(dev->conn, pci) < 0)
+ if (pciResetDevice(dev->conn, pci, NULL) < 0)
goto out;
ret = 0;
--
1.6.2.5
@@ -0,0 +1,121 @@
From d79f35fbd4eaf610972621b042993d00f3247d5c Mon Sep 17 00:00:00 2001
From: Mark McLoughlin <markmc@redhat.com>
Date: Fri, 14 Aug 2009 08:31:11 +0100
Subject: [PATCH] Allow PM reset on multi-function PCI devices
https://bugzilla.redhat.com/515689
It turns out that a PCI Power Management reset only affects individual
functions, and not the whole device.
The PCI Power Management spec talks about resetting the 'device' rather
than the 'function', but Intel's Dexuan Cui informs me that it is
actually a per-function reset.
Also, Yu Zhao has added pci_pm_reset() to the kernel, and it doesn't
reject multi-function devices, so it must be true! :-)
(A side issue is that we could defer the PM reset to the kernel if we
could detect that the kernel has PM reset support, but barring version
number checks we don't have a way to detect that support)
* src/pci.c: remove the pciDeviceContainsOtherFunctions() check from
pciTryPowerManagementReset() and prefer PM reset over bus reset
where both are available
Cc: Cui, Dexuan <dexuan.cui@intel.com>
Cc: Yu Zhao <yu.zhao@intel.com>
(cherry picked from commit 64a6682b93a2a8aa38067a43979c9eaf993d2b41)
Fedora-patch: libvirt-allow-pm-reset-on-multi-function-pci-devices.patch
---
src/pci.c | 48 +++++++++---------------------------------------
1 files changed, 9 insertions(+), 39 deletions(-)
diff --git a/src/pci.c b/src/pci.c
index 68a380d..f78ab9f 100644
--- a/src/pci.c
+++ b/src/pci.c
@@ -397,29 +397,6 @@ pciBusContainsOtherDevices(virConnectPtr conn, pciDevice *dev)
return 1;
}
-/* Any other functions on this device ? */
-static int
-pciSharesDevice(pciDevice *a, pciDevice *b)
-{
- return
- a->domain == b->domain &&
- a->bus == b->bus &&
- a->slot == b->slot &&
- a->function != b->function;
-}
-
-static int
-pciDeviceContainsOtherFunctions(virConnectPtr conn, pciDevice *dev)
-{
- pciDevice *matched = NULL;
- if (pciIterDevices(conn, pciSharesDevice, dev, &matched) < 0)
- return 1;
- if (!matched)
- return 0;
- pciFreeDevice(conn, matched);
- return 1;
-}
-
/* Is @a the parent of @b ? */
static int
pciIsParent(pciDevice *a, pciDevice *b)
@@ -524,7 +501,7 @@ out:
* above we require the device supports a full internal reset.
*/
static int
-pciTryPowerManagementReset(virConnectPtr conn, pciDevice *dev)
+pciTryPowerManagementReset(virConnectPtr conn ATTRIBUTE_UNUSED, pciDevice *dev)
{
uint8_t config_space[PCI_CONF_LEN];
uint32_t ctl;
@@ -532,16 +509,6 @@ pciTryPowerManagementReset(virConnectPtr conn, pciDevice *dev)
if (!dev->pci_pm_cap_pos)
return -1;
- /* For now, we just refuse to do a power management reset
- * if there are other functions on this device.
- * In future, we could allow it so long as those functions
- * are not in use by the host or other guests.
- */
- if (pciDeviceContainsOtherFunctions(conn, dev)) {
- VIR_WARN("%s contains other functions, not resetting", dev->name);
- return -1;
- }
-
/* Save and restore the device's config space. */
if (pciRead(dev, 0, &config_space[0], PCI_CONF_LEN) < 0) {
VIR_WARN("Failed to save PCI config space for %s", dev->name);
@@ -599,14 +566,17 @@ pciResetDevice(virConnectPtr conn, pciDevice *dev)
if (dev->has_flr)
return 0;
+ /* If the device supports PCI power management reset,
+ * that's the next best thing because it only resets
+ * the function, not the whole device.
+ */
+ if (dev->has_pm_reset)
+ ret = pciTryPowerManagementReset(conn, dev);
+
/* Bus reset is not an option with the root bus */
- if (dev->bus != 0)
+ if (ret < 0 && dev->bus != 0)
ret = pciTrySecondaryBusReset(conn, dev);
- /* Next best option is a PCI power management reset */
- if (ret < 0 && dev->has_pm_reset)
- ret = pciTryPowerManagementReset(conn, dev);
-
if (ret < 0)
pciReportError(conn, VIR_ERR_NO_SUPPORT,
_("No PCI reset capability available for %s"),
--
1.6.2.5
@@ -0,0 +1,31 @@
From 1319852c443c432d44a2e73508f3be742027f780 Mon Sep 17 00:00:00 2001
From: Mark McLoughlin <markmc@redhat.com>
Date: Wed, 19 Aug 2009 11:28:02 +0100
Subject: [PATCH] Don't overwrite error in qemudWaitForMonitor()
May help diagnose https://bugzilla.redhat.com/515054
Fedora-patch: libvirt-do-not-overwrite-error-in-wait-for-monitor.patch
---
src/qemu_driver.c | 5 +++--
1 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
index dfd19c5..74e106a 100644
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -985,8 +985,9 @@ static int qemudWaitForMonitor(virConnectPtr conn,
return 0;
/* Unexpected end of file - inform user of QEMU log data */
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- _("unable to start guest: %s"), buf);
+ if (!virGetLastError())
+ qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+ _("unable to start guest: %s"), buf);
return -1;
}
--
1.6.2.5
@@ -0,0 +1,53 @@
From 2754da03d65f216271c81ece791b96a19272c812 Mon Sep 17 00:00:00 2001
From: Mark McLoughlin <markmc@redhat.com>
Date: Sat, 15 Aug 2009 19:38:15 +0100
Subject: [PATCH] Fix list updating after disk hot-unplug
The current code makes a poor effort at updating the device arrays after
hot-unplug. Fix that and combine the two code paths into one.
* src/qemu_driver.c: fix list updating in qemudDomainDetachPciDiskDevice()
(cherry picked from commit 4e12af5623e4a962a6bb911af06fa29aa85befba)
Fedora-patch: libvirt-fix-device-list-update-after-detach.patch
---
src/qemu_driver.c | 21 ++++++++++-----------
1 files changed, 10 insertions(+), 11 deletions(-)
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
index dfd19c5..ce04beb 100644
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -4123,18 +4123,17 @@ try_command:
goto cleanup;
}
- if (vm->def->ndisks > 1) {
- vm->def->disks[i] = vm->def->disks[--vm->def->ndisks];
- if (VIR_REALLOC_N(vm->def->disks, vm->def->ndisks) < 0) {
- virReportOOMError(conn);
- goto cleanup;
- }
- qsort(vm->def->disks, vm->def->ndisks, sizeof(*vm->def->disks),
- virDomainDiskQSort);
- } else {
- VIR_FREE(vm->def->disks[0]);
- vm->def->ndisks = 0;
+ if (i != --vm->def->ndisks)
+ memmove(&vm->def->disks[i],
+ &vm->def->disks[i+1],
+ sizeof(*vm->def->disks) * (vm->def->ndisks-i));
+ if (VIR_REALLOC_N(vm->def->disks, vm->def->ndisks) < 0) {
+ virReportOOMError(conn);
+ goto cleanup;
}
+ qsort(vm->def->disks, vm->def->ndisks, sizeof(*vm->def->disks),
+ virDomainDiskQSort);
+
ret = 0;
cleanup:
--
1.6.2.5
@@ -0,0 +1,45 @@
From 21ef933dfdd64c754d184d41d87ecd94eaddf697 Mon Sep 17 00:00:00 2001
From: Chris Lalancette <clalance@redhat.com>
Date: Wed, 5 Aug 2009 13:42:07 +0200
Subject: [PATCH] Run 'cont' on successful migration finish.
https://bugzilla.redhat.com/516187
As of qemu 0.10.6, qemu now honors the -S flag on incoming migration.
That means that when the migration completes, we have to issue a
'cont' command to get the VM running again. We do it unconditionally
since it won't hurt on older qemu.
(cherry picked from commit d1ec4d7a5a4f50c9492137eaab4f021caa075f95)
Fedora-patch: libvirt-fix-migration-completion-with-newer-qemu.patch
---
src/qemu_driver.c | 11 +++++++++++
1 files changed, 11 insertions(+), 0 deletions(-)
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
index 7dbf4a2..ff56f61 100644
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -5162,7 +5162,18 @@ qemudDomainMigrateFinish2 (virConnectPtr dconn,
*/
if (retcode == 0) {
dom = virGetDomain (dconn, vm->def->name, vm->def->uuid);
+
+ /* run 'cont' on the destination, which allows migration on qemu
+ * >= 0.10.6 to work properly. This isn't strictly necessary on
+ * older qemu's, but it also doesn't hurt anything there
+ */
+ if (qemudMonitorCommand(vm, "cont", &info) < 0) {
+ qemudReportError(dconn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+ "%s", _("resume operation failed"));
+ goto cleanup;
+ }
VIR_FREE(info);
+
vm->state = VIR_DOMAIN_RUNNING;
event = virDomainEventNewFromObj(vm,
VIR_DOMAIN_EVENT_RESUMED,
--
1.6.2.5
@@ -0,0 +1,61 @@
From ea544e7b038776c7db555ab0428b63ebb1604163 Mon Sep 17 00:00:00 2001
From: Darryl L. Pierce <dpierce@redhat.com>
Date: Fri, 21 Aug 2009 16:57:29 +0200
Subject: [PATCH] 517157 fix selinux problem with images on NFS
* src/security_selinux.c: ignores EOPNOTSUPP when attempting to access an
NFS share
(cherry picked from commit 777fc2e9d60844a7387355d9cef06bd25190d146)
Fedora-patch: libvirt-fix-selinux-problem-with-images-on-nfs.patch
---
src/security_selinux.c | 25 +++++++++++++++++--------
1 files changed, 17 insertions(+), 8 deletions(-)
diff --git a/src/security_selinux.c b/src/security_selinux.c
index 8ebe1fe..97f16b3 100644
--- a/src/security_selinux.c
+++ b/src/security_selinux.c
@@ -285,6 +285,8 @@ SELinuxSetFilecon(virConnectPtr conn, const char *path, char *tcon)
VIR_INFO("Setting SELinux context on '%s' to '%s'", path, tcon);
if (setfilecon(path, tcon) < 0) {
+ int setfilecon_errno = errno;
+
if (getfilecon(path, &econ) >= 0) {
if (STREQ(tcon, econ)) {
freecon(econ);
@@ -293,14 +295,21 @@ SELinuxSetFilecon(virConnectPtr conn, const char *path, char *tcon)
}
freecon(econ);
}
- virSecurityReportError(conn, VIR_ERR_ERROR,
- _("%s: unable to set security context "
- "'\%s\' on %s: %s."), __func__,
- tcon,
- path,
- virStrerror(errno, ebuf, sizeof ebuf));
- if (security_getenforce() == 1)
- return -1;
+
+ /* if the error complaint is related to an image hosted on
+ * an nfs mount, then ignore it.
+ * rhbz 517157
+ */
+ if (setfilecon_errno != EOPNOTSUPP) {
+ virSecurityReportError(conn, VIR_ERR_ERROR,
+ _("%s: unable to set security context "
+ "'\%s\' on %s: %s."), __func__,
+ tcon,
+ path,
+ virStrerror(errno, ebuf, sizeof ebuf));
+ if (security_getenforce() == 1)
+ return -1;
+ }
}
return 0;
}
--
1.6.2.5
@@ -0,0 +1,38 @@
From 0878a15ad937449b5dfc4cf49888cc7753473e33 Mon Sep 17 00:00:00 2001
From: Daniel Veillard <veillard@redhat.com>
Date: Fri, 26 Jun 2009 18:14:16 +0000
Subject: [PATCH] Fix xen driver segfault with newer Xen
https://bugzilla.redhat.com/518091
(cherry picked from commit 14435163a086c0bcdff04308077fa46a5fa08bb0)
Fedora-patch: libvirt-fix-xen-driver-segfault-with-newer-xen.patch
---
src/xend_internal.c | 10 +++++++++-
1 files changed, 9 insertions(+), 1 deletions(-)
diff --git a/src/xend_internal.c b/src/xend_internal.c
index 2e2fd21..c3a9836 100644
--- a/src/xend_internal.c
+++ b/src/xend_internal.c
@@ -2077,7 +2077,15 @@ xenDaemonParseSxprGraphicsNew(virConnectPtr conn,
if (sexpr_lookup(node, "device/vfb")) {
/* New style graphics config for PV guests in >= 3.0.4,
* or for HVM guests in >= 3.0.5 */
- tmp = sexpr_node(node, "device/vfb/type");
+ if (sexpr_node(node, "device/vfb/type")) {
+ tmp = sexpr_node(node, "device/vfb/type");
+ } else if (sexpr_node(node, "device/vfb/vnc")) {
+ tmp = "vnc";
+ } else if (sexpr_node(node, "device/vfb/sdl")) {
+ tmp = "sdl";
+ } else {
+ tmp = "unknown";
+ }
if (VIR_ALLOC(graphics) < 0)
goto no_memory;
--
1.6.2.5
@@ -0,0 +1,141 @@
From 9f80bab3829b97ac2802c15b9f3e4a6bbbb24627 Mon Sep 17 00:00:00 2001
From: Mark McLoughlin <markmc@redhat.com>
Date: Fri, 14 Aug 2009 08:31:11 +0100
Subject: [PATCH] Improve PCI host device reset error message
https://bugzilla.redhat.com/499678
Currently, if we are unable to reset a PCI device we return a fairly
generic 'No PCI reset capability available' error message.
Fix that by returning an error from the individual reset messages and
using that error to construct the higher level error mesage.
* src/pci.c: set errors in pciTryPowerManagementReset() and
pciTrySecondaryBusReset() on failure; use those error messages
in pciResetDevice(), or explain that no reset support is available
(cherry picked from commit ebea34185612c3b96d7d3bbd8b7c2ce6c9f4fe6f)
Fedora-patch: libvirt-improve-pci-hostdev-reset-error-message.patch
---
src/pci.c | 44 +++++++++++++++++++++++++++++++-------------
src/qemu_driver.c | 4 ++--
2 files changed, 33 insertions(+), 15 deletions(-)
diff --git a/src/pci.c b/src/pci.c
index f78ab9f..1dddb08 100644
--- a/src/pci.c
+++ b/src/pci.c
@@ -451,15 +451,18 @@ pciTrySecondaryBusReset(virConnectPtr conn, pciDevice *dev)
* are not in use by the host or other guests.
*/
if (pciBusContainsOtherDevices(conn, dev)) {
- VIR_WARN("Other devices on bus with %s, not doing bus reset",
- dev->name);
+ pciReportError(conn, VIR_ERR_NO_SUPPORT,
+ _("Other devices on bus with %s, not doing bus reset"),
+ dev->name);
return -1;
}
/* Find the parent bus */
parent = pciGetParentDevice(conn, dev);
if (!parent) {
- VIR_WARN("Failed to find parent device for %s", dev->name);
+ pciReportError(conn, VIR_ERR_NO_SUPPORT,
+ _("Failed to find parent device for %s"),
+ dev->name);
return -1;
}
@@ -470,7 +473,9 @@ pciTrySecondaryBusReset(virConnectPtr conn, pciDevice *dev)
* are multiple devices/functions
*/
if (pciRead(dev, 0, config_space, PCI_CONF_LEN) < 0) {
- VIR_WARN("Failed to save PCI config space for %s", dev->name);
+ pciReportError(conn, VIR_ERR_NO_SUPPORT,
+ _("Failed to save PCI config space for %s"),
+ dev->name);
goto out;
}
@@ -487,9 +492,12 @@ pciTrySecondaryBusReset(virConnectPtr conn, pciDevice *dev)
usleep(200 * 1000); /* sleep 200ms */
- if (pciWrite(dev, 0, config_space, PCI_CONF_LEN) < 0)
- VIR_WARN("Failed to restore PCI config space for %s", dev->name);
-
+ if (pciWrite(dev, 0, config_space, PCI_CONF_LEN) < 0) {
+ pciReportError(conn, VIR_ERR_NO_SUPPORT,
+ _("Failed to restore PCI config space for %s"),
+ dev->name);
+ goto out;
+ }
ret = 0;
out:
pciFreeDevice(conn, parent);
@@ -511,7 +519,9 @@ pciTryPowerManagementReset(virConnectPtr conn ATTRIBUTE_UNUSED, pciDevice *dev)
/* Save and restore the device's config space. */
if (pciRead(dev, 0, &config_space[0], PCI_CONF_LEN) < 0) {
- VIR_WARN("Failed to save PCI config space for %s", dev->name);
+ pciReportError(conn, VIR_ERR_NO_SUPPORT,
+ _("Failed to save PCI config space for %s"),
+ dev->name);
return -1;
}
@@ -528,8 +538,12 @@ pciTryPowerManagementReset(virConnectPtr conn ATTRIBUTE_UNUSED, pciDevice *dev)
usleep(10 * 1000); /* sleep 10ms */
- if (pciWrite(dev, 0, &config_space[0], PCI_CONF_LEN) < 0)
- VIR_WARN("Failed to restore PCI config space for %s", dev->name);
+ if (pciWrite(dev, 0, &config_space[0], PCI_CONF_LEN) < 0) {
+ pciReportError(conn, VIR_ERR_NO_SUPPORT,
+ _("Failed to restore PCI config space for %s"),
+ dev->name);
+ return -1;
+ }
return 0;
}
@@ -577,10 +591,14 @@ pciResetDevice(virConnectPtr conn, pciDevice *dev)
if (ret < 0 && dev->bus != 0)
ret = pciTrySecondaryBusReset(conn, dev);
- if (ret < 0)
+ if (ret < 0) {
+ virErrorPtr err = virGetLastError();
pciReportError(conn, VIR_ERR_NO_SUPPORT,
- _("No PCI reset capability available for %s"),
- dev->name);
+ _("Unable to reset PCI device %s: %s"),
+ dev->name,
+ err ? err->message : _("no FLR, PM reset or bus reset available"));
+ }
+
return ret;
}
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
index ddd3693..9f87d2a 100644
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -1345,9 +1345,9 @@ qemuDomainReAttachHostDevices(virConnectPtr conn, virDomainDefPtr def)
continue;
}
- if (pciDettachDevice(conn, dev) < 0) {
+ if (pciReAttachDevice(conn, dev) < 0) {
virErrorPtr err = virGetLastError();
- VIR_ERROR(_("Failed to reset PCI device: %s\n"),
+ VIR_ERROR(_("Failed to re-attach PCI device: %s\n"),
err ? err->message : "");
virResetError(err);
}
--
1.6.2.5
@@ -0,0 +1,124 @@
From 1e44604c0d4c2d4c1347c2a1027f1ea02a6499f9 Mon Sep 17 00:00:00 2001
From: Mark McLoughlin <markmc@redhat.com>
Date: Fri, 14 Aug 2009 08:31:11 +0100
Subject: [PATCH] Reset and re-attach PCI host devices on guest shutdown
https://bugzilla.redhat.com/499561
When the guest shuts down, we should attempt to restore all PCI host
devices to a sane state.
In the case of managed hostdevs, we should reset and re-attach the
devices. In the case of unmanaged hostdevs, we should just reset them.
Note, KVM will already reset assigned devices when the guest shuts
down using whatever means it can, so we are only doing it to cover the
cases the kernel can't handle.
* src/qemu_driver.c: add qemuDomainReAttachHostDevices() and call
it from qemudShutdownVMDaemon()
(cherry picked from commit 4035152a8767e72fd4e26a91cb4d5afa75b72e61)
Fedora-patch: libvirt-reattach-pci-hostdevs-after-guest-shutdown.patch
---
src/qemu_driver.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 76 insertions(+), 0 deletions(-)
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
index ce04beb..ddd3693 100644
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -1282,6 +1282,80 @@ error:
return -1;
}
+static void
+qemuDomainReAttachHostDevices(virConnectPtr conn, virDomainDefPtr def)
+{
+ int i;
+
+ /* Again 2 loops; reset all the devices before re-attach */
+
+ for (i = 0 ; i < def->nhostdevs ; i++) {
+ virDomainHostdevDefPtr hostdev = def->hostdevs[i];
+ pciDevice *dev;
+
+ if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
+ continue;
+ if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
+ continue;
+
+ dev = pciGetDevice(conn,
+ hostdev->source.subsys.u.pci.domain,
+ hostdev->source.subsys.u.pci.bus,
+ hostdev->source.subsys.u.pci.slot,
+ hostdev->source.subsys.u.pci.function);
+ if (!dev) {
+ virErrorPtr err = virGetLastError();
+ VIR_ERROR(_("Failed to allocate pciDevice: %s\n"),
+ err ? err->message : "");
+ virResetError(err);
+ continue;
+ }
+
+ if (pciResetDevice(conn, dev) < 0) {
+ virErrorPtr err = virGetLastError();
+ VIR_ERROR(_("Failed to reset PCI device: %s\n"),
+ err ? err->message : "");
+ virResetError(err);
+ }
+
+ pciFreeDevice(conn, dev);
+ }
+
+ for (i = 0 ; i < def->nhostdevs ; i++) {
+ virDomainHostdevDefPtr hostdev = def->hostdevs[i];
+ pciDevice *dev;
+
+ if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
+ continue;
+ if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
+ continue;
+ if (!hostdev->managed)
+ continue;
+
+ dev = pciGetDevice(conn,
+ hostdev->source.subsys.u.pci.domain,
+ hostdev->source.subsys.u.pci.bus,
+ hostdev->source.subsys.u.pci.slot,
+ hostdev->source.subsys.u.pci.function);
+ if (!dev) {
+ virErrorPtr err = virGetLastError();
+ VIR_ERROR(_("Failed to allocate pciDevice: %s\n"),
+ err ? err->message : "");
+ virResetError(err);
+ continue;
+ }
+
+ if (pciDettachDevice(conn, dev) < 0) {
+ virErrorPtr err = virGetLastError();
+ VIR_ERROR(_("Failed to reset PCI device: %s\n"),
+ err ? err->message : "");
+ virResetError(err);
+ }
+
+ pciFreeDevice(conn, dev);
+ }
+}
+
static int qemudDomainSetSecurityLabel(virConnectPtr conn, struct qemud_driver *driver, virDomainObjPtr vm)
{
if (vm->def->seclabel.label != NULL)
@@ -1560,6 +1634,8 @@ static void qemudShutdownVMDaemon(virConnectPtr conn ATTRIBUTE_UNUSED,
VIR_FREE(vm->def->seclabel.imagelabel);
}
+ qemuDomainReAttachHostDevices(conn, vm->def);
+
if (qemudRemoveDomainStatus(conn, driver, vm) < 0) {
VIR_WARN(_("Failed to remove domain status for %s"),
vm->def->name);
--
1.6.2.5
+893 -2102
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1 +1 @@
SHA512 (libvirt-3.7.0.tar.xz) = b3f7021ef4c6954430f8fa503f0c49e3df4f662b228cb631ba2c2139ecec2307dde6cec05037cc28663e82ab1001296c20c5c68acd183cd364dd484a7746f498
3035b484861516a1cd425acef1e760e3 libvirt-0.6.2.tar.gz