qemu: Fix probing for guest capabilities

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.
This commit is contained in:
Jiri Denemark 2012-07-13 16:30:55 +02:00
parent a8d63a485e
commit 8e6fb68f1f

View File

@ -646,6 +646,7 @@ qemuCapsInitGuest(virCapsPtr caps,
struct stat st; struct stat st;
unsigned int ncpus; unsigned int ncpus;
virBitmapPtr qemuCaps = NULL; virBitmapPtr qemuCaps = NULL;
virBitmapPtr kvmCaps = NULL;
int ret = -1; int ret = -1;
/* Check for existance of base emulator, or alternate base /* Check for existance of base emulator, or alternate base
@ -658,7 +659,12 @@ qemuCapsInitGuest(virCapsPtr caps,
binary = virFindFileInPath(info->altbinary); 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 * - host & guest arches match
* Or * Or
* - hostarch is x86_64 and guest arch is i686 * - hostarch is x86_64 and guest arch is i686
@ -666,37 +672,44 @@ qemuCapsInitGuest(virCapsPtr caps,
*/ */
if (STREQ(info->arch, hostmachine) || if (STREQ(info->arch, hostmachine) ||
(STREQ(hostmachine, "x86_64") && STREQ(info->arch, "i686"))) { (STREQ(hostmachine, "x86_64") && STREQ(info->arch, "i686"))) {
if (access("/dev/kvm", F_OK) == 0) { const char *const kvmbins[] = { "/usr/libexec/qemu-kvm", /* RHEL */
const char *const kvmbins[] = { "/usr/libexec/qemu-kvm", /* RHEL */ "qemu-kvm", /* Fedora */
"qemu-kvm", /* Fedora */ "kvm" }; /* Upstream .spec */
"kvm" }; /* Upstream .spec */
for (i = 0; i < ARRAY_CARDINALITY(kvmbins); ++i) { for (i = 0; i < ARRAY_CARDINALITY(kvmbins); ++i) {
kvmbin = virFindFileInPath(kvmbins[i]); kvmbin = virFindFileInPath(kvmbins[i]);
if (!kvmbin) if (!kvmbin)
continue; continue;
haskvm = 1; if (qemuCapsExtractVersionInfo(kvmbin, info->arch,
if (!binary) NULL, &kvmCaps) < 0) {
binary = kvmbin; VIR_FREE(kvmbin);
continue;
break;
} }
}
if (access("/dev/kqemu", F_OK) == 0) if (!binary) {
haskqemu = 1; binary = kvmbin;
qemuCaps = kvmCaps;
kvmbin = NULL;
kvmCaps = NULL;
}
break;
}
} }
if (!binary) if (!binary)
return 0; return 0;
/* Ignore binary if extracting version info fails */ if (access("/dev/kvm", F_OK) == 0 &&
if (qemuCapsExtractVersionInfo(binary, info->arch, NULL, &qemuCaps) < 0) { (qemuCapsGet(qemuCaps, QEMU_CAPS_KVM) ||
ret = 0; qemuCapsGet(qemuCaps, QEMU_CAPS_ENABLE_KVM) ||
goto cleanup; kvmbin))
} haskvm = 1;
if (access("/dev/kqemu", F_OK) == 0 &&
qemuCapsGet(qemuCaps, QEMU_CAPS_KQEMU))
haskqemu = 1;
if (stat(binary, &st) == 0) { if (stat(binary, &st) == 0) {
binary_mtime = st.st_mtime; binary_mtime = st.st_mtime;
@ -788,21 +801,23 @@ qemuCapsInitGuest(virCapsPtr caps,
if (haskvm) { if (haskvm) {
virCapsGuestDomainPtr dom; virCapsGuestDomainPtr dom;
if (stat(kvmbin, &st) == 0) { if (kvmbin) {
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)) {
int probe = 1; 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) if (old_caps && binary_mtime)
probe = !qemuCapsGetOldMachines("hvm", info->arch, info->wordsize, probe = !qemuCapsGetOldMachines("hvm", info->arch,
kvmbin, binary_mtime, info->wordsize, kvmbin,
old_caps, &machines, &nmachines); binary_mtime, old_caps,
&machines, &nmachines);
if (probe && if (probe &&
qemuCapsProbeMachineTypes(kvmbin, qemuCaps, qemuCapsProbeMachineTypes(kvmbin, qemuCaps,
&machines, &nmachines) < 0) &machines, &nmachines) < 0)
@ -811,7 +826,7 @@ qemuCapsInitGuest(virCapsPtr caps,
if ((dom = virCapabilitiesAddGuestDomain(guest, if ((dom = virCapabilitiesAddGuestDomain(guest,
"kvm", "kvm",
kvmbin, kvmbin ? kvmbin : binary,
NULL, NULL,
nmachines, nmachines,
machines)) == NULL) { machines)) == NULL) {
@ -846,14 +861,10 @@ qemuCapsInitGuest(virCapsPtr caps,
ret = 0; ret = 0;
cleanup: cleanup:
if (binary == kvmbin) { VIR_FREE(binary);
/* don't double free */ VIR_FREE(kvmbin);
VIR_FREE(binary);
} else {
VIR_FREE(binary);
VIR_FREE(kvmbin);
}
qemuCapsFree(qemuCaps); qemuCapsFree(qemuCaps);
qemuCapsFree(kvmCaps);
return ret; return ret;