diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 2af441803c..ffe7bcdf43 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -3492,25 +3492,21 @@ virQEMUCapsInitCached(virCapsPtr caps, VIR_WARN("Failed to load cached caps from '%s' for '%s': %s", capsfile, qemuCaps->binary, virGetLastErrorMessage()); virResetLastError(); - ret = 0; - virQEMUCapsReset(qemuCaps); - goto cleanup; + goto discard; } + if (!virQEMUCapsIsValid(qemuCaps, qemuctime)) + goto discard; + /* Discard cache if QEMU binary or libvirtd changed */ - if (qemuctime != qemuCaps->ctime || - selfctime != virGetSelfLastChanged() || + if (selfctime != virGetSelfLastChanged() || selfvers != LIBVIR_VERSION_NUMBER) { - VIR_DEBUG("Outdated cached capabilities '%s' for '%s' " - "(%lld vs %lld, %lld vs %lld, %lu vs %lu)", - capsfile, qemuCaps->binary, - (long long)qemuCaps->ctime, (long long)qemuctime, + VIR_DEBUG("Outdated capabilities for '%s': libvirt changed " + "(%lld vs %lld, %lu vs %lu)", + qemuCaps->binary, (long long)selfctime, (long long)virGetSelfLastChanged(), selfvers, (unsigned long)LIBVIR_VERSION_NUMBER); - ignore_value(unlink(capsfile)); - virQEMUCapsReset(qemuCaps); - ret = 0; - goto cleanup; + goto discard; } VIR_DEBUG("Loaded '%s' for '%s' ctime %lld usedQMP=%d", @@ -3524,6 +3520,14 @@ virQEMUCapsInitCached(virCapsPtr caps, VIR_FREE(capsfile); VIR_FREE(capsdir); return ret; + + discard: + VIR_DEBUG("Dropping cached capabilities '%s' for '%s'", + capsfile, qemuCaps->binary); + ignore_value(unlink(capsfile)); + virQEMUCapsReset(qemuCaps); + ret = 0; + goto cleanup; } @@ -4076,17 +4080,35 @@ virQEMUCapsNewForBinary(virCapsPtr caps, } -bool virQEMUCapsIsValid(virQEMUCapsPtr qemuCaps) +bool +virQEMUCapsIsValid(virQEMUCapsPtr qemuCaps, + time_t ctime) { - struct stat sb; - if (!qemuCaps->binary) return true; - if (stat(qemuCaps->binary, &sb) < 0) - return false; + if (!ctime) { + struct stat sb; - return sb.st_ctime == qemuCaps->ctime; + if (stat(qemuCaps->binary, &sb) < 0) { + char ebuf[1024]; + VIR_DEBUG("Failed to stat QEMU binary '%s': %s", + qemuCaps->binary, + virStrerror(errno, ebuf, sizeof(ebuf))); + return false; + } + ctime = sb.st_ctime; + } + + if (ctime != qemuCaps->ctime) { + VIR_DEBUG("Outdated capabilities for '%s': QEMU binary changed " + "(%lld vs %lld)", + qemuCaps->binary, + (long long) ctime, (long long) qemuCaps->ctime); + return false; + } + + return true; } @@ -4179,7 +4201,7 @@ virQEMUCapsCacheLookup(virCapsPtr caps, virMutexLock(&cache->lock); ret = virHashLookup(cache->binaries, binary); if (ret && - !virQEMUCapsIsValid(ret)) { + !virQEMUCapsIsValid(ret, 0)) { VIR_DEBUG("Cached capabilities %p no longer valid for %s", ret, binary); virHashRemoveEntry(cache->binaries, binary); diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 983ea75874..d1044043f6 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -451,7 +451,8 @@ int virQEMUCapsGetMachineTypesCaps(virQEMUCapsPtr qemuCaps, size_t *nmachines, virCapsGuestMachinePtr **machines); -bool virQEMUCapsIsValid(virQEMUCapsPtr qemuCaps); +bool virQEMUCapsIsValid(virQEMUCapsPtr qemuCaps, + time_t ctime); void virQEMUCapsFilterByMachineType(virQEMUCapsPtr qemuCaps, const char *machineType);