Even though qemu-kvm binaries can be used in TCG mode, libvirt would
only detect them if /dev/kvm was available. Thus, one would need to make
a /usr/bin/qemu symlink to be able to use TCG mode with qemu-kvm in an
environment without KVM support.
And even though QEMU is able to make use of KVM, libvirt would not
advertise KVM support unless there was a qemu-kvm symlink available.
This patch fixes both issues.
---
src/qemu/qemu_capabilities.c | 95 ++++++++++++++++++++++++--------------------
1 file changed, 53 insertions(+), 42 deletions(-)
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 9e4d927..cbea365 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -645,6 +645,7 @@ qemuCapsInitGuest(virCapsPtr caps,
struct stat st;
unsigned int ncpus;
virBitmapPtr qemuCaps = NULL;
+ virBitmapPtr kvmCaps = NULL;
int ret = -1;
/* Check for existance of base emulator, or alternate base
@@ -657,7 +658,12 @@ qemuCapsInitGuest(virCapsPtr caps,
binary = virFindFileInPath(info->altbinary);
}
- /* Can use acceleration for KVM/KQEMU if
+ /* Ignore binary if extracting version info fails */
+ if (binary &&
+ qemuCapsExtractVersionInfo(binary, info->arch, NULL, &qemuCaps) < 0)
+ VIR_FREE(binary);
+
+ /* qemu-kvm/kvm binaries can only be used if
* - host & guest arches match
* Or
* - hostarch is x86_64 and guest arch is i686
@@ -665,37 +671,44 @@ qemuCapsInitGuest(virCapsPtr caps,
*/
if (STREQ(info->arch, hostmachine) ||
(STREQ(hostmachine, "x86_64") && STREQ(info->arch,
"i686"))) {
- if (access("/dev/kvm", F_OK) == 0) {
- const char *const kvmbins[] = { "/usr/libexec/qemu-kvm", /* RHEL
*/
- "qemu-kvm", /* Fedora */
- "kvm" }; /* Upstream .spec */
+ const char *const kvmbins[] = { "/usr/libexec/qemu-kvm", /* RHEL */
+ "qemu-kvm", /* Fedora */
+ "kvm" }; /* Upstream .spec */
- for (i = 0; i < ARRAY_CARDINALITY(kvmbins); ++i) {
- kvmbin = virFindFileInPath(kvmbins[i]);
+ for (i = 0; i < ARRAY_CARDINALITY(kvmbins); ++i) {
+ kvmbin = virFindFileInPath(kvmbins[i]);
- if (!kvmbin)
- continue;
+ if (!kvmbin)
+ continue;
- haskvm = 1;
- if (!binary)
- binary = kvmbin;
+ if (qemuCapsExtractVersionInfo(kvmbin, info->arch,
+ NULL, &kvmCaps) < 0) {
+ VIR_FREE(kvmbin);
+ continue;
+ }
- break;
+ if (!binary) {
+ binary = kvmbin;
+ qemuCaps = kvmCaps;
+ kvmbin = NULL;
+ kvmCaps = NULL;
}
+ break;
}
-
- if (access("/dev/kqemu", F_OK) == 0)
- haskqemu = 1;
}
if (!binary)
return 0;
- /* Ignore binary if extracting version info fails */
- if (qemuCapsExtractVersionInfo(binary, info->arch, NULL, &qemuCaps) < 0) {
- ret = 0;
- goto cleanup;
- }
+ if (access("/dev/kvm", F_OK) == 0 &&
+ (qemuCapsGet(qemuCaps, QEMU_CAPS_KVM) ||
+ qemuCapsGet(qemuCaps, QEMU_CAPS_ENABLE_KVM) ||
+ kvmbin))
+ haskvm = 1;
+
+ if (access("/dev/kqemu", F_OK) == 0 &&
+ qemuCapsGet(qemuCaps, QEMU_CAPS_KQEMU))
+ haskqemu = 1;
if (stat(binary, &st) == 0) {
binary_mtime = st.st_mtime;
@@ -787,21 +800,23 @@ qemuCapsInitGuest(virCapsPtr caps,
if (haskvm) {
virCapsGuestDomainPtr dom;
- if (stat(kvmbin, &st) == 0) {
- binary_mtime = st.st_mtime;
- } else {
- char ebuf[1024];
- VIR_WARN("Failed to stat %s, most peculiar : %s",
- binary, virStrerror(errno, ebuf, sizeof(ebuf)));
- binary_mtime = 0;
- }
-
- if (!STREQ(binary, kvmbin)) {
+ if (kvmbin) {
int probe = 1;
+
+ if (stat(kvmbin, &st) == 0) {
+ binary_mtime = st.st_mtime;
+ } else {
+ char ebuf[1024];
+ VIR_WARN("Failed to stat %s, most peculiar : %s",
+ binary, virStrerror(errno, ebuf, sizeof(ebuf)));
+ binary_mtime = 0;
+ }
+
if (old_caps && binary_mtime)
- probe = !qemuCapsGetOldMachines("hvm", info->arch,
info->wordsize,
- kvmbin, binary_mtime,
- old_caps, &machines,
&nmachines);
+ probe = !qemuCapsGetOldMachines("hvm", info->arch,
+ info->wordsize, kvmbin,
+ binary_mtime, old_caps,
+ &machines, &nmachines);
if (probe &&
qemuCapsProbeMachineTypes(kvmbin, qemuCaps,
&machines, &nmachines) < 0)
@@ -810,7 +825,7 @@ qemuCapsInitGuest(virCapsPtr caps,
if ((dom = virCapabilitiesAddGuestDomain(guest,
"kvm",
- kvmbin,
+ kvmbin ? kvmbin : binary,
NULL,
nmachines,
machines)) == NULL) {
@@ -845,14 +860,10 @@ qemuCapsInitGuest(virCapsPtr caps,
ret = 0;
cleanup:
- if (binary == kvmbin) {
- /* don't double free */
- VIR_FREE(binary);
- } else {
- VIR_FREE(binary);
- VIR_FREE(kvmbin);
- }
+ VIR_FREE(binary);
+ VIR_FREE(kvmbin);
qemuCapsFree(qemuCaps);
+ qemuCapsFree(kvmCaps);
return ret;
--
1.7.11.1