mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-03-07 17:28:15 +00:00
Only probe qemu for machine types when binary changes
By probing for qemu machine types, we increased the time of a GetCapabilities call from 100us to a whopping 60ms. This patch takes the approach of only probing for machine types when the mtime of the emulator binary changed since the last time the capabilities were generated. * src/capabilities.h: cache the emulator binary mtime * src/qemu_conf.c: add qemudGetOldMachines() to copy the machine types from the old caps struct if the mtime for the binary hasn't changed * src/qemu_conf.h, src/qemu_driver.c: pass the old caps pointer to qemudCapsInit()
This commit is contained in:
parent
0f15d0344d
commit
707302b2cf
@ -49,6 +49,7 @@ struct _virCapsGuestDomainInfo {
|
||||
char *loader;
|
||||
int nmachines;
|
||||
virCapsGuestMachinePtr *machines;
|
||||
time_t emulator_mtime; /* do @machines need refreshing? */
|
||||
};
|
||||
|
||||
typedef struct _virCapsGuestDomain virCapsGuestDomain;
|
||||
|
@ -456,8 +456,73 @@ rewait:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
qemudGetOldMachines(const char *ostype,
|
||||
const char *arch,
|
||||
int wordsize,
|
||||
const char *emulator,
|
||||
time_t emulator_mtime,
|
||||
virCapsPtr old_caps,
|
||||
virCapsGuestMachinePtr **machines,
|
||||
int *nmachines)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < old_caps->nguests; i++) {
|
||||
virCapsGuestPtr guest = old_caps->guests[i];
|
||||
virCapsGuestDomainInfoPtr info = &guest->arch.defaultInfo;
|
||||
virCapsGuestMachinePtr *list;
|
||||
|
||||
if (!STREQ(ostype, guest->ostype) ||
|
||||
!STREQ(arch, guest->arch.name) ||
|
||||
wordsize != guest->arch.wordsize ||
|
||||
!STREQ(emulator, info->emulator))
|
||||
continue;
|
||||
|
||||
if (emulator_mtime != info->emulator_mtime) {
|
||||
VIR_DEBUG("mtime on %s has changed, refreshing machine types",
|
||||
info->emulator);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* It sucks to have to dup these, when we're most likely going
|
||||
* to free the old caps anyway - except if an error occurs, we'll
|
||||
* stick with the old caps.
|
||||
* Also, if we get OOM here, just let the caller try and probe
|
||||
* the binary directly, which will probably fail too.
|
||||
*/
|
||||
if (VIR_ALLOC_N(list, info->nmachines) < 0)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < info->nmachines; i++) {
|
||||
if (VIR_ALLOC(list[i]) < 0) {
|
||||
virCapabilitiesFreeMachines(list, info->nmachines);
|
||||
return 0;
|
||||
}
|
||||
if (info->machines[i]->name &&
|
||||
!(list[i]->name = strdup(info->machines[i]->name))) {
|
||||
virCapabilitiesFreeMachines(list, info->nmachines);
|
||||
return 0;
|
||||
}
|
||||
if (info->machines[i]->canonical &&
|
||||
!(list[i]->canonical = strdup(info->machines[i]->canonical))) {
|
||||
virCapabilitiesFreeMachines(list, info->nmachines);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
*machines = list;
|
||||
*nmachines = info->nmachines;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
qemudCapsInitGuest(virCapsPtr caps,
|
||||
virCapsPtr old_caps,
|
||||
const char *hostmachine,
|
||||
const struct qemu_arch_info *info,
|
||||
int hvm) {
|
||||
@ -467,8 +532,10 @@ qemudCapsInitGuest(virCapsPtr caps,
|
||||
int haskqemu = 0;
|
||||
const char *kvmbin = NULL;
|
||||
const char *binary = NULL;
|
||||
time_t binary_mtime;
|
||||
virCapsGuestMachinePtr *machines = NULL;
|
||||
int nmachines = 0;
|
||||
struct stat st;
|
||||
|
||||
/* Check for existance of base emulator, or alternate base
|
||||
* which can be used with magic cpu choice
|
||||
@ -507,6 +574,15 @@ qemudCapsInitGuest(virCapsPtr caps,
|
||||
if (!binary)
|
||||
return 0;
|
||||
|
||||
if (stat(binary, &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 (info->machine) {
|
||||
virCapsGuestMachinePtr machine;
|
||||
|
||||
@ -526,9 +602,16 @@ qemudCapsInitGuest(virCapsPtr caps,
|
||||
|
||||
machines[0] = machine;
|
||||
nmachines = 1;
|
||||
|
||||
} else if (qemudProbeMachineTypes(binary, &machines, &nmachines) < 0)
|
||||
} else {
|
||||
int probe = 1;
|
||||
if (old_caps && binary_mtime)
|
||||
probe = !qemudGetOldMachines(hvm ? "hvm" : "xen", info->arch,
|
||||
info->wordsize, binary, binary_mtime,
|
||||
old_caps, &machines, &nmachines);
|
||||
if (probe &&
|
||||
qemudProbeMachineTypes(binary, &machines, &nmachines) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* We register kvm as the base emulator too, since we can
|
||||
* just give -no-kvm to disable acceleration if required */
|
||||
@ -548,6 +631,8 @@ qemudCapsInitGuest(virCapsPtr caps,
|
||||
return -1;
|
||||
}
|
||||
|
||||
guest->arch.defaultInfo.emulator_mtime = binary_mtime;
|
||||
|
||||
if (hvm) {
|
||||
if (virCapabilitiesAddGuestDomain(guest,
|
||||
"qemu",
|
||||
@ -597,7 +682,7 @@ qemudCapsInitGuest(virCapsPtr caps,
|
||||
return 0;
|
||||
}
|
||||
|
||||
virCapsPtr qemudCapsInit(void) {
|
||||
virCapsPtr qemudCapsInit(virCapsPtr old_caps) {
|
||||
struct utsname utsname;
|
||||
virCapsPtr caps;
|
||||
int i;
|
||||
@ -626,7 +711,7 @@ virCapsPtr qemudCapsInit(void) {
|
||||
|
||||
/* First the pure HVM guests */
|
||||
for (i = 0 ; i < ARRAY_CARDINALITY(arch_info_hvm) ; i++)
|
||||
if (qemudCapsInitGuest(caps,
|
||||
if (qemudCapsInitGuest(caps, old_caps,
|
||||
utsname.machine,
|
||||
&arch_info_hvm[i], 1) < 0)
|
||||
goto no_memory;
|
||||
@ -639,7 +724,7 @@ virCapsPtr qemudCapsInit(void) {
|
||||
if (STREQ(arch_info_xen[i].arch, utsname.machine) ||
|
||||
(STREQ(utsname.machine, "x86_64") &&
|
||||
STREQ(arch_info_xen[i].arch, "i686"))) {
|
||||
if (qemudCapsInitGuest(caps,
|
||||
if (qemudCapsInitGuest(caps, old_caps,
|
||||
utsname.machine,
|
||||
&arch_info_xen[i], 0) < 0)
|
||||
goto no_memory;
|
||||
|
@ -125,7 +125,7 @@ struct qemud_driver {
|
||||
int qemudLoadDriverConfig(struct qemud_driver *driver,
|
||||
const char *filename);
|
||||
|
||||
virCapsPtr qemudCapsInit (void);
|
||||
virCapsPtr qemudCapsInit (virCapsPtr old_caps);
|
||||
|
||||
int qemudExtractVersion (virConnectPtr conn,
|
||||
struct qemud_driver *driver);
|
||||
|
@ -516,7 +516,7 @@ qemudStartup(int privileged) {
|
||||
virStrerror(-rc, buf, sizeof(buf)));
|
||||
}
|
||||
|
||||
if ((qemu_driver->caps = qemudCapsInit()) == NULL)
|
||||
if ((qemu_driver->caps = qemudCapsInit(NULL)) == NULL)
|
||||
goto out_of_memory;
|
||||
|
||||
if (qemudLoadDriverConfig(qemu_driver, driverConf) < 0) {
|
||||
@ -2440,7 +2440,7 @@ static char *qemudGetCapabilities(virConnectPtr conn) {
|
||||
char *xml = NULL;
|
||||
|
||||
qemuDriverLock(driver);
|
||||
if ((caps = qemudCapsInit()) == NULL) {
|
||||
if ((caps = qemudCapsInit(qemu_driver->caps)) == NULL) {
|
||||
virReportOOMError(conn);
|
||||
goto cleanup;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user