[libvirt] [PATCH] qemu: Fix probing for guest capabilities

Jiri Denemark jdenemar at redhat.com
Fri Jul 13 15:00:00 UTC 2012


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




More information about the libvir-list mailing list