[libvirt] [PATCH RFC 3/8] qemu: add qemu emulator cache framework
Daniel Veillard
veillard at redhat.com
Mon Mar 12 07:47:09 UTC 2012
On Sun, Mar 11, 2012 at 02:45:04PM -0400, Lee Schermerhorn wrote:
> Define a qemu emulator cache structure and function to lookup,
> create, refresh emulator cache objects. The cache "tags" are
> the paths to the emulator binaries. E.g., "/usr/bin/qemu"
>
> Subsequent patches will "hook up" the various extract/probe info
> functions to consult the cache.
>
> Notes/questions:
> 1) "qemuCapsProbes" converted to bitmap along with capabilities flags
> as part of rebase. Overkill?
> 2) Is it OK for the root of the cache and the nEmulators to be statically
> defined in qemu_capabilities.c as opposed to a field in the driver struct?
> It is private to that source file and I don't see an easy wait to get
> a handle on the driver struct therein.
>
> ---
> src/qemu/qemu_capabilities.c | 166 +++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 166 insertions(+)
>
> Index: libvirt-0.9.10/src/qemu/qemu_capabilities.c
> ===================================================================
> --- libvirt-0.9.10.orig/src/qemu/qemu_capabilities.c
> +++ libvirt-0.9.10/src/qemu/qemu_capabilities.c
> @@ -170,6 +170,46 @@ struct qemu_arch_info {
> int nflags;
> };
>
> +/*
> + * * Flags to record which "probes" have been cached
> + * */
> +enum qemuCapsProbes {
> + QEMU_PROBE_VERSION_INFO = 0,
> + QEMU_PROBE_MACHINE_TYPES = 1,
> + QEMU_PROBE_CPU_MODELS = 2,
> + QEMU_PROBE_SIZE
> +};
> +
> +typedef struct _qemuEmulatorCache qemuEmulatorCache;
> +typedef qemuEmulatorCache* qemuEmulatorCachePtr;
> +struct _qemuEmulatorCache {
> + char *path;
> + char *arch;
> + time_t mtime;
> + virBitmapPtr cachedProbes;
> +
> + unsigned int version;
> + virBitmapPtr caps;
> +
> + virCapsGuestMachinePtr *machines;
> + int nmachines;
> +
> + char **cpus;
> + unsigned int ncpus;
> +};
> +
> +static qemuEmulatorCachePtr *emulatorCache = NULL;
> +static int nEmulators;
> +
> +static qemuEmulatorCachePtr
> +qemuEmulatorCachedInfoGet(enum qemuCapsProbes,
> + const char *binary,
> + const char *arch);
> +
> +static void
> +qemuEmulatorCachedInfoRelease(qemuEmulatorCachePtr emulator ATTRIBUTE_UNUSED)
> +{ }
> +
> /* Feature flags for the architecture info */
> static const struct qemu_feature_flags const arch_info_i686_flags [] = {
> { "pae", 1, 0 },
> @@ -319,6 +359,12 @@ cleanup:
> }
>
> static int
> +qemuCapsCacheMachineTypes(qemuEmulatorCachePtr emulator)
> +{
> + return emulator ? 0 : 1;
> +}
> +
> +static int
> qemuCapsGetOldMachinesFromInfo(virCapsGuestDomainInfoPtr info,
> const char *emulator,
> time_t emulator_mtime,
> @@ -612,6 +658,11 @@ cleanup:
> return ret;
> }
>
> +static int
> +qemuCapsCacheCPUModels(qemuEmulatorCachePtr emulator)
> +{
> + return emulator ? 0 : 1;
> +}
>
> static int
> qemuCapsInitGuest(virCapsPtr caps,
> @@ -1510,6 +1561,12 @@ cleanup:
> return ret;
> }
>
> +static int
> +qemuCapsCacheVersionInfo(qemuEmulatorCachePtr emulator)
> +{
> + return emulator ? 0 : 1;
> +}
> +
> static void
> uname_normalize (struct utsname *ut)
> {
> @@ -1610,3 +1667,112 @@ qemuCapsGet(virBitmapPtr caps,
> else
> return b;
> }
> +
> +static qemuEmulatorCachePtr
> +qemuEmulatorCachedInfoGet(enum qemuCapsProbes probe,
> + const char *binary,
> + const char *arch)
> +{
> + qemuEmulatorCachePtr emulator = NULL;
> + struct stat st;
> + bool alreadyCached;
> + int i;
> +
> + if (stat(binary, &st) != 0) {
> + char ebuf[1024];
> + VIR_INFO("Failed to stat emulator %s : %s",
> + binary, virStrerror(errno, ebuf, sizeof(ebuf)));
> + goto error;
Hum ... seems to me we should still go though the emulator cache
here and discard cached info (if present) for that path
> + }
> +
> + for (i = 0; i < nEmulators; ++i) {
> + emulator = emulatorCache[i];
> +
> + if (!STREQ(binary, emulator->path))
> + continue;
> +
> + if (arch && !emulator->arch) {
> + if (!(emulator->arch = strdup(arch)))
> + goto no_memory;
> + /*
> + * We have an 'arch' now, where we didn't before.
> + * So, even if we've already cached this probe,
> + * refresh the cache with the specified arch.
> + */
> + break;
> + }
> +
> + if (st.st_mtime != emulator->mtime)
> + break; /* binary changed, refresh cache */
> +
> + if (virBitmapGetBit(emulator->cachedProbes, probe, &alreadyCached) < 0) {
> + VIR_ERROR(_("Unrecognized probe id '%d'"), probe);
> + goto error;
> + }
> + if (!alreadyCached)
> + break; /* do it now */
> +
> + return emulator;
> + }
> +
> + if (i == nEmulators) {
> + if (VIR_REALLOC_N(emulatorCache, nEmulators + 1) < 0)
> + goto no_memory;
> + if (VIR_ALLOC(emulator) < 0)
> + goto no_memory;
> + if (!(emulator->path = strdup(binary)))
> + goto no_memory_free_emulator;
> + if (arch && !(emulator->arch = strdup(arch)))
> + goto no_memory_free_emulator;
> + if (!(emulator->cachedProbes = virBitmapAlloc(QEMU_PROBE_SIZE)))
> + goto no_memory_free_emulator;
> + VIR_DEBUG("Adding emulator cache for %s - %s",
> + emulator->path, emulator->arch);
> + emulatorCache[nEmulators] = emulator;
> + nEmulators += 1;
> + } else {
> + VIR_DEBUG("Refreshing emulator cache for %s - %s",
> + emulator->path, emulator->arch);
> + }
> +
> + switch (probe) {
> +
> + case QEMU_PROBE_VERSION_INFO:
> + if (qemuCapsCacheVersionInfo(emulator) != 0 ||
> + virBitmapSetBit(emulator->cachedProbes, QEMU_PROBE_VERSION_INFO) < 0)
> + goto error;
> + break;
> +
> + case QEMU_PROBE_MACHINE_TYPES:
> + if (qemuCapsCacheMachineTypes(emulator) != 0 ||
> + virBitmapSetBit(emulator->cachedProbes, QEMU_PROBE_MACHINE_TYPES) < 0)
> + goto error;
> + break;
> +
> + case QEMU_PROBE_CPU_MODELS:
> + if (qemuCapsCacheCPUModels(emulator) != 0 ||
> + virBitmapSetBit(emulator->cachedProbes, QEMU_PROBE_CPU_MODELS) < 0)
> + goto error;
> + break;
> +
> + default:
> + /* We REALLY shouldn't get here... */
> + VIR_ERROR(_("Unrecognized probe id '%d'"), probe);
> + goto error;
> + }
> +
> +
> + emulator->mtime = st.st_mtime;
> + return emulator;
> +
> +no_memory_free_emulator:
> + VIR_FREE(emulator->path);
> + VIR_FREE(emulator->arch);
> + VIR_FREE(emulator);
> +
> +no_memory:
> + virReportOOMError();
> +
> +error:
> + return NULL;
> +}
>
> --
> libvir-list mailing list
> libvir-list at redhat.com
> https://www.redhat.com/mailman/listinfo/libvir-list
--
Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/
daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/
http://veillard.com/ | virtualization library http://libvirt.org/
More information about the libvir-list
mailing list