[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