提交 9372343f 编写于 作者: D Daniel P. Berrange 提交者: Cole Robinson

xen: fix race in refresh of config cache

The xenXMConfigCacheRefresh method scans /etc/xen and loads
all config files it finds. It then scans its internal hash
table and purges any (previously) loaded config files whose
refresh timestamp does not match the timestamp recorded at
the start of xenXMConfigCacheRefresh(). There is unfortunately
a subtle flaw in this, because if loading the config files
takes longer than 1 second, some of the config files will
have a refresh timestamp that is 1 or more seconds different
(newer) than is checked for. So we immediately purge a bunch
of valid config files we just loaded.

To avoid this flaw, we must pass the timestamp we record at
the start of xenXMConfigCacheRefresh() into the
xenXMConfigCacheAddFile() method, instead of letting the
latter call time(NULL) again.
Signed-off-by: NDaniel P. Berrange <berrange@redhat.com>
(cherry picked from commit 427067f7)
上级 b84e9ef2
...@@ -217,11 +217,11 @@ xenInotifyRemoveDomainConfigInfo(virConnectPtr conn, const char *fname) ...@@ -217,11 +217,11 @@ xenInotifyRemoveDomainConfigInfo(virConnectPtr conn, const char *fname)
} }
static int static int
xenInotifyAddDomainConfigInfo(virConnectPtr conn, const char *fname) xenInotifyAddDomainConfigInfo(virConnectPtr conn, const char *fname, time_t now)
{ {
xenUnifiedPrivatePtr priv = conn->privateData; xenUnifiedPrivatePtr priv = conn->privateData;
return priv->useXenConfigCache ? return priv->useXenConfigCache ?
xenXMConfigCacheAddFile(conn, fname) : xenXMConfigCacheAddFile(conn, fname, now) :
xenInotifyXendDomainsDirAddEntry(conn, fname); xenInotifyXendDomainsDirAddEntry(conn, fname);
} }
...@@ -238,6 +238,7 @@ xenInotifyEvent(int watch ATTRIBUTE_UNUSED, ...@@ -238,6 +238,7 @@ xenInotifyEvent(int watch ATTRIBUTE_UNUSED,
char *tmp, *name; char *tmp, *name;
virConnectPtr conn = data; virConnectPtr conn = data;
xenUnifiedPrivatePtr priv = NULL; xenUnifiedPrivatePtr priv = NULL;
time_t now = time(NULL);
VIR_DEBUG("got inotify event"); VIR_DEBUG("got inotify event");
...@@ -300,7 +301,7 @@ xenInotifyEvent(int watch ATTRIBUTE_UNUSED, ...@@ -300,7 +301,7 @@ xenInotifyEvent(int watch ATTRIBUTE_UNUSED,
} }
} else if (e->mask & (IN_CREATE | IN_CLOSE_WRITE | IN_MOVED_TO)) { } else if (e->mask & (IN_CREATE | IN_CLOSE_WRITE | IN_MOVED_TO)) {
virObjectEventPtr event; virObjectEventPtr event;
if (xenInotifyAddDomainConfigInfo(conn, fname) < 0) { if (xenInotifyAddDomainConfigInfo(conn, fname, now) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, virReportError(VIR_ERR_INTERNAL_ERROR,
"%s", _("Error adding file to config cache")); "%s", _("Error adding file to config cache"));
goto cleanup; goto cleanup;
...@@ -344,6 +345,7 @@ xenInotifyOpen(virConnectPtr conn, ...@@ -344,6 +345,7 @@ xenInotifyOpen(virConnectPtr conn,
char *path; char *path;
xenUnifiedPrivatePtr priv = conn->privateData; xenUnifiedPrivatePtr priv = conn->privateData;
int direrr; int direrr;
time_t now = time(NULL);
virCheckFlags(VIR_CONNECT_RO, -1); virCheckFlags(VIR_CONNECT_RO, -1);
...@@ -374,7 +376,7 @@ xenInotifyOpen(virConnectPtr conn, ...@@ -374,7 +376,7 @@ xenInotifyOpen(virConnectPtr conn,
return -1; return -1;
} }
if (xenInotifyAddDomainConfigInfo(conn, path) < 0) { if (xenInotifyAddDomainConfigInfo(conn, path, now) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, virReportError(VIR_ERR_INTERNAL_ERROR,
"%s", _("Error adding file to config list")); "%s", _("Error adding file to config list"));
closedir(dh); closedir(dh);
......
...@@ -191,15 +191,14 @@ xenXMConfigCacheRemoveFile(virConnectPtr conn, const char *filename) ...@@ -191,15 +191,14 @@ xenXMConfigCacheRemoveFile(virConnectPtr conn, const char *filename)
* calling this function * calling this function
*/ */
int int
xenXMConfigCacheAddFile(virConnectPtr conn, const char *filename) xenXMConfigCacheAddFile(virConnectPtr conn, const char *filename, time_t now)
{ {
xenUnifiedPrivatePtr priv = conn->privateData; xenUnifiedPrivatePtr priv = conn->privateData;
xenXMConfCachePtr entry; xenXMConfCachePtr entry;
struct stat st; struct stat st;
int newborn = 0; int newborn = 0;
time_t now = time(NULL);
VIR_DEBUG("Adding file %s", filename); VIR_DEBUG("Adding file %s %lld", filename, (long long)now);
/* Get modified time */ /* Get modified time */
if ((stat(filename, &st) < 0)) { if ((stat(filename, &st) < 0)) {
...@@ -373,7 +372,7 @@ xenXMConfigCacheRefresh(virConnectPtr conn) ...@@ -373,7 +372,7 @@ xenXMConfigCacheRefresh(virConnectPtr conn)
/* If we already have a matching entry and it is not /* If we already have a matching entry and it is not
modified, then carry on to next one*/ modified, then carry on to next one*/
if (xenXMConfigCacheAddFile(conn, path) < 0) { if (xenXMConfigCacheAddFile(conn, path, now) < 0) {
/* Ignoring errors, since a lot of stuff goes wrong in /etc/xen */ /* Ignoring errors, since a lot of stuff goes wrong in /etc/xen */
} }
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
# include "domain_conf.h" # include "domain_conf.h"
int xenXMConfigCacheRefresh (virConnectPtr conn); int xenXMConfigCacheRefresh (virConnectPtr conn);
int xenXMConfigCacheAddFile(virConnectPtr conn, const char *filename); int xenXMConfigCacheAddFile(virConnectPtr conn, const char *filename, time_t now);
int xenXMConfigCacheRemoveFile(virConnectPtr conn, const char *filename); int xenXMConfigCacheRemoveFile(virConnectPtr conn, const char *filename);
int xenXMOpen(virConnectPtr conn, virConnectAuthPtr auth, unsigned int flags); int xenXMOpen(virConnectPtr conn, virConnectAuthPtr auth, unsigned int flags);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册