Compare commits
296 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9e23d5e3a9 | |||
| c5bb6a7965 | |||
| ac335adbbc | |||
| 7294ce1ae2 | |||
| c23de3143a | |||
| 7042f56045 | |||
| 2a9c282548 | |||
| 2ae80af461 | |||
| 7335ede0e1 | |||
| 6c92ba3805 | |||
| 446f680673 | |||
| 3f56aa2870 | |||
| 3cec91694f | |||
| cb0cfa566f | |||
| a27acebf66 | |||
| 99d3a0ca1a | |||
| 9c962ebc4f | |||
| 99cbbf6606 | |||
| b73e509648 | |||
| b23ff9c0f7 | |||
| 20f9ed9c4c | |||
| 04cb28c315 | |||
| a74ea318d1 | |||
| 98ed6b4e36 | |||
| 2c49d1fd11 | |||
| 6e7bca6631 | |||
| 2fe145bb02 | |||
| 10b7d235e3 | |||
| 232e2e7de2 | |||
| fb1e4b061e | |||
| 0b1a013081 | |||
| a972457f43 | |||
| 67cfa34a05 | |||
| fc2ebb7646 | |||
| e92b461b4f | |||
| b1ac7b5791 | |||
| 88424efe85 | |||
| 4e2aab98a2 | |||
| f4bc1a2fe2 | |||
| a4bf2768b8 | |||
| 47cd44e9da | |||
| 731c6b90ff | |||
| 47ca46905d | |||
| 860ffc5b13 | |||
| 611b2ee520 | |||
| edcb926f9d | |||
| caebff8304 | |||
| 8fa41135ca | |||
| 0debbff964 | |||
| d6cc78be66 | |||
| 8d9645735e | |||
| 4c65f08330 | |||
| 2427f8f078 | |||
| d168e4f934 | |||
| 4dd365589f | |||
| 50e253df29 | |||
| cb71801a2b | |||
| 4a9c74e91d | |||
| 281508ec99 | |||
| feb92626e1 | |||
| 93cadb0880 | |||
| dd6b57aa60 | |||
| b8cb754e9d | |||
| dbe61507bd | |||
| ce7b23d9d0 | |||
| 8ded6ff93e | |||
| 1ef96f3488 | |||
| ee3bf37900 | |||
| 7452a06938 | |||
| fe8f9ed9c4 | |||
| 1b64f74c82 | |||
| c81949046d | |||
| 19dcb913e6 | |||
| e4b5ba1a9d | |||
| 5f1a422d83 | |||
| c5b0b3ef9d | |||
| c0a04cb876 | |||
| 3cc7cdf12f | |||
| 6b531d9967 | |||
| 4d05ac021c | |||
| d29aa84b17 | |||
| a075adc818 | |||
| 4d0e63f99c | |||
| 9e11936ec5 | |||
| a4075ec632 | |||
| dadb59c95f | |||
| e73cc6a9d8 | |||
| 10cd84e37f | |||
| e63e2040cd | |||
| 91063332d7 | |||
| 503330ba5d | |||
| 0a64085f47 | |||
| 1073e2447a | |||
| 5b1a906ace | |||
| aff97e0146 | |||
| a4b41a378b | |||
| 3ec523d168 | |||
| 622cf0d642 | |||
| a540751e83 | |||
| 11b596669a | |||
| fefbae879b | |||
| 695b281409 | |||
| 9f9eae34c1 | |||
| ae37ed3500 | |||
| f7f509999b | |||
| 419bcc4b2f | |||
| 7b59d4f7eb | |||
| 03326e9c04 | |||
| f40b464d1e | |||
| 810ca6c207 | |||
| 8df3aef6aa | |||
| 0223d5a656 | |||
| aad810a204 | |||
| 1b8b7567b1 | |||
| 442040caac | |||
| 65efaafca2 | |||
| e87c8ab0c7 | |||
| be6bda45b4 | |||
| 8c9e40d383 | |||
| 0f6f9b973a | |||
| 3db6039b2b | |||
| 4051217c8b | |||
| c5c28baba1 | |||
| 43618df1d4 | |||
| a2951dccb5 | |||
| b884323c03 | |||
| adeaf839fd | |||
| 40d99010e1 | |||
| 11755d8663 | |||
| 2daa92daf9 | |||
| db2858c661 | |||
| 53adb9aaba | |||
| 168df8b606 | |||
| f9085f2538 | |||
| b159bbdc98 | |||
| a5af3cf105 | |||
| 27ca069db7 | |||
| 000a3274d2 | |||
| 19c7799c31 | |||
| 198ff818c6 | |||
| e80c83ad06 | |||
| 660e0112c6 | |||
| 45c1cabef6 | |||
| 56be2c5e38 | |||
| 4aa9c4f1a3 | |||
| 7be420ad22 | |||
| 40b00623a4 | |||
| ce09ec66c7 | |||
| 97d7c80e2e | |||
| b856ae03bf | |||
| 803b3b891a | |||
| 350081d1a9 | |||
| 1b71b68bb9 | |||
| 4084288dd5 | |||
| d1cd1b7ceb | |||
| 5ed69704b9 | |||
| be6e136cb1 | |||
| d3109abfa4 | |||
| f5ff4a2393 | |||
| 8cc50838dc | |||
| 2c2e71c0ce | |||
| 96b1b18b42 | |||
| f7763bfd17 | |||
| 404e58cb18 | |||
| cd3767e3b9 | |||
| f1867a5ecc | |||
| b5548f62cb | |||
| 52f3bedee7 | |||
| f87237919c | |||
| e8969fb913 | |||
| 74d46bc7dd | |||
| 4b6ea94306 | |||
| 963754bc8c | |||
| 7b5483236c | |||
| 438006407c | |||
| 76c8282ee2 | |||
| f463598b24 | |||
| f4e752a385 | |||
| c37cb21dea | |||
| e0bfc1f8aa | |||
| 544ad4a787 | |||
| 8f163760ed | |||
| 565427cf89 | |||
| e10da2f6d4 | |||
| aa386576d5 | |||
| c73c129b48 | |||
| afe729ac3c | |||
| b6038bae4f | |||
| e6d9787587 | |||
| 44699dc495 | |||
| 991d719dde | |||
| 96a520b555 | |||
| e31df5e9de | |||
| 6763b267b9 | |||
| 24e91208a4 | |||
| 15dec999e7 | |||
| d6b0635d3d | |||
| 336a93264e | |||
| 6398d1cff5 | |||
| 6926ed26ea | |||
| 6253f97a2d | |||
| 37ddbd0eac | |||
| 95fe7c8df2 | |||
| 79ae809020 | |||
| f19e302ba9 | |||
| e9c1d3f4b0 | |||
| 0f577d932b | |||
| 21a02c2e90 | |||
| 4e460d5f09 | |||
| f9de2f6bc6 | |||
| 2daa1b7814 | |||
| f99eeb8567 | |||
| 7069f75cb8 | |||
| 2cac7dac46 | |||
| 913c3c6554 | |||
| a5a4c0c89b | |||
| 8c8aca2fab | |||
| daf8e124ca | |||
| 38c4b724fe | |||
| 4d00487275 | |||
| a6831c26c1 | |||
| c363c7ebdb | |||
| 18ee6daf8a | |||
| 459eb426c3 | |||
| a0d670d2bf | |||
| d7b41212c1 | |||
| 2e1539eba4 | |||
| ee9521d87c | |||
| 8d8fc08bac | |||
| e79d304c79 | |||
| db03f03fd9 | |||
| 957403ebec | |||
| 6c32e1aaeb | |||
| 362e335c0b | |||
| ed6c49f874 | |||
| 47fcec5405 | |||
| d7239a45b6 | |||
| f13fb18c58 | |||
| d29644418d | |||
| ed9e426b26 | |||
| 659febf9ff | |||
| fca1fccfad | |||
| f713d63bab | |||
| 5a45e466cf | |||
| 742b24eb23 | |||
| 03369d2383 | |||
| 2605d662e0 | |||
| e8394ab5b5 | |||
| 8ad156a5c2 | |||
| f2d6fb6239 | |||
| e3a592c38d | |||
| 7e99819dda | |||
| a160d7f98d | |||
| 36cab842e8 | |||
| 7b7b86e327 | |||
| f4bfe638b6 | |||
| 0e9d242f05 | |||
| e24467a8c2 | |||
| b39c370a76 | |||
| 62e4e7cde2 | |||
| f822179f97 | |||
| 47e7e1e548 | |||
| e73b75314b | |||
| 8193a55b4a | |||
| 6036708fa2 | |||
| 4717aa0b6d | |||
| 97ae25ea7d | |||
| 6470ed033b | |||
| b550f9c1d5 | |||
| ee0273ffc3 | |||
| 50fce74b00 | |||
| e29f71d1c9 | |||
| 427ed20801 | |||
| d23e6c285b | |||
| 2c139b45d8 | |||
| 762435e3b7 | |||
| 6383d6b056 | |||
| 3712441ea6 | |||
| 9d0bc882fa | |||
| 90dddf3d3d | |||
| 86abd54d02 | |||
| 4ab5ad5425 | |||
| f9c1b758c3 | |||
| 38cf1bd5ba | |||
| aeda455930 | |||
| 288291b795 | |||
| 7c2073faca | |||
| 5b528ba717 | |||
| 4f731a7250 | |||
| f1ac0031f5 | |||
| e45b9c9030 | |||
| 3cf75c269d | |||
| 585033f372 | |||
| 897506e66a | |||
| e4bf8ffa42 | |||
| 20367a58a6 |
-14
@@ -1,14 +0,0 @@
|
||||
.build*.log
|
||||
*.rpm
|
||||
i686
|
||||
x86_64
|
||||
libvirt-*.tar.gz
|
||||
libvirt-0.6.0.tar.gz
|
||||
libvirt-0.6.1.tar.gz
|
||||
libvirt-0.6.2.tar.gz
|
||||
libvirt-0.6.3.tar.gz
|
||||
libvirt-0.6.4.tar.gz
|
||||
libvirt-0.6.5.tar.gz
|
||||
libvirt-0.7.0-0.1.gitf055724.tar.gz
|
||||
libvirt-0.7.0-0.6.gite195b43.tar.gz
|
||||
libvirt-0.7.0.tar.gz
|
||||
@@ -0,0 +1,5 @@
|
||||
.build*.log
|
||||
*.rpm
|
||||
i686
|
||||
x86_64
|
||||
libvirt-*.tar.xz
|
||||
@@ -0,0 +1,34 @@
|
||||
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);
|
||||
@@ -0,0 +1,108 @@
|
||||
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 \
|
||||
@@ -0,0 +1,101 @@
|
||||
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;
|
||||
@@ -0,0 +1,72 @@
|
||||
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 \
|
||||
@@ -0,0 +1,177 @@
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
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);
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
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",
|
||||
@@ -0,0 +1,63 @@
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
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
|
||||
@@ -0,0 +1,126 @@
|
||||
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>
|
||||
@@ -0,0 +1,133 @@
|
||||
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",
|
||||
@@ -0,0 +1,36 @@
|
||||
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__ */
|
||||
@@ -0,0 +1,49 @@
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
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);
|
||||
@@ -0,0 +1,27 @@
|
||||
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);
|
||||
@@ -0,0 +1,121 @@
|
||||
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;
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
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
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
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
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
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
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
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
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
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
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
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
|
||||
|
||||
@@ -0,0 +1,535 @@
|
||||
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
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
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
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
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
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
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
|
||||
|
||||
@@ -4,7 +4,7 @@ NAME := libvirt
|
||||
SPECFILE = $(firstword $(wildcard *.spec))
|
||||
|
||||
define find-makefile-common
|
||||
for d in common ../common ../../common ; do if [ -f $$d/Makefile.common ] ; then if [ -f $$d/CVS/Root -a -w $$/Makefile.common ] ; then cd $$d ; cvs -Q update ; fi ; echo "$$d/Makefile.common" ; break ; fi ; done
|
||||
for d in common ../common ../../common ; do if [ -f $$d/Makefile.common ] ; then if [ -f $$d/CVS/Root -a -w $$d/Makefile.common ] ; then cd $$d ; cvs -Q update ; fi ; echo "$$d/Makefile.common" ; break ; fi ; done
|
||||
endef
|
||||
|
||||
MAKEFILE_COMMON := $(shell $(find-makefile-common))
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
From 5f8d720b5f1393ee333a5fa8375ffe9ac954d48b Mon Sep 17 00:00:00 2001
|
||||
From: Daniel P. Berrange <berrange@redhat.com>
|
||||
Date: Mon, 17 Aug 2009 08:32:08 +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.4-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 6b0b404..53186e0 100644
|
||||
--- a/src/qemu_conf.c
|
||||
+++ b/src/qemu_conf.c
|
||||
@@ -1384,6 +1384,20 @@ int qemudBuildCommandLine(virConnectPtr conn,
|
||||
char uuid[VIR_UUID_STRING_BUFLEN];
|
||||
char domid[50];
|
||||
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 (def->nsounds &&
|
||||
+ !soundWarned) {
|
||||
+ soundWarned = 1;
|
||||
+ VIR_WARN0("Sound cards for VMs are disabled while SELinux security model is active");
|
||||
+ }
|
||||
+ }
|
||||
|
||||
uname_normalize(&ut);
|
||||
|
||||
@@ -2015,7 +2029,8 @@ int qemudBuildCommandLine(virConnectPtr conn,
|
||||
}
|
||||
|
||||
/* Add sound hardware */
|
||||
- if (def->nsounds) {
|
||||
+ if (def->nsounds &&
|
||||
+ !skipSound) {
|
||||
int size = 100;
|
||||
char *modstr;
|
||||
if (VIR_ALLOC_N(modstr, size+1) < 0)
|
||||
--
|
||||
1.6.2.5
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
From 541cfdf5465ac3bba2c0c0901950547bc6638e47 Mon Sep 17 00:00:00 2001
|
||||
From: Mark McLoughlin <markmc@redhat.com>
|
||||
Date: Thu, 6 Aug 2009 15:14:19 +0100
|
||||
Subject: [PATCH] chown kernel/initrd before spawning qemu
|
||||
|
||||
If we're running qemu unprivileged, we need to chown any supplied kernel
|
||||
or initrd before spawning it.
|
||||
|
||||
* src/qemu_driver.c: rename qemuDomainSetDiskOwnership() to
|
||||
qemuDomainSetFileOwnership(), pass it a path string instead of a disk
|
||||
definition and use it for chowning the kernel/initrd in
|
||||
qemuDomainSetAllDeviceOwnership()
|
||||
|
||||
(cherry picked from commit c42b39784534930791d1feb3de859d85a7848168)
|
||||
|
||||
Fedora-patch: libvirt-0.7.0-chown-kernel-initrd-before-spawning-qemu.patch
|
||||
---
|
||||
src/qemu_driver.c | 20 ++++++++++++--------
|
||||
1 files changed, 12 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
|
||||
index 412b68d..bd58435 100644
|
||||
--- a/src/qemu_driver.c
|
||||
+++ b/src/qemu_driver.c
|
||||
@@ -1684,18 +1684,18 @@ static int qemuDomainSetHostdevOwnership(virConnectPtr conn,
|
||||
|
||||
}
|
||||
|
||||
-static int qemuDomainSetDiskOwnership(virConnectPtr conn,
|
||||
- virDomainDiskDefPtr def,
|
||||
+static int qemuDomainSetFileOwnership(virConnectPtr conn,
|
||||
+ const char *path,
|
||||
uid_t uid, gid_t gid)
|
||||
{
|
||||
|
||||
- if (!def->src)
|
||||
+ if (!path)
|
||||
return 0;
|
||||
|
||||
- VIR_DEBUG("Setting ownership on %s to %d:%d", def->src, uid, gid);
|
||||
- if (chown(def->src, uid, gid) < 0) {
|
||||
+ VIR_DEBUG("Setting ownership on %s to %d:%d", path, uid, gid);
|
||||
+ if (chown(path, uid, gid) < 0) {
|
||||
virReportSystemError(conn, errno, _("cannot set ownership on %s"),
|
||||
- def->src);
|
||||
+ path);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
@@ -1725,7 +1725,7 @@ static int qemuDomainSetDeviceOwnership(virConnectPtr conn,
|
||||
(def->data.disk->readonly || def->data.disk->shared))
|
||||
return 0;
|
||||
|
||||
- return qemuDomainSetDiskOwnership(conn, def->data.disk, uid, gid);
|
||||
+ return qemuDomainSetFileOwnership(conn, def->data.disk->src, uid, gid);
|
||||
|
||||
case VIR_DOMAIN_DEVICE_HOSTDEV:
|
||||
return qemuDomainSetHostdevOwnership(conn, def->data.hostdev, uid, gid);
|
||||
@@ -1753,12 +1753,16 @@ static int qemuDomainSetAllDeviceOwnership(virConnectPtr conn,
|
||||
uid = restore ? 0 : driver->user;
|
||||
gid = restore ? 0 : driver->group;
|
||||
|
||||
+ if (qemuDomainSetFileOwnership(conn, def->os.kernel, uid, gid) < 0 ||
|
||||
+ qemuDomainSetFileOwnership(conn, def->os.initrd, uid, gid) < 0)
|
||||
+ return -1;
|
||||
+
|
||||
for (i = 0 ; i < def->ndisks ; i++) {
|
||||
if (restore &&
|
||||
(def->disks[i]->readonly || def->disks[i]->shared))
|
||||
continue;
|
||||
|
||||
- if (qemuDomainSetDiskOwnership(conn, def->disks[i], uid, gid) < 0)
|
||||
+ if (qemuDomainSetFileOwnership(conn, def->disks[i]->src, uid, gid) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
--
|
||||
1.6.2.5
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
From ddf0a7cb04debe60825d11186e68cc6de6fd1dd2 Mon Sep 17 00:00:00 2001
|
||||
From: Mark McLoughlin <markmc@redhat.com>
|
||||
Date: Mon, 10 Aug 2009 11:16:37 +0100
|
||||
Subject: [PATCH] Handle kernels with no ipv6 support
|
||||
|
||||
If the ipv6 kernel module is not loaded, then we get this when starting
|
||||
a virtual network:
|
||||
|
||||
libvir: Network Config error :
|
||||
cannot enable /proc/sys/net/ipv6/conf/virbr0/disable_ipv6:
|
||||
No such file or directory
|
||||
|
||||
If disable_ipv6 is not present, we should just merrily continue on our
|
||||
way.
|
||||
|
||||
* src/network_driver.c: make networkDisableIPV6() not fail if the kernel
|
||||
has no ipv6 support
|
||||
|
||||
(cherry picked from commit f5a8f969dd92ec2744e1eec5d35288d5fbcded22)
|
||||
|
||||
Fedora-patch: libvirt-0.7.0-handle-kernels-with-no-ipv6-support.patch
|
||||
---
|
||||
src/network_driver.c | 6 ++++++
|
||||
1 files changed, 6 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/src/network_driver.c b/src/network_driver.c
|
||||
index eaea454..84910ab 100644
|
||||
--- a/src/network_driver.c
|
||||
+++ b/src/network_driver.c
|
||||
@@ -801,6 +801,12 @@ static int networkDisableIPV6(virConnectPtr conn,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
+ if (access(field, W_OK) < 0 && errno == ENOENT) {
|
||||
+ VIR_DEBUG("ipv6 appears to already be disabled on %s", network->def->bridge);
|
||||
+ ret = 0;
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+
|
||||
if (virFileWriteStr(field, "1") < 0) {
|
||||
virReportSystemError(conn, errno,
|
||||
_("cannot enable %s"), field);
|
||||
--
|
||||
1.6.2.5
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
From 663bf081dc6737c7fcc68a7ca1169aca60fbf8e5 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel P. Berrange <berrange@redhat.com>
|
||||
Date: Thu, 13 Aug 2009 11:56:31 +0100
|
||||
Subject: [PATCH] Make LXC / UML drivers robust against NUMA topology brokenness
|
||||
|
||||
Some kernel versions expose broken NUMA topology for some machines.
|
||||
This causes the LXC/UML drivers to fail to start. QEMU driver was
|
||||
already fixed for this problem
|
||||
|
||||
* src/lxc_conf.c: Log and ignore failure to populate NUMA info
|
||||
* src/uml_conf.c: Log and ignore failure to populate NUMA info
|
||||
* src/capabilities.c: Reset nnumaCell to 0 after freeing
|
||||
|
||||
(cherry picked from commit 19bac57b26c2d46ac8a7601158f210f34acdceac)
|
||||
|
||||
Fedora-patch: libvirt-0.7.0-numa-ignore-fail.patch
|
||||
---
|
||||
src/capabilities.c | 1 +
|
||||
src/lxc_conf.c | 12 ++++++++++--
|
||||
src/uml_conf.c | 11 +++++++++--
|
||||
3 files changed, 20 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/src/capabilities.c b/src/capabilities.c
|
||||
index c6766b6..193a9fe 100644
|
||||
--- a/src/capabilities.c
|
||||
+++ b/src/capabilities.c
|
||||
@@ -139,6 +139,7 @@ virCapabilitiesFreeNUMAInfo(virCapsPtr caps)
|
||||
for (i = 0 ; i < caps->host.nnumaCell ; i++)
|
||||
virCapabilitiesFreeHostNUMACell(caps->host.numaCell[i]);
|
||||
VIR_FREE(caps->host.numaCell);
|
||||
+ caps->host.nnumaCell = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
diff --git a/src/lxc_conf.c b/src/lxc_conf.c
|
||||
index d06a024..fef60ba 100644
|
||||
--- a/src/lxc_conf.c
|
||||
+++ b/src/lxc_conf.c
|
||||
@@ -30,6 +30,8 @@
|
||||
#include "lxc_conf.h"
|
||||
#include "nodeinfo.h"
|
||||
#include "virterror_internal.h"
|
||||
+#include "logging.h"
|
||||
+
|
||||
|
||||
#define VIR_FROM_THIS VIR_FROM_LXC
|
||||
|
||||
@@ -46,8 +48,14 @@ virCapsPtr lxcCapsInit(void)
|
||||
0, 0)) == NULL)
|
||||
goto no_memory;
|
||||
|
||||
- if (nodeCapsInitNUMA(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 (nodeCapsInitNUMA(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/uml_conf.c b/src/uml_conf.c
|
||||
index 48e05a8..4f756d4 100644
|
||||
--- a/src/uml_conf.c
|
||||
+++ b/src/uml_conf.c
|
||||
@@ -45,6 +45,7 @@
|
||||
#include "nodeinfo.h"
|
||||
#include "verify.h"
|
||||
#include "bridge.h"
|
||||
+#include "logging.h"
|
||||
|
||||
#define VIR_FROM_THIS VIR_FROM_UML
|
||||
|
||||
@@ -63,8 +64,14 @@ virCapsPtr umlCapsInit(void) {
|
||||
0, 0)) == NULL)
|
||||
goto no_memory;
|
||||
|
||||
- if (nodeCapsInitNUMA(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 (nodeCapsInitNUMA(caps) < 0) {
|
||||
+ virCapabilitiesFreeNUMAInfo(caps);
|
||||
+ VIR_WARN0("Failed to query host NUMA topology, disabling NUMA capabilities");
|
||||
+ }
|
||||
|
||||
if ((guest = virCapabilitiesAddGuest(caps,
|
||||
"uml",
|
||||
--
|
||||
1.6.2.5
|
||||
|
||||
@@ -1,505 +0,0 @@
|
||||
From d54fc5008d465d192101a0cb78fd02c437dff736 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel P. Berrange <berrange@redhat.com>
|
||||
Date: Mon, 17 Aug 2009 08:32:08 +0100
|
||||
Subject: [PATCH] Policykit rewrite (bug #499970)
|
||||
|
||||
Fedora-patch: libvirt-0.7.0-policy-kit-rewrite.patch
|
||||
---
|
||||
configure.in | 73 ++++++++++++++++++++++++++++--------------
|
||||
qemud/Makefile.am | 11 +++++-
|
||||
qemud/libvirtd.policy | 42 ------------------------
|
||||
qemud/libvirtd.policy-0 | 42 ++++++++++++++++++++++++
|
||||
qemud/libvirtd.policy-1 | 42 ++++++++++++++++++++++++
|
||||
qemud/qemud.c | 4 +-
|
||||
qemud/qemud.h | 4 +-
|
||||
qemud/remote.c | 81 ++++++++++++++++++++++++++++++++++++++++++++--
|
||||
src/remote_internal.c | 7 ++++
|
||||
9 files changed, 230 insertions(+), 76 deletions(-)
|
||||
delete mode 100644 qemud/libvirtd.policy
|
||||
create mode 100644 qemud/libvirtd.policy-0
|
||||
create mode 100644 qemud/libvirtd.policy-1
|
||||
|
||||
diff --git a/configure.in b/configure.in
|
||||
index 45fa9ed..d28c44a 100644
|
||||
--- a/configure.in
|
||||
+++ b/configure.in
|
||||
@@ -641,40 +641,61 @@ AC_SUBST([SASL_LIBS])
|
||||
dnl PolicyKit library
|
||||
POLKIT_CFLAGS=
|
||||
POLKIT_LIBS=
|
||||
+PKCHECK_PATH=
|
||||
AC_ARG_WITH([polkit],
|
||||
[ --with-polkit use PolicyKit for UNIX socket access checks],
|
||||
[],
|
||||
[with_polkit=check])
|
||||
|
||||
+with_polkit0=no
|
||||
+with_polkit1=no
|
||||
if test "x$with_polkit" = "xyes" -o "x$with_polkit" = "xcheck"; then
|
||||
- PKG_CHECK_MODULES(POLKIT, polkit-dbus >= $POLKIT_REQUIRED,
|
||||
- [with_polkit=yes], [
|
||||
- if test "x$with_polkit" = "xcheck" ; then
|
||||
- with_polkit=no
|
||||
- else
|
||||
- AC_MSG_ERROR(
|
||||
- [You must install PolicyKit >= $POLKIT_REQUIRED to compile libvirt])
|
||||
- fi
|
||||
- ])
|
||||
- if test "x$with_polkit" = "xyes" ; then
|
||||
+ dnl Check for new polkit first - just a binary
|
||||
+ AC_PATH_PROG([PKCHECK_PATH],[pkcheck], [], [/usr/sbin:$PATH])
|
||||
+ if test "x$PKCHECK_PATH" != "x" ; then
|
||||
+ AC_DEFINE_UNQUOTED([PKCHECK_PATH],["$PKCHECK_PATH"],[Location of pkcheck program])
|
||||
AC_DEFINE_UNQUOTED([HAVE_POLKIT], 1,
|
||||
- [use PolicyKit for UNIX socket access checks])
|
||||
-
|
||||
- old_CFLAGS=$CFLAGS
|
||||
- old_LDFLAGS=$LDFLAGS
|
||||
- CFLAGS="$CFLAGS $POLKIT_CFLAGS"
|
||||
- LDFLAGS="$LDFLAGS $POLKIT_LIBS"
|
||||
- AC_CHECK_FUNCS([polkit_context_is_caller_authorized])
|
||||
- CFLAGS="$old_CFLAGS"
|
||||
- LDFLAGS="$old_LDFLAGS"
|
||||
-
|
||||
- AC_PATH_PROG([POLKIT_AUTH], [polkit-auth])
|
||||
- if test "x$POLKIT_AUTH" != "x"; then
|
||||
- AC_DEFINE_UNQUOTED([POLKIT_AUTH],["$POLKIT_AUTH"],[Location of polkit-auth program])
|
||||
+ [use PolicyKit for UNIX socket access checks])
|
||||
+ AC_DEFINE_UNQUOTED([HAVE_POLKIT1], 1,
|
||||
+ [use PolicyKit for UNIX socket access checks])
|
||||
+ with_polkit="yes"
|
||||
+ with_polkit1="yes"
|
||||
+ else
|
||||
+ dnl Check for old polkit second - library + binary
|
||||
+ PKG_CHECK_MODULES(POLKIT, polkit-dbus >= $POLKIT_REQUIRED,
|
||||
+ [with_polkit=yes], [
|
||||
+ if test "x$with_polkit" = "xcheck" ; then
|
||||
+ with_polkit=no
|
||||
+ else
|
||||
+ AC_MSG_ERROR(
|
||||
+ [You must install PolicyKit >= $POLKIT_REQUIRED to compile libvirt])
|
||||
+ fi
|
||||
+ ])
|
||||
+ if test "x$with_polkit" = "xyes" ; then
|
||||
+ AC_DEFINE_UNQUOTED([HAVE_POLKIT], 1,
|
||||
+ [use PolicyKit for UNIX socket access checks])
|
||||
+ AC_DEFINE_UNQUOTED([HAVE_POLKIT0], 1,
|
||||
+ [use PolicyKit for UNIX socket access checks])
|
||||
+
|
||||
+ old_CFLAGS=$CFLAGS
|
||||
+ old_LDFLAGS=$LDFLAGS
|
||||
+ CFLAGS="$CFLAGS $POLKIT_CFLAGS"
|
||||
+ LDFLAGS="$LDFLAGS $POLKIT_LIBS"
|
||||
+ AC_CHECK_FUNCS([polkit_context_is_caller_authorized])
|
||||
+ CFLAGS="$old_CFLAGS"
|
||||
+ LDFLAGS="$old_LDFLAGS"
|
||||
+
|
||||
+ AC_PATH_PROG([POLKIT_AUTH], [polkit-auth])
|
||||
+ if test "x$POLKIT_AUTH" != "x"; then
|
||||
+ AC_DEFINE_UNQUOTED([POLKIT_AUTH],["$POLKIT_AUTH"],[Location of polkit-auth program])
|
||||
+ fi
|
||||
+ with_polkit0="yes"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
AM_CONDITIONAL([HAVE_POLKIT], [test "x$with_polkit" = "xyes"])
|
||||
+AM_CONDITIONAL([HAVE_POLKIT0], [test "x$with_polkit0" = "xyes"])
|
||||
+AM_CONDITIONAL([HAVE_POLKIT1], [test "x$with_polkit1" = "xyes"])
|
||||
AC_SUBST([POLKIT_CFLAGS])
|
||||
AC_SUBST([POLKIT_LIBS])
|
||||
|
||||
@@ -1695,7 +1716,11 @@ else
|
||||
AC_MSG_NOTICE([ avahi: no])
|
||||
fi
|
||||
if test "$with_polkit" = "yes" ; then
|
||||
-AC_MSG_NOTICE([ polkit: $POLKIT_CFLAGS $POLKIT_LIBS])
|
||||
+if test "$with_polkit0" = "yes" ; then
|
||||
+AC_MSG_NOTICE([ polkit: $POLKIT_CFLAGS $POLKIT_LIBS (version 0)])
|
||||
+else
|
||||
+AC_MSG_NOTICE([ polkit: $PKCHECK_PATH (version 1)])
|
||||
+fi
|
||||
else
|
||||
AC_MSG_NOTICE([ polkit: no])
|
||||
fi
|
||||
diff --git a/qemud/Makefile.am b/qemud/Makefile.am
|
||||
index 959ff88..3d143da 100644
|
||||
--- a/qemud/Makefile.am
|
||||
+++ b/qemud/Makefile.am
|
||||
@@ -21,7 +21,8 @@ EXTRA_DIST = \
|
||||
remote_protocol.x \
|
||||
libvirtd.conf \
|
||||
libvirtd.init.in \
|
||||
- libvirtd.policy \
|
||||
+ libvirtd.policy-0 \
|
||||
+ libvirtd.policy-1 \
|
||||
libvirtd.sasl \
|
||||
libvirtd.sysconf \
|
||||
libvirtd.aug \
|
||||
@@ -147,7 +148,13 @@ endif
|
||||
libvirtd_LDADD += ../src/libvirt.la
|
||||
|
||||
if HAVE_POLKIT
|
||||
+if HAVE_POLKIT0
|
||||
policydir = $(datadir)/PolicyKit/policy
|
||||
+policyfile = libvirtd.policy-0
|
||||
+else
|
||||
+policydir = $(datadir)/polkit-1/actions
|
||||
+policyfile = libvirtd.policy-1
|
||||
+endif
|
||||
endif
|
||||
|
||||
if HAVE_AVAHI
|
||||
@@ -197,7 +204,7 @@ endif
|
||||
if HAVE_POLKIT
|
||||
install-data-polkit:: install-init
|
||||
mkdir -p $(DESTDIR)$(policydir)
|
||||
- $(INSTALL_DATA) $(srcdir)/libvirtd.policy $(DESTDIR)$(policydir)/org.libvirt.unix.policy
|
||||
+ $(INSTALL_DATA) $(srcdir)/$(policyfile) $(DESTDIR)$(policydir)/org.libvirt.unix.policy
|
||||
uninstall-data-polkit:: install-init
|
||||
rm -f $(DESTDIR)$(policydir)/org.libvirt.unix.policy
|
||||
else
|
||||
diff --git a/qemud/libvirtd.policy b/qemud/libvirtd.policy
|
||||
deleted file mode 100644
|
||||
index b6da946..0000000
|
||||
--- a/qemud/libvirtd.policy
|
||||
+++ /dev/null
|
||||
@@ -1,42 +0,0 @@
|
||||
-<!DOCTYPE policyconfig PUBLIC
|
||||
- "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
|
||||
- "http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd">
|
||||
-
|
||||
-<!--
|
||||
-Policy definitions for libvirt daemon
|
||||
-
|
||||
-Copyright (c) 2007 Daniel P. Berrange <berrange redhat com>
|
||||
-
|
||||
-libvirt is licensed to you under the GNU Lesser General Public License
|
||||
-version 2. See COPYING for details.
|
||||
-
|
||||
-NOTE: If you make changes to this file, make sure to validate the file
|
||||
-using the polkit-policy-file-validate(1) tool. Changes made to this
|
||||
-file are instantly applied.
|
||||
--->
|
||||
-
|
||||
-<policyconfig>
|
||||
- <action id="org.libvirt.unix.monitor">
|
||||
- <description>Monitor local virtualized systems</description>
|
||||
- <message>System policy prevents monitoring of local virtualized systems</message>
|
||||
- <defaults>
|
||||
- <!-- Any program can use libvirt in read-only mode for monitoring,
|
||||
- even if not part of a session -->
|
||||
- <allow_any>yes</allow_any>
|
||||
- <allow_inactive>yes</allow_inactive>
|
||||
- <allow_active>yes</allow_active>
|
||||
- </defaults>
|
||||
- </action>
|
||||
-
|
||||
- <action id="org.libvirt.unix.manage">
|
||||
- <description>Manage local virtualized systems</description>
|
||||
- <message>System policy prevents management of local virtualized systems</message>
|
||||
- <defaults>
|
||||
- <!-- Only a program in the active host session can use libvirt in
|
||||
- read-write mode for management, and we require user password -->
|
||||
- <allow_any>no</allow_any>
|
||||
- <allow_inactive>no</allow_inactive>
|
||||
- <allow_active>auth_admin_keep_session</allow_active>
|
||||
- </defaults>
|
||||
- </action>
|
||||
-</policyconfig>
|
||||
diff --git a/qemud/libvirtd.policy-0 b/qemud/libvirtd.policy-0
|
||||
new file mode 100644
|
||||
index 0000000..b6da946
|
||||
--- /dev/null
|
||||
+++ b/qemud/libvirtd.policy-0
|
||||
@@ -0,0 +1,42 @@
|
||||
+<!DOCTYPE policyconfig PUBLIC
|
||||
+ "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
|
||||
+ "http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd">
|
||||
+
|
||||
+<!--
|
||||
+Policy definitions for libvirt daemon
|
||||
+
|
||||
+Copyright (c) 2007 Daniel P. Berrange <berrange redhat com>
|
||||
+
|
||||
+libvirt is licensed to you under the GNU Lesser General Public License
|
||||
+version 2. See COPYING for details.
|
||||
+
|
||||
+NOTE: If you make changes to this file, make sure to validate the file
|
||||
+using the polkit-policy-file-validate(1) tool. Changes made to this
|
||||
+file are instantly applied.
|
||||
+-->
|
||||
+
|
||||
+<policyconfig>
|
||||
+ <action id="org.libvirt.unix.monitor">
|
||||
+ <description>Monitor local virtualized systems</description>
|
||||
+ <message>System policy prevents monitoring of local virtualized systems</message>
|
||||
+ <defaults>
|
||||
+ <!-- Any program can use libvirt in read-only mode for monitoring,
|
||||
+ even if not part of a session -->
|
||||
+ <allow_any>yes</allow_any>
|
||||
+ <allow_inactive>yes</allow_inactive>
|
||||
+ <allow_active>yes</allow_active>
|
||||
+ </defaults>
|
||||
+ </action>
|
||||
+
|
||||
+ <action id="org.libvirt.unix.manage">
|
||||
+ <description>Manage local virtualized systems</description>
|
||||
+ <message>System policy prevents management of local virtualized systems</message>
|
||||
+ <defaults>
|
||||
+ <!-- Only a program in the active host session can use libvirt in
|
||||
+ read-write mode for management, and we require user password -->
|
||||
+ <allow_any>no</allow_any>
|
||||
+ <allow_inactive>no</allow_inactive>
|
||||
+ <allow_active>auth_admin_keep_session</allow_active>
|
||||
+ </defaults>
|
||||
+ </action>
|
||||
+</policyconfig>
|
||||
diff --git a/qemud/libvirtd.policy-1 b/qemud/libvirtd.policy-1
|
||||
new file mode 100644
|
||||
index 0000000..6fa3a5e
|
||||
--- /dev/null
|
||||
+++ b/qemud/libvirtd.policy-1
|
||||
@@ -0,0 +1,42 @@
|
||||
+<!DOCTYPE policyconfig PUBLIC
|
||||
+ "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
|
||||
+ "http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd">
|
||||
+
|
||||
+<!--
|
||||
+Policy definitions for libvirt daemon
|
||||
+
|
||||
+Copyright (c) 2007 Daniel P. Berrange <berrange redhat com>
|
||||
+
|
||||
+libvirt is licensed to you under the GNU Lesser General Public License
|
||||
+version 2. See COPYING for details.
|
||||
+
|
||||
+NOTE: If you make changes to this file, make sure to validate the file
|
||||
+using the polkit-policy-file-validate(1) tool. Changes made to this
|
||||
+file are instantly applied.
|
||||
+-->
|
||||
+
|
||||
+<policyconfig>
|
||||
+ <action id="org.libvirt.unix.monitor">
|
||||
+ <description>Monitor local virtualized systems</description>
|
||||
+ <message>System policy prevents monitoring of local virtualized systems</message>
|
||||
+ <defaults>
|
||||
+ <!-- Any program can use libvirt in read-only mode for monitoring,
|
||||
+ even if not part of a session -->
|
||||
+ <allow_any>yes</allow_any>
|
||||
+ <allow_inactive>yes</allow_inactive>
|
||||
+ <allow_active>yes</allow_active>
|
||||
+ </defaults>
|
||||
+ </action>
|
||||
+
|
||||
+ <action id="org.libvirt.unix.manage">
|
||||
+ <description>Manage local virtualized systems</description>
|
||||
+ <message>System policy prevents management of local virtualized systems</message>
|
||||
+ <defaults>
|
||||
+ <!-- Only a program in the active host session can use libvirt in
|
||||
+ read-write mode for management, and we require user password -->
|
||||
+ <allow_any>no</allow_any>
|
||||
+ <allow_inactive>no</allow_inactive>
|
||||
+ <allow_active>auth_admin_keep</allow_active>
|
||||
+ </defaults>
|
||||
+ </action>
|
||||
+</policyconfig>
|
||||
diff --git a/qemud/qemud.c b/qemud/qemud.c
|
||||
index 3e551ca..50b0cdd 100644
|
||||
--- a/qemud/qemud.c
|
||||
+++ b/qemud/qemud.c
|
||||
@@ -895,7 +895,7 @@ static struct qemud_server *qemudNetworkInit(struct qemud_server *server) {
|
||||
}
|
||||
#endif
|
||||
|
||||
-#ifdef HAVE_POLKIT
|
||||
+#if HAVE_POLKIT0
|
||||
if (auth_unix_rw == REMOTE_AUTH_POLKIT ||
|
||||
auth_unix_ro == REMOTE_AUTH_POLKIT) {
|
||||
DBusError derr;
|
||||
@@ -982,7 +982,7 @@ static struct qemud_server *qemudNetworkInit(struct qemud_server *server) {
|
||||
sock = sock->next;
|
||||
}
|
||||
|
||||
-#ifdef HAVE_POLKIT
|
||||
+#if HAVE_POLKIT0
|
||||
if (server->sysbus)
|
||||
dbus_connection_unref(server->sysbus);
|
||||
#endif
|
||||
diff --git a/qemud/qemud.h b/qemud/qemud.h
|
||||
index 254db44..e8ce209 100644
|
||||
--- a/qemud/qemud.h
|
||||
+++ b/qemud/qemud.h
|
||||
@@ -34,7 +34,7 @@
|
||||
#include <sasl/sasl.h>
|
||||
#endif
|
||||
|
||||
-#ifdef HAVE_POLKIT
|
||||
+#if HAVE_POLKIT0
|
||||
#include <dbus/dbus.h>
|
||||
#endif
|
||||
|
||||
@@ -253,7 +253,7 @@ struct qemud_server {
|
||||
#if HAVE_SASL
|
||||
char **saslUsernameWhitelist;
|
||||
#endif
|
||||
-#if HAVE_POLKIT
|
||||
+#if HAVE_POLKIT0
|
||||
DBusConnection *sysbus;
|
||||
#endif
|
||||
};
|
||||
diff --git a/qemud/remote.c b/qemud/remote.c
|
||||
index d32d513..490a807 100644
|
||||
--- a/qemud/remote.c
|
||||
+++ b/qemud/remote.c
|
||||
@@ -43,7 +43,7 @@
|
||||
#include <fnmatch.h>
|
||||
#include "virterror_internal.h"
|
||||
|
||||
-#ifdef HAVE_POLKIT
|
||||
+#if HAVE_POLKIT0
|
||||
#include <polkit/polkit.h>
|
||||
#include <polkit-dbus/polkit-dbus.h>
|
||||
#endif
|
||||
@@ -3106,7 +3106,80 @@ remoteDispatchAuthSaslStep (struct qemud_server *server ATTRIBUTE_UNUSED,
|
||||
#endif /* HAVE_SASL */
|
||||
|
||||
|
||||
-#if HAVE_POLKIT
|
||||
+#if HAVE_POLKIT1
|
||||
+static int
|
||||
+remoteDispatchAuthPolkit (struct qemud_server *server,
|
||||
+ struct qemud_client *client,
|
||||
+ virConnectPtr conn ATTRIBUTE_UNUSED,
|
||||
+ remote_error *rerr,
|
||||
+ void *args ATTRIBUTE_UNUSED,
|
||||
+ remote_auth_polkit_ret *ret)
|
||||
+{
|
||||
+ pid_t callerPid;
|
||||
+ uid_t callerUid;
|
||||
+ const char *action;
|
||||
+ int status = -1;
|
||||
+ char pidbuf[50];
|
||||
+ int rv;
|
||||
+
|
||||
+ virMutexLock(&server->lock);
|
||||
+ virMutexLock(&client->lock);
|
||||
+ virMutexUnlock(&server->lock);
|
||||
+
|
||||
+ action = client->readonly ?
|
||||
+ "org.libvirt.unix.monitor" :
|
||||
+ "org.libvirt.unix.manage";
|
||||
+
|
||||
+ const char * const pkcheck [] = {
|
||||
+ PKCHECK_PATH,
|
||||
+ "--action-id", action,
|
||||
+ "--process", pidbuf,
|
||||
+ "--allow-user-interaction",
|
||||
+ NULL
|
||||
+ };
|
||||
+
|
||||
+ REMOTE_DEBUG("Start PolicyKit auth %d", client->fd);
|
||||
+ if (client->auth != REMOTE_AUTH_POLKIT) {
|
||||
+ VIR_ERROR0(_("client tried invalid PolicyKit init request"));
|
||||
+ goto authfail;
|
||||
+ }
|
||||
+
|
||||
+ if (qemudGetSocketIdentity(client->fd, &callerUid, &callerPid) < 0) {
|
||||
+ VIR_ERROR0(_("cannot get peer socket identity"));
|
||||
+ goto authfail;
|
||||
+ }
|
||||
+
|
||||
+ VIR_INFO(_("Checking PID %d running as %d"), callerPid, callerUid);
|
||||
+
|
||||
+ rv = snprintf(pidbuf, sizeof pidbuf, "%d", callerPid);
|
||||
+ if (rv < 0 || rv >= sizeof pidbuf) {
|
||||
+ VIR_ERROR(_("Caller PID was too large %d"), callerPid);
|
||||
+ goto authfail;
|
||||
+ }
|
||||
+
|
||||
+ if (virRun(NULL, pkcheck, &status) < 0) {
|
||||
+ VIR_ERROR(_("Cannot invoke %s"), PKCHECK_PATH);
|
||||
+ goto authfail;
|
||||
+ }
|
||||
+ if (status != 0) {
|
||||
+ VIR_ERROR(_("Policy kit denied action %s from pid %d, uid %d, result: %d\n"),
|
||||
+ action, callerPid, callerUid, status);
|
||||
+ goto authfail;
|
||||
+ }
|
||||
+ VIR_INFO(_("Policy allowed action %s from pid %d, uid %d"),
|
||||
+ action, callerPid, callerUid);
|
||||
+ ret->complete = 1;
|
||||
+ client->auth = REMOTE_AUTH_NONE;
|
||||
+
|
||||
+ virMutexUnlock(&client->lock);
|
||||
+ return 0;
|
||||
+
|
||||
+authfail:
|
||||
+ remoteDispatchAuthError(rerr);
|
||||
+ virMutexUnlock(&client->lock);
|
||||
+ return -1;
|
||||
+}
|
||||
+#elif HAVE_POLKIT0
|
||||
static int
|
||||
remoteDispatchAuthPolkit (struct qemud_server *server,
|
||||
struct qemud_client *client,
|
||||
@@ -3217,7 +3290,7 @@ authfail:
|
||||
return -1;
|
||||
}
|
||||
|
||||
-#else /* HAVE_POLKIT */
|
||||
+#else /* !HAVE_POLKIT0 & !HAVE_POLKIT1*/
|
||||
|
||||
static int
|
||||
remoteDispatchAuthPolkit (struct qemud_server *server ATTRIBUTE_UNUSED,
|
||||
@@ -3231,7 +3304,7 @@ remoteDispatchAuthPolkit (struct qemud_server *server ATTRIBUTE_UNUSED,
|
||||
remoteDispatchAuthError(rerr);
|
||||
return -1;
|
||||
}
|
||||
-#endif /* HAVE_POLKIT */
|
||||
+#endif /* HAVE_POLKIT1 */
|
||||
|
||||
|
||||
/***************************************************************
|
||||
diff --git a/src/remote_internal.c b/src/remote_internal.c
|
||||
index a58b768..e98c99b 100644
|
||||
--- a/src/remote_internal.c
|
||||
+++ b/src/remote_internal.c
|
||||
@@ -6201,6 +6201,7 @@ remoteAuthPolkit (virConnectPtr conn, struct private_data *priv, int in_open,
|
||||
virConnectAuthPtr auth)
|
||||
{
|
||||
remote_auth_polkit_ret ret;
|
||||
+#if HAVE_POLKIT0
|
||||
int i, allowcb = 0;
|
||||
virConnectCredential cred = {
|
||||
VIR_CRED_EXTERNAL,
|
||||
@@ -6210,8 +6211,10 @@ remoteAuthPolkit (virConnectPtr conn, struct private_data *priv, int in_open,
|
||||
NULL,
|
||||
0,
|
||||
};
|
||||
+#endif
|
||||
DEBUG0("Client initialize PolicyKit authentication");
|
||||
|
||||
+#if HAVE_POLKIT0
|
||||
if (auth && auth->cb) {
|
||||
/* Check if the necessary credential type for PolicyKit is supported */
|
||||
for (i = 0 ; i < auth->ncredtype ; i++) {
|
||||
@@ -6220,6 +6223,7 @@ remoteAuthPolkit (virConnectPtr conn, struct private_data *priv, int in_open,
|
||||
}
|
||||
|
||||
if (allowcb) {
|
||||
+ DEBUG0("Client run callback for PolicyKit authentication");
|
||||
/* Run the authentication callback */
|
||||
if ((*(auth->cb))(&cred, 1, auth->cbdata) < 0) {
|
||||
virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE,
|
||||
@@ -6233,6 +6237,9 @@ remoteAuthPolkit (virConnectPtr conn, struct private_data *priv, int in_open,
|
||||
} else {
|
||||
DEBUG0("No auth callback provided");
|
||||
}
|
||||
+#else
|
||||
+ DEBUG0("No auth callback required for PolicyKit-1");
|
||||
+#endif
|
||||
|
||||
memset (&ret, 0, sizeof ret);
|
||||
if (call (conn, priv, in_open, REMOTE_PROC_AUTH_POLKIT,
|
||||
--
|
||||
1.6.2.5
|
||||
|
||||
@@ -1,465 +0,0 @@
|
||||
From 332979bb680d833529ab9cecac6828c6ce54d731 Mon Sep 17 00:00:00 2001
|
||||
From: Mark McLoughlin <markmc@redhat.com>
|
||||
Date: Fri, 14 Aug 2009 08:31:10 +0100
|
||||
Subject: [PATCH] Add host PCI device hotplug support
|
||||
|
||||
Attaching a host PCI device to a qemu guest is done with a
|
||||
straightforward 'pci_add pci_addr auto host host=XX:XX.X' command.
|
||||
|
||||
Like with NIC and disk hotplug, we need to retain the guest PCI address
|
||||
assigned by qemu so that we can use it for hot-unplug.
|
||||
|
||||
Identifying a device for detach is done using the host PCI address.
|
||||
|
||||
Managed mode is handled by detaching/resetting the device before
|
||||
attaching it to the guest and re-attaching it after detaching it from
|
||||
the guest.
|
||||
|
||||
(cherry picked from commit 7636ef4630fc15c3d559eceb5b5c4fb1524b7c5a)
|
||||
(cherry picked from commit 0c5b7b93a3cdb197c55d79c2605e9e19e3af43f5)
|
||||
(cherry picked from commit 60ff07585ca8f7e639fed477e2e2cf79ce1c5c21)
|
||||
(cherry picked from commit 4e12af5623e4a962a6bb911af06fa29aa85befba)
|
||||
(cherry picked from commit 4dbecff9fbd5b5d1154bc7a41a5d4dd00533b359)
|
||||
(cherry picked from commit 12edef9a6aca5bd9a2ea18b73ca862f615684d84)
|
||||
(cherry picked from commit 457e05062863a35c7efb35470886b9b83a49d04d)
|
||||
(cherry picked from commit e8ad33931296c67de0538e78d12e21706a826d37)
|
||||
|
||||
Fedora-patch: libvirt-add-pci-hostdev-hotplug-support.patch
|
||||
---
|
||||
src/domain_conf.c | 33 +++++-
|
||||
src/domain_conf.h | 13 +++
|
||||
src/libvirt_private.syms | 2 +
|
||||
src/qemu_driver.c | 266 ++++++++++++++++++++++++++++++++++++++++++++--
|
||||
4 files changed, 300 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/src/domain_conf.c b/src/domain_conf.c
|
||||
index 2301a96..bad53f7 100644
|
||||
--- a/src/domain_conf.c
|
||||
+++ b/src/domain_conf.c
|
||||
@@ -1977,7 +1977,8 @@ out:
|
||||
static int
|
||||
virDomainHostdevSubsysPciDefParseXML(virConnectPtr conn,
|
||||
const xmlNodePtr node,
|
||||
- virDomainHostdevDefPtr def) {
|
||||
+ virDomainHostdevDefPtr def,
|
||||
+ int flags) {
|
||||
|
||||
int ret = -1;
|
||||
xmlNodePtr cur;
|
||||
@@ -2049,6 +2050,20 @@ virDomainHostdevSubsysPciDefParseXML(virConnectPtr conn,
|
||||
_("pci address needs function id"));
|
||||
goto out;
|
||||
}
|
||||
+ } else if ((flags & VIR_DOMAIN_XML_INTERNAL_STATUS) &&
|
||||
+ xmlStrEqual(cur->name, BAD_CAST "state")) {
|
||||
+ char *devaddr = virXMLPropString(cur, "devaddr");
|
||||
+ if (devaddr &&
|
||||
+ sscanf(devaddr, "%x:%x:%x",
|
||||
+ &def->source.subsys.u.pci.guest_addr.domain,
|
||||
+ &def->source.subsys.u.pci.guest_addr.bus,
|
||||
+ &def->source.subsys.u.pci.guest_addr.slot) < 3) {
|
||||
+ virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||
+ _("Unable to parse devaddr parameter '%s'"),
|
||||
+ devaddr);
|
||||
+ VIR_FREE(devaddr);
|
||||
+ goto out;
|
||||
+ }
|
||||
} else {
|
||||
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||
_("unknown pci source type '%s'"),
|
||||
@@ -2123,7 +2138,7 @@ virDomainHostdevDefParseXML(virConnectPtr conn,
|
||||
}
|
||||
if (def->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
|
||||
def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) {
|
||||
- if (virDomainHostdevSubsysPciDefParseXML(conn, cur, def) < 0)
|
||||
+ if (virDomainHostdevSubsysPciDefParseXML(conn, cur, def, flags) < 0)
|
||||
goto error;
|
||||
}
|
||||
} else {
|
||||
@@ -3937,7 +3952,8 @@ virDomainGraphicsDefFormat(virConnectPtr conn,
|
||||
static int
|
||||
virDomainHostdevDefFormat(virConnectPtr conn,
|
||||
virBufferPtr buf,
|
||||
- virDomainHostdevDefPtr def)
|
||||
+ virDomainHostdevDefPtr def,
|
||||
+ int flags)
|
||||
{
|
||||
const char *mode = virDomainHostdevModeTypeToString(def->mode);
|
||||
const char *type;
|
||||
@@ -3978,6 +3994,15 @@ virDomainHostdevDefFormat(virConnectPtr conn,
|
||||
def->source.subsys.u.pci.bus,
|
||||
def->source.subsys.u.pci.slot,
|
||||
def->source.subsys.u.pci.function);
|
||||
+ if (flags & VIR_DOMAIN_XML_INTERNAL_STATUS) {
|
||||
+ virBufferAddLit(buf, " <state");
|
||||
+ if (virHostdevHasValidGuestAddr(def))
|
||||
+ virBufferVSprintf(buf, " devaddr='%.4x:%.2x:%.2x'",
|
||||
+ def->source.subsys.u.pci.guest_addr.domain,
|
||||
+ def->source.subsys.u.pci.guest_addr.bus,
|
||||
+ def->source.subsys.u.pci.guest_addr.slot);
|
||||
+ virBufferAddLit(buf, "/>\n");
|
||||
+ }
|
||||
}
|
||||
|
||||
virBufferAddLit(buf, " </source>\n");
|
||||
@@ -4192,7 +4217,7 @@ char *virDomainDefFormat(virConnectPtr conn,
|
||||
goto cleanup;
|
||||
|
||||
for (n = 0 ; n < def->nhostdevs ; n++)
|
||||
- if (virDomainHostdevDefFormat(conn, &buf, def->hostdevs[n]) < 0)
|
||||
+ if (virDomainHostdevDefFormat(conn, &buf, def->hostdevs[n], flags) < 0)
|
||||
goto cleanup;
|
||||
|
||||
virBufferAddLit(&buf, " </devices>\n");
|
||||
diff --git a/src/domain_conf.h b/src/domain_conf.h
|
||||
index 63fca76..44302be 100644
|
||||
--- a/src/domain_conf.h
|
||||
+++ b/src/domain_conf.h
|
||||
@@ -391,6 +391,11 @@ struct _virDomainHostdevDef {
|
||||
unsigned bus;
|
||||
unsigned slot;
|
||||
unsigned function;
|
||||
+ struct {
|
||||
+ unsigned domain;
|
||||
+ unsigned bus;
|
||||
+ unsigned slot;
|
||||
+ } guest_addr;
|
||||
} pci;
|
||||
} u;
|
||||
} subsys;
|
||||
@@ -404,6 +409,14 @@ struct _virDomainHostdevDef {
|
||||
char* target;
|
||||
};
|
||||
|
||||
+static inline int
|
||||
+virHostdevHasValidGuestAddr(virDomainHostdevDefPtr def)
|
||||
+{
|
||||
+ return def->source.subsys.u.pci.guest_addr.domain ||
|
||||
+ def->source.subsys.u.pci.guest_addr.bus ||
|
||||
+ def->source.subsys.u.pci.guest_addr.slot;
|
||||
+}
|
||||
+
|
||||
/* Flags for the 'type' field in next struct */
|
||||
enum virDomainDeviceType {
|
||||
VIR_DOMAIN_DEVICE_DISK,
|
||||
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
|
||||
index 4f1b01f..22131c4 100644
|
||||
--- a/src/libvirt_private.syms
|
||||
+++ b/src/libvirt_private.syms
|
||||
@@ -88,6 +88,8 @@ virDomainGetRootFilesystem;
|
||||
virDomainGraphicsTypeFromString;
|
||||
virDomainGraphicsDefFree;
|
||||
virDomainHostdevDefFree;
|
||||
+virDomainHostdevModeTypeToString;
|
||||
+virDomainHostdevSubsysTypeToString;
|
||||
virDomainInputDefFree;
|
||||
virDomainLifecycleTypeFromString;
|
||||
virDomainLifecycleTypeToString;
|
||||
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
|
||||
index cbc27c4..99dac52 100644
|
||||
--- a/src/qemu_driver.c
|
||||
+++ b/src/qemu_driver.c
|
||||
@@ -5258,9 +5258,91 @@ cleanup:
|
||||
return -1;
|
||||
}
|
||||
|
||||
-static int qemudDomainAttachHostDevice(virConnectPtr conn,
|
||||
- virDomainObjPtr vm,
|
||||
- virDomainDeviceDefPtr dev)
|
||||
+static int qemudDomainAttachHostPciDevice(virConnectPtr conn,
|
||||
+ struct qemud_driver *driver,
|
||||
+ virDomainObjPtr vm,
|
||||
+ virDomainDeviceDefPtr dev)
|
||||
+{
|
||||
+ virDomainHostdevDefPtr hostdev = dev->data.hostdev;
|
||||
+ char *cmd, *reply;
|
||||
+ unsigned domain, bus, slot;
|
||||
+ pciDevice *pci;
|
||||
+
|
||||
+ if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs+1) < 0) {
|
||||
+ virReportOOMError(conn);
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ pci = 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)
|
||||
+ return -1;
|
||||
+
|
||||
+ if ((hostdev->managed && pciDettachDevice(conn, pci) < 0) ||
|
||||
+ pciResetDevice(conn, pci, driver->activePciHostdevs) < 0) {
|
||||
+ pciFreeDevice(conn, pci);
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ if (pciDeviceListAdd(conn, driver->activePciHostdevs, pci) < 0) {
|
||||
+ pciFreeDevice(conn, pci);
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ cmd = reply = NULL;
|
||||
+
|
||||
+ if (virAsprintf(&cmd, "pci_add pci_addr=auto host host=%.2x:%.2x.%.1x",
|
||||
+ hostdev->source.subsys.u.pci.bus,
|
||||
+ hostdev->source.subsys.u.pci.slot,
|
||||
+ hostdev->source.subsys.u.pci.function) < 0) {
|
||||
+ virReportOOMError(conn);
|
||||
+ goto error;
|
||||
+ }
|
||||
+
|
||||
+ if (qemudMonitorCommand(vm, cmd, &reply) < 0) {
|
||||
+ qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
|
||||
+ "%s", _("cannot attach host pci device"));
|
||||
+ goto error;
|
||||
+ }
|
||||
+
|
||||
+ if (strstr(reply, "invalid type: host")) {
|
||||
+ qemudReportError(conn, dom, NULL, VIR_ERR_NO_SUPPORT, "%s",
|
||||
+ _("PCI device assignment is not supported by this version of qemu"));
|
||||
+ goto error;
|
||||
+ }
|
||||
+
|
||||
+ if (qemudParsePciAddReply(vm, reply, &domain, &bus, &slot) < 0) {
|
||||
+ qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
|
||||
+ _("parsing pci_add reply failed: %s"), reply);
|
||||
+ goto error;
|
||||
+ }
|
||||
+
|
||||
+ hostdev->source.subsys.u.pci.guest_addr.domain = domain;
|
||||
+ hostdev->source.subsys.u.pci.guest_addr.bus = bus;
|
||||
+ hostdev->source.subsys.u.pci.guest_addr.slot = slot;
|
||||
+
|
||||
+ vm->def->hostdevs[vm->def->nhostdevs++] = hostdev;
|
||||
+
|
||||
+ VIR_FREE(reply);
|
||||
+ VIR_FREE(cmd);
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+error:
|
||||
+ pciDeviceListDel(conn, driver->activePciHostdevs, pci);
|
||||
+
|
||||
+ VIR_FREE(reply);
|
||||
+ VIR_FREE(cmd);
|
||||
+
|
||||
+ return -1;
|
||||
+}
|
||||
+
|
||||
+static int qemudDomainAttachHostUsbDevice(virConnectPtr conn,
|
||||
+ virDomainObjPtr vm,
|
||||
+ virDomainDeviceDefPtr dev)
|
||||
{
|
||||
int ret;
|
||||
char *cmd, *reply;
|
||||
@@ -5310,6 +5392,36 @@ static int qemudDomainAttachHostDevice(virConnectPtr conn,
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int qemudDomainAttachHostDevice(virConnectPtr conn,
|
||||
+ struct qemud_driver *driver,
|
||||
+ virDomainObjPtr vm,
|
||||
+ virDomainDeviceDefPtr dev)
|
||||
+{
|
||||
+ virDomainHostdevDefPtr hostdev = dev->data.hostdev;
|
||||
+
|
||||
+ if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) {
|
||||
+ qemudReportError(conn, dom, NULL, VIR_ERR_NO_SUPPORT,
|
||||
+ _("hostdev mode '%s' not supported"),
|
||||
+ virDomainHostdevModeTypeToString(hostdev->mode));
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ if (qemuDomainSetDeviceOwnership(conn, driver, dev, 0) < 0)
|
||||
+ return -1;
|
||||
+
|
||||
+ switch (hostdev->source.subsys.type) {
|
||||
+ case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
|
||||
+ return qemudDomainAttachHostPciDevice(conn, driver, vm, dev);
|
||||
+ case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
|
||||
+ return qemudDomainAttachHostUsbDevice(conn, vm, dev);
|
||||
+ default:
|
||||
+ qemudReportError(conn, dom, NULL, VIR_ERR_NO_SUPPORT,
|
||||
+ _("hostdev subsys type '%s' not supported"),
|
||||
+ virDomainHostdevSubsysTypeToString(hostdev->source.subsys.type));
|
||||
+ return -1;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static int qemudDomainAttachDevice(virDomainPtr dom,
|
||||
const char *xml) {
|
||||
struct qemud_driver *driver = dom->conn->privateData;
|
||||
@@ -5411,13 +5523,8 @@ static int qemudDomainAttachDevice(virDomainPtr dom,
|
||||
}
|
||||
} else if (dev->type == VIR_DOMAIN_DEVICE_NET) {
|
||||
ret = qemudDomainAttachNetDevice(dom->conn, driver, vm, dev, qemuCmdFlags);
|
||||
- } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV &&
|
||||
- dev->data.hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
|
||||
- dev->data.hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) {
|
||||
- if (qemuDomainSetDeviceOwnership(dom->conn, driver, dev, 0) < 0)
|
||||
- goto cleanup;
|
||||
-
|
||||
- ret = qemudDomainAttachHostDevice(dom->conn, vm, dev);
|
||||
+ } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) {
|
||||
+ ret = qemudDomainAttachHostDevice(dom->conn, driver, vm, dev);
|
||||
} else {
|
||||
qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
|
||||
_("device type '%s' cannot be attached"),
|
||||
@@ -5630,6 +5737,143 @@ cleanup:
|
||||
return ret;
|
||||
}
|
||||
|
||||
+static int qemudDomainDetachHostPciDevice(virConnectPtr conn,
|
||||
+ struct qemud_driver *driver,
|
||||
+ virDomainObjPtr vm,
|
||||
+ virDomainDeviceDefPtr dev)
|
||||
+{
|
||||
+ virDomainHostdevDefPtr detach;
|
||||
+ char *cmd, *reply;
|
||||
+ int i, ret;
|
||||
+ pciDevice *pci;
|
||||
+
|
||||
+ for (i = 0 ; i < vm->def->nhostdevs ; i++) {
|
||||
+ unsigned domain = vm->def->hostdevs[i]->source.subsys.u.pci.domain;
|
||||
+ unsigned bus = vm->def->hostdevs[i]->source.subsys.u.pci.bus;
|
||||
+ unsigned slot = vm->def->hostdevs[i]->source.subsys.u.pci.slot;
|
||||
+ unsigned function = vm->def->hostdevs[i]->source.subsys.u.pci.function;
|
||||
+
|
||||
+ if (dev->data.hostdev->source.subsys.u.pci.domain == domain &&
|
||||
+ dev->data.hostdev->source.subsys.u.pci.bus == bus &&
|
||||
+ dev->data.hostdev->source.subsys.u.pci.slot == slot &&
|
||||
+ dev->data.hostdev->source.subsys.u.pci.function == function) {
|
||||
+ detach = vm->def->hostdevs[i];
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (!detach) {
|
||||
+ qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
|
||||
+ _("host pci device %.4x:%.2x:%.2x.%.1x not found"),
|
||||
+ dev->data.hostdev->source.subsys.u.pci.domain,
|
||||
+ dev->data.hostdev->source.subsys.u.pci.bus,
|
||||
+ dev->data.hostdev->source.subsys.u.pci.slot,
|
||||
+ dev->data.hostdev->source.subsys.u.pci.function);
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ if (!virHostdevHasValidGuestAddr(detach)) {
|
||||
+ qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
|
||||
+ "%s", _("hostdev cannot be detached - device state missing"));
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ if (virAsprintf(&cmd, "pci_del pci_addr=%.4x:%.2x:%.2x",
|
||||
+ detach->source.subsys.u.pci.guest_addr.domain,
|
||||
+ detach->source.subsys.u.pci.guest_addr.bus,
|
||||
+ detach->source.subsys.u.pci.guest_addr.slot) < 0) {
|
||||
+ virReportOOMError(conn);
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ if (qemudMonitorCommand(vm, cmd, &reply) < 0) {
|
||||
+ qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
|
||||
+ "%s", _("cannot detach host pci device"));
|
||||
+ VIR_FREE(cmd);
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ DEBUG("%s: pci_del reply: %s", vm->def->name, reply);
|
||||
+
|
||||
+ /* If the command fails due to a wrong PCI address qemu prints
|
||||
+ * 'invalid pci address'; nothing is printed on success */
|
||||
+ if (strstr(reply, "Invalid pci address")) {
|
||||
+ qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
|
||||
+ _("failed to detach host pci device: invalid PCI address %.4x:%.2x:%.2x: %s"),
|
||||
+ detach->source.subsys.u.pci.guest_addr.domain,
|
||||
+ detach->source.subsys.u.pci.guest_addr.bus,
|
||||
+ detach->source.subsys.u.pci.guest_addr.slot,
|
||||
+ reply);
|
||||
+ VIR_FREE(reply);
|
||||
+ VIR_FREE(cmd);
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ VIR_FREE(reply);
|
||||
+ VIR_FREE(cmd);
|
||||
+
|
||||
+ ret = 0;
|
||||
+
|
||||
+ pci = pciGetDevice(conn,
|
||||
+ detach->source.subsys.u.pci.domain,
|
||||
+ detach->source.subsys.u.pci.bus,
|
||||
+ detach->source.subsys.u.pci.slot,
|
||||
+ detach->source.subsys.u.pci.function);
|
||||
+ if (!pci)
|
||||
+ ret = -1;
|
||||
+ else {
|
||||
+ pciDeviceListDel(conn, driver->activePciHostdevs, pci);
|
||||
+ if (pciResetDevice(conn, pci, driver->activePciHostdevs) < 0)
|
||||
+ ret = -1;
|
||||
+ if (detach->managed && pciReAttachDevice(conn, pci) < 0)
|
||||
+ ret = -1;
|
||||
+ pciFreeDevice(conn, pci);
|
||||
+ }
|
||||
+
|
||||
+ if (i != --vm->def->nhostdevs)
|
||||
+ memmove(&vm->def->hostdevs[i],
|
||||
+ &vm->def->hostdevs[i+1],
|
||||
+ sizeof(*vm->def->hostdevs) * (vm->def->nhostdevs-i));
|
||||
+ if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs) < 0) {
|
||||
+ virReportOOMError(conn);
|
||||
+ ret = -1;
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int qemudDomainDetachHostDevice(virConnectPtr conn,
|
||||
+ struct qemud_driver *driver,
|
||||
+ virDomainObjPtr vm,
|
||||
+ virDomainDeviceDefPtr dev)
|
||||
+{
|
||||
+ virDomainHostdevDefPtr hostdev = dev->data.hostdev;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) {
|
||||
+ qemudReportError(conn, dom, NULL, VIR_ERR_NO_SUPPORT,
|
||||
+ _("hostdev mode '%s' not supported"),
|
||||
+ virDomainHostdevModeTypeToString(hostdev->mode));
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ switch (hostdev->source.subsys.type) {
|
||||
+ case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
|
||||
+ ret = qemudDomainDetachHostPciDevice(conn, driver, vm, dev);
|
||||
+ break;
|
||||
+ default:
|
||||
+ qemudReportError(conn, dom, NULL, VIR_ERR_NO_SUPPORT,
|
||||
+ _("hostdev subsys type '%s' not supported"),
|
||||
+ virDomainHostdevSubsysTypeToString(hostdev->source.subsys.type));
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ if (qemuDomainSetDeviceOwnership(conn, driver, dev, 1) < 0)
|
||||
+ VIR_WARN0("Fail to restore disk device ownership");
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
static int qemudDomainDetachDevice(virDomainPtr dom,
|
||||
const char *xml) {
|
||||
struct qemud_driver *driver = dom->conn->privateData;
|
||||
@@ -5670,6 +5914,8 @@ static int qemudDomainDetachDevice(virDomainPtr dom,
|
||||
VIR_WARN0("Fail to restore disk device ownership");
|
||||
} else if (dev->type == VIR_DOMAIN_DEVICE_NET) {
|
||||
ret = qemudDomainDetachNetDevice(dom->conn, vm, dev);
|
||||
+ } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) {
|
||||
+ ret = qemudDomainDetachHostDevice(dom->conn, driver, vm, dev);
|
||||
} else
|
||||
qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
|
||||
"%s", _("only SCSI or virtio disk device can be detached dynamically"));
|
||||
--
|
||||
1.6.2.5
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
From 100eb35a80932cd9a162c38ecd2ab8b01894fb61 Mon Sep 17 00:00:00 2001
|
||||
From: Mark McLoughlin <markmc@redhat.com>
|
||||
Date: Mon, 17 Aug 2009 15:05:22 +0100
|
||||
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 097c818bf00b3777778ffc32fea3a6ed1e741e2b)
|
||||
|
||||
Fedora-patch: libvirt-add-space-to-nodedev-list-tree.patch
|
||||
---
|
||||
src/virsh.c | 4 +++-
|
||||
1 files changed, 3 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/src/virsh.c b/src/virsh.c
|
||||
index 94c3c4e..2d0cf81 100644
|
||||
--- a/src/virsh.c
|
||||
+++ b/src/virsh.c
|
||||
@@ -5370,6 +5370,8 @@ cmdNodeListDevicesPrint(vshControl *ctl,
|
||||
if (depth && depth < MAX_DEPTH) {
|
||||
indentBuf[indentIdx] = '+';
|
||||
indentBuf[indentIdx+1] = '-';
|
||||
+ indentBuf[indentIdx+2] = ' ';
|
||||
+ indentBuf[indentIdx+3] = '\0';
|
||||
}
|
||||
|
||||
/* Print this device */
|
||||
@@ -5398,7 +5400,7 @@ cmdNodeListDevicesPrint(vshControl *ctl,
|
||||
/* If there is a child device, then print another blank line */
|
||||
if (nextlastdev != -1) {
|
||||
vshPrint(ctl, "%s", indentBuf);
|
||||
- vshPrint(ctl, " |\n");
|
||||
+ vshPrint(ctl, " |\n");
|
||||
}
|
||||
|
||||
/* Finally print all children */
|
||||
--
|
||||
1.6.2.5
|
||||
|
||||
@@ -1,812 +0,0 @@
|
||||
From 89eefbd116ae74c3a5cfcfc74a31a40b83c726c3 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 bd63692..4f1b01f 100644
|
||||
--- a/src/libvirt_private.syms
|
||||
+++ b/src/libvirt_private.syms
|
||||
@@ -278,7 +278,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 74f7ef0..96e5d6d 100644
|
||||
--- a/src/pci.c
|
||||
+++ b/src/pci.c
|
||||
@@ -63,6 +63,7 @@ struct _pciDevice {
|
||||
unsigned pci_pm_cap_pos;
|
||||
unsigned has_flr : 1;
|
||||
unsigned has_pm_reset : 1;
|
||||
+ unsigned managed : 1;
|
||||
};
|
||||
|
||||
/* For virReportOOMError() and virReportSystemError() */
|
||||
@@ -225,7 +226,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.
|
||||
@@ -236,7 +237,8 @@ static int
|
||||
pciIterDevices(virConnectPtr conn,
|
||||
pciIterPredicate predicate,
|
||||
pciDevice *dev,
|
||||
- pciDevice **matched)
|
||||
+ pciDevice **matched,
|
||||
+ void *data)
|
||||
{
|
||||
DIR *dir;
|
||||
struct dirent *entry;
|
||||
@@ -254,7 +256,7 @@ pciIterDevices(virConnectPtr conn,
|
||||
|
||||
while ((entry = readdir(dir))) {
|
||||
unsigned domain, bus, slot, function;
|
||||
- pciDevice *try;
|
||||
+ pciDevice *check;
|
||||
|
||||
/* Ignore '.' and '..' */
|
||||
if (entry->d_name[0] == '.')
|
||||
@@ -266,18 +268,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;
|
||||
@@ -379,63 +381,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;
|
||||
}
|
||||
|
||||
@@ -443,9 +452,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;
|
||||
@@ -455,10 +466,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;
|
||||
}
|
||||
|
||||
@@ -572,10 +583,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;
|
||||
|
||||
@@ -594,7 +613,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();
|
||||
@@ -890,8 +909,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 517626a..ab9d5e1 100644
|
||||
--- a/src/qemu_conf.h
|
||||
+++ b/src/qemu_conf.h
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "threads.h"
|
||||
#include "security.h"
|
||||
#include "cgroup.h"
|
||||
+#include "pci.h"
|
||||
|
||||
#define qemudDebug(fmt, ...) do {} while(0)
|
||||
|
||||
@@ -107,6 +108,8 @@ struct qemud_driver {
|
||||
|
||||
char *securityDriverName;
|
||||
virSecurityDriverPtr securityDriver;
|
||||
+
|
||||
+ pciDeviceList *activePciHostdevs;
|
||||
};
|
||||
|
||||
|
||||
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
|
||||
index fd39fc2..cbc27c4 100644
|
||||
--- a/src/qemu_driver.c
|
||||
+++ b/src/qemu_driver.c
|
||||
@@ -128,6 +128,9 @@ static int qemudDomainSetMemoryBalloon(virConnectPtr conn,
|
||||
static int qemudDetectVcpuPIDs(virConnectPtr conn,
|
||||
virDomainObjPtr vm);
|
||||
|
||||
+static int qemuUpdateActivePciHostdevs(struct qemud_driver *driver,
|
||||
+ virDomainDefPtr def);
|
||||
+
|
||||
static struct qemud_driver *qemu_driver = NULL;
|
||||
|
||||
static int qemuCgroupControllerActive(struct qemud_driver *driver,
|
||||
@@ -320,6 +323,10 @@ qemuReconnectDomain(struct qemud_driver *driver,
|
||||
goto error;
|
||||
}
|
||||
|
||||
+ if (qemuUpdateActivePciHostdevs(driver, obj->def) < 0) {
|
||||
+ goto error;
|
||||
+ }
|
||||
+
|
||||
if (obj->def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC &&
|
||||
driver->securityDriver &&
|
||||
driver->securityDriver->domainReserveSecurityLabel &&
|
||||
@@ -524,6 +531,9 @@ qemudStartup(int privileged) {
|
||||
if ((qemu_driver->caps = qemudCapsInit(NULL)) == NULL)
|
||||
goto out_of_memory;
|
||||
|
||||
+ if ((qemu_driver->activePciHostdevs = pciDeviceListNew(NULL)) == NULL)
|
||||
+ goto error;
|
||||
+
|
||||
if (qemudLoadDriverConfig(qemu_driver, driverConf) < 0) {
|
||||
goto error;
|
||||
}
|
||||
@@ -648,6 +658,7 @@ qemudShutdown(void) {
|
||||
return -1;
|
||||
|
||||
qemuDriverLock(qemu_driver);
|
||||
+ pciDeviceListFree(NULL, qemu_driver->activePciHostdevs);
|
||||
virCapabilitiesFree(qemu_driver->caps);
|
||||
|
||||
virDomainObjListFree(&qemu_driver->domains);
|
||||
@@ -1329,48 +1340,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;
|
||||
@@ -1385,95 +1364,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 const char *const defaultDeviceACL[] = {
|
||||
@@ -2001,7 +2036,7 @@ static int qemudStartVMDaemon(virConnectPtr conn,
|
||||
if (qemuSetupCgroup(conn, driver, vm) < 0)
|
||||
goto cleanup;
|
||||
|
||||
- if (qemuPrepareHostDevices(conn, vm->def) < 0)
|
||||
+ if (qemuPrepareHostDevices(conn, driver, vm->def) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (VIR_ALLOC(vm->monitor_chr) < 0) {
|
||||
@@ -2183,7 +2218,7 @@ static void qemudShutdownVMDaemon(virConnectPtr conn,
|
||||
VIR_WARN("Failed to restore all device ownership for %s",
|
||||
vm->def->name);
|
||||
|
||||
- qemuDomainReAttachHostDevices(conn, vm->def);
|
||||
+ qemuDomainReAttachHostDevices(conn, driver, vm->def);
|
||||
|
||||
retry:
|
||||
if ((ret = qemuRemoveCgroup(conn, driver, vm)) < 0) {
|
||||
@@ -6791,6 +6826,7 @@ out:
|
||||
static int
|
||||
qemudNodeDeviceReset (virNodeDevicePtr dev)
|
||||
{
|
||||
+ struct qemud_driver *driver = dev->conn->privateData;
|
||||
pciDevice *pci;
|
||||
unsigned domain, bus, slot, function;
|
||||
int ret = -1;
|
||||
@@ -6802,11 +6838,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 f2ffc25..dfa9ca5 100644
|
||||
--- a/src/xen_unified.c
|
||||
+++ b/src/xen_unified.c
|
||||
@@ -1641,7 +1641,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
|
||||
|
||||
@@ -1,121 +0,0 @@
|
||||
From 5aad00b08cadc4d9da8bffd3d255ffaac98d36dd 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 2dc2e1c..11b3e8b 100644
|
||||
--- a/src/pci.c
|
||||
+++ b/src/pci.c
|
||||
@@ -402,29 +402,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)
|
||||
@@ -529,7 +506,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;
|
||||
@@ -537,16 +514,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);
|
||||
@@ -604,14 +571,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
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
From 165fb333c9d954fec636dc0f1917ba50417478c0 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/network 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 qemudDomainDetachNetDevice() and
|
||||
qemudDomainDetachPciDiskDevice()
|
||||
|
||||
(cherry picked from commit 4e12af5623e4a962a6bb911af06fa29aa85befba)
|
||||
|
||||
Fedora-patch: libvirt-fix-device-list-update-after-detach.patch
|
||||
---
|
||||
src/qemu_driver.c | 38 ++++++++++++++++++--------------------
|
||||
1 files changed, 18 insertions(+), 20 deletions(-)
|
||||
|
||||
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
|
||||
index bd58435..2c4fd6f 100644
|
||||
--- a/src/qemu_driver.c
|
||||
+++ b/src/qemu_driver.c
|
||||
@@ -5404,18 +5404,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:
|
||||
@@ -5503,16 +5502,15 @@ qemudDomainDetachNetDevice(virConnectPtr conn,
|
||||
|
||||
DEBUG("%s: host_net_remove reply: %s", vm->def->name, reply);
|
||||
|
||||
- if (vm->def->nnets > 1) {
|
||||
- vm->def->nets[i] = vm->def->nets[--vm->def->nnets];
|
||||
- if (VIR_REALLOC_N(vm->def->nets, vm->def->nnets) < 0) {
|
||||
- virReportOOMError(conn);
|
||||
- goto cleanup;
|
||||
- }
|
||||
- } else {
|
||||
- VIR_FREE(vm->def->nets[0]);
|
||||
- vm->def->nnets = 0;
|
||||
+ if (i != --vm->def->nnets)
|
||||
+ memmove(&vm->def->nets[i],
|
||||
+ &vm->def->nets[i+1],
|
||||
+ sizeof(*vm->def->nets) * (vm->def->nnets-i));
|
||||
+ if (VIR_REALLOC_N(vm->def->nets, vm->def->nnets) < 0) {
|
||||
+ virReportOOMError(conn);
|
||||
+ goto cleanup;
|
||||
}
|
||||
+
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
--
|
||||
1.6.2.5
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
From f2eb2ad5163d5bae2392a8bfc6040c45426c9f5f 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 99dac52..bf9a0b2 100644
|
||||
--- a/src/qemu_driver.c
|
||||
+++ b/src/qemu_driver.c
|
||||
@@ -6951,7 +6951,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
|
||||
|
||||
@@ -1,141 +0,0 @@
|
||||
From c8a9dbe131713de83bdc67c563c4ab149e32c489 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 11b3e8b..74f7ef0 100644
|
||||
--- a/src/pci.c
|
||||
+++ b/src/pci.c
|
||||
@@ -456,15 +456,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;
|
||||
}
|
||||
|
||||
@@ -475,7 +478,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;
|
||||
}
|
||||
|
||||
@@ -492,9 +497,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);
|
||||
@@ -516,7 +524,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;
|
||||
}
|
||||
|
||||
@@ -533,8 +543,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;
|
||||
}
|
||||
@@ -582,10 +596,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 4ce7a54..fd39fc2 100644
|
||||
--- a/src/qemu_driver.c
|
||||
+++ b/src/qemu_driver.c
|
||||
@@ -1465,9 +1465,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
|
||||
|
||||
@@ -1,124 +0,0 @@
|
||||
From 8f26acc66ca90eea67fd5e84be5a76e3b8aa7fbf 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 2c4fd6f..4ce7a54 100644
|
||||
--- a/src/qemu_driver.c
|
||||
+++ b/src/qemu_driver.c
|
||||
@@ -1402,6 +1402,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 const char *const defaultDeviceACL[] = {
|
||||
"/dev/null", "/dev/full", "/dev/zero",
|
||||
"/dev/random", "/dev/urandom",
|
||||
@@ -2109,6 +2183,8 @@ static void qemudShutdownVMDaemon(virConnectPtr conn,
|
||||
VIR_WARN("Failed to restore all device ownership for %s",
|
||||
vm->def->name);
|
||||
|
||||
+ qemuDomainReAttachHostDevices(conn, vm->def);
|
||||
+
|
||||
retry:
|
||||
if ((ret = qemuRemoveCgroup(conn, driver, vm)) < 0) {
|
||||
if (ret == -EBUSY && (retries++ < 5)) {
|
||||
--
|
||||
1.6.2.5
|
||||
|
||||
+2135
-1030
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user