diff --git a/src/qemu_conf.c b/src/qemu_conf.c index 22a99ec..f79137f 100644 --- a/src/qemu_conf.c +++ b/src/qemu_conf.c @@ -418,13 +418,14 @@ virCapsPtr qemudCapsInit(void) { int qemudExtractVersionInfo(const char *qemu, unsigned int *retversion, + unsigned int *retkvmversion, unsigned int *retflags) { const char *const qemuarg[] = { qemu, "-help", NULL }; const char *const qemuenv[] = { "LC_ALL=C", NULL }; pid_t child; int newstdout = -1; - int ret = -1, status; - unsigned int major, minor, micro; + int ret = -1, scanret = -1, status; + unsigned int major, minor, micro, kvmver; unsigned int version; unsigned int flags = 0; @@ -443,10 +444,12 @@ int qemudExtractVersionInfo(const char *qemu, if (len < 0) goto cleanup2; - if (sscanf(help, "QEMU PC emulator version %u.%u.%u", - &major, &minor, µ) != 3) { + scanret = sscanf(help, "QEMU PC emulator version %u.%u.%u (kvm-%u", + &major, &minor, µ, &kvmver); + if (scanret == 3) + kvmver = 0; + else if (scanret != 4) goto cleanup2; - } version = (major * 1000 * 1000) + (minor * 1000) + micro; @@ -465,6 +468,8 @@ int qemudExtractVersionInfo(const char *qemu, if (retversion) *retversion = version; + if (retkvmversion) + *retkvmversion = kvmver; if (retflags) *retflags = flags; @@ -472,6 +477,7 @@ int qemudExtractVersionInfo(const char *qemu, qemudDebug("Version %d %d %d Cooked version: %d, with flags ? %d", major, minor, micro, version, flags); + qemudDebug("KVM version: %d", kvmver); cleanup2: VIR_FREE(help); @@ -500,28 +506,34 @@ rewait: return ret; } -int qemudExtractVersion(virConnectPtr conn, - struct qemud_driver *driver) { +int qemudExtractVersion(struct qemud_driver *driver) { const char *binary; struct stat sb; + struct utsname ut; if (driver->qemuVersion > 0) return 0; + uname (&ut); + if ((binary = virCapabilitiesDefaultGuestEmulator(driver->caps, "hvm", + ut.machine, + "kvm")) == NULL && + (binary = virCapabilitiesDefaultGuestEmulator(driver->caps, + "hvm", "i686", "qemu")) == NULL) return -1; if (stat(binary, &sb) < 0) { - qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, - _("Cannot find QEMU binary %s: %s"), binary, - strerror(errno)); return -1; } - if (qemudExtractVersionInfo(binary, &driver->qemuVersion, NULL) < 0) { + if (qemudExtractVersionInfo(binary, + &driver->qemuVersion, + &driver->kvmVersion, + NULL) < 0) { return -1; } diff --git a/src/qemu_conf.h b/src/qemu_conf.h index 88dfade..8d429fb 100644 --- a/src/qemu_conf.h +++ b/src/qemu_conf.h @@ -50,6 +50,7 @@ enum qemud_cmd_flags { /* Main driver state */ struct qemud_driver { unsigned int qemuVersion; + unsigned int kvmVersion; int nextvmid; virDomainObjPtr domains; @@ -83,10 +84,10 @@ int qemudLoadDriverConfig(struct qemud_driver *driver, virCapsPtr qemudCapsInit (void); -int qemudExtractVersion (virConnectPtr conn, - struct qemud_driver *driver); +int qemudExtractVersion (struct qemud_driver *driver); int qemudExtractVersionInfo (const char *qemu, unsigned int *version, + unsigned int *kvmversion, unsigned int *flags); int qemudBuildCommandLine (virConnectPtr conn, diff --git a/src/qemu_driver.c b/src/qemu_driver.c index 0c04da6..d1b9d7c 100644 --- a/src/qemu_driver.c +++ b/src/qemu_driver.c @@ -240,6 +240,12 @@ qemudStartup(void) { if ((qemu_driver->caps = qemudCapsInit()) == NULL) goto out_of_memory; + // Dependent on capabilities being initialized + if (qemudExtractVersion(qemu_driver) < 0) { + qemudShutdown(); + return -1; + } + if (qemudLoadDriverConfig(qemu_driver, driverConf) < 0) { qemudShutdown(); return -1; @@ -923,7 +929,7 @@ static int qemudStartVMDaemon(virConnectPtr conn, } if (qemudExtractVersionInfo(vm->def->emulator, - NULL, + NULL, NULL, &qemuCmdFlags) < 0) { qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("Cannot determine QEMU argv syntax %s"), @@ -1793,11 +1799,20 @@ static const char *qemudGetType(virConnectPtr conn ATTRIBUTE_UNUSED) { } -static int kvmGetMaxVCPUs(void) { - int maxvcpus = 1; +static int kvmGetMaxVCPUs(virConnectPtr conn) { + + struct qemud_driver *driver = (struct qemud_driver *)conn->privateData; + int maxvcpus = 1, r, fd; + + // KVM-30 added support for up to 4 vcpus + // KVM-62 raised this to 16 + if (driver->kvmVersion < 30) + maxvcpus = 1; + else if (driver->kvmVersion < 62) + maxvcpus = 4; + else + maxvcpus = 16; - int r, fd; - fd = open(KVM_DEVICE, O_RDONLY); if (fd < 0) { qemudLog(QEMUD_WARN, _("Unable to open " KVM_DEVICE ": %s\n"), strerror(errno)); @@ -1820,10 +1835,8 @@ static int qemudGetMaxVCPUs(virConnectPtr conn, const char *type) { if (STRCASEEQ(type, "qemu")) return 16; - /* XXX future KVM will support SMP. Need to probe - kernel to figure out KVM module version i guess */ if (STRCASEEQ(type, "kvm")) - return kvmGetMaxVCPUs(); + return kvmGetMaxVCPUs(conn); if (STRCASEEQ(type, "kqemu")) return 1; @@ -1993,7 +2006,7 @@ static virDomainPtr qemudDomainLookupByName(virConnectPtr conn, static int qemudGetVersion(virConnectPtr conn, unsigned long *version) { struct qemud_driver *driver = (struct qemud_driver *)conn->privateData; - if (qemudExtractVersion(conn, driver) < 0) + if (qemudExtractVersion(driver) < 0) return -1; *version = qemu_driver->qemuVersion; @@ -3035,7 +3048,7 @@ static int qemudDomainChangeEjectableMedia(virDomainPtr dom, } if (qemudExtractVersionInfo(vm->def->emulator, - NULL, + NULL, NULL, &qemuCmdFlags) < 0) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, _("Cannot determine QEMU argv syntax %s"),