Currently the QEMU capabilities cache files on disk are only
invalidated if the QEMU binary changes. New versions of libvirt,
however, may want to extract more information from existing
binaries. Thus we must take into account modification time of
the libvirtd daemon and/or any loadable driver modules when
checking cache validity
Signed-off-by: Daniel P. Berrange <berrange(a)redhat.com>
---
daemon/libvirtd.c | 2 ++
src/driver.c | 2 ++
src/libvirt_private.syms | 2 ++
src/qemu/qemu_capabilities.c | 24 +++++++++++++++---------
src/util/virutil.c | 23 +++++++++++++++++++++++
src/util/virutil.h | 4 ++++
6 files changed, 48 insertions(+), 9 deletions(-)
diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c
index 72f0e81..d8226a4 100644
--- a/daemon/libvirtd.c
+++ b/daemon/libvirtd.c
@@ -1152,6 +1152,8 @@ int main(int argc, char **argv) {
exit(EXIT_FAILURE);
}
+ virUpdateSelfLastModified(argv[0]);
+
if (strstr(argv[0], "lt-libvirtd") ||
strstr(argv[0], "/daemon/.libs/libvirtd")) {
char *tmp = strrchr(argv[0], '/');
diff --git a/src/driver.c b/src/driver.c
index ab2a253..2acf39c 100644
--- a/src/driver.c
+++ b/src/driver.c
@@ -74,6 +74,8 @@ virDriverLoadModule(const char *name)
goto cleanup;
}
+ virUpdateSelfLastModified(modfile);
+
handle = dlopen(modfile, RTLD_NOW | RTLD_GLOBAL);
if (!handle) {
VIR_ERROR(_("failed to load module %s %s"), modfile, dlerror());
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 00e3d9c..82a8918 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1954,6 +1954,7 @@ virGetGroupID;
virGetGroupList;
virGetGroupName;
virGetHostname;
+virGetSelfLastModified;
virGetUnprivSGIOSysfsPath;
virGetUserCacheDirectory;
virGetUserConfigDirectory;
@@ -1983,6 +1984,7 @@ virSetNonBlock;
virSetUIDGID;
virSetUIDGIDWithCaps;
virStrIsPrint;
+virUpdateSelfLastModified;
virValidateWWN;
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index e3ed960..3dfaf48 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -2564,18 +2564,21 @@ virQEMUCapsSaveCache(virQEMUCapsPtr qemuCaps, const char
*filename)
goto cleanup;
}
- ut.actime = qemuCaps->mtime;
- ut.modtime = qemuCaps->mtime;
+ ut.modtime = virGetSelfLastModified();
+ if (qemuCaps->mtime > ut.modtime)
+ ut.modtime = qemuCaps->mtime;
+
+ ut.actime = ut.modtime;
if (utime(filename, &ut) < 0) {
virReportSystemError(errno,
- _("Failed to set mtime on '%s' for
'%s'"),
- filename, qemuCaps->binary);
+ _("Failed to set mtime on '%s' for '%s'
to %lld"),
+ filename, qemuCaps->binary, (long long)ut.modtime);
ignore_value(unlink(filename));
goto cleanup;
}
VIR_DEBUG("Saved caps '%s' for '%s' with %lld",
- filename, qemuCaps->binary, (long long)qemuCaps->mtime);
+ filename, qemuCaps->binary, (long long)ut.modtime);
ret = 0;
cleanup:
@@ -2654,6 +2657,7 @@ virQEMUCapsInitCached(virQEMUCapsPtr qemuCaps, const char
*cacheDir)
int ret = -1;
char *binaryhash = NULL;
struct stat sb;
+ time_t selfmtime = virGetSelfLastModified();
if (virAsprintf(&capsdir, "%s/capabilities", cacheDir) < 0)
goto cleanup;
@@ -2687,11 +2691,13 @@ virQEMUCapsInitCached(virQEMUCapsPtr qemuCaps, const char
*cacheDir)
}
/* Discard if cache is older that QEMU binary */
- /* XXX must also compare to libvirtd timestamp */
- if (sb.st_mtime < qemuCaps->mtime) {
- VIR_DEBUG("Outdated cached capabilities '%s' for '%s' (%lld
vs %lld)",
+ if (sb.st_mtime < qemuCaps->mtime ||
+ sb.st_mtime < selfmtime) {
+ VIR_DEBUG("Outdated cached capabilities '%s' for '%s'
(%lld,%lld vs %lld)",
capsfile, qemuCaps->binary,
- (long long)sb.st_mtime, (long long)qemuCaps->mtime);
+ (long long)sb.st_mtime,
+ (long long)selfmtime,
+ (long long)qemuCaps->mtime);
ignore_value(unlink(capsfile));
ret = 0;
goto cleanup;
diff --git a/src/util/virutil.c b/src/util/virutil.c
index 7a2fbb0..0e3fbd7 100644
--- a/src/util/virutil.c
+++ b/src/util/virutil.c
@@ -2173,3 +2173,26 @@ bool virIsSUID(void)
{
return getuid() != geteuid();
}
+
+
+static time_t selfLastModified;
+
+time_t virGetSelfLastModified(void)
+{
+ return selfLastModified;
+}
+
+
+void virUpdateSelfLastModified(const char *path)
+{
+ struct stat sb;
+
+ if (stat(path, &sb) < 0)
+ return;
+
+ if (sb.st_mtime > selfLastModified) {
+ VIR_DEBUG("Setting self last modified to %lld for '%s'",
+ (long long)sb.st_mtime, path);
+ selfLastModified = sb.st_mtime;
+ }
+}
diff --git a/src/util/virutil.h b/src/util/virutil.h
index 029265c..0bf7687 100644
--- a/src/util/virutil.h
+++ b/src/util/virutil.h
@@ -194,4 +194,8 @@ const char *virGetEnvBlockSUID(const char *name);
const char *virGetEnvAllowSUID(const char *name);
bool virIsSUID(void);
+
+time_t virGetSelfLastModified(void);
+void virUpdateSelfLastModified(const char *path);
+
#endif /* __VIR_UTIL_H__ */
--
1.8.5.3