summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Kahn Gillmor <dkg@fifthhorseman.net>2019-02-22 22:05:38 +0100
committerDaniel Kahn Gillmor <dkg@fifthhorseman.net>2019-02-22 22:47:47 +0100
commitb03c97c78a8b516d107d3d1b431e06d2265e82b1 (patch)
tree95a420e80d1c676e610e9af3f817ef57dc3a679f
parenttests: mute warning on OpenBSD (diff)
downloadknot-b03c97c78a8b516d107d3d1b431e06d2265e82b1.tar.xz
knot-b03c97c78a8b516d107d3d1b431e06d2265e82b1.zip
zonefile: Verify mtime against full-precision timestamp
We've just used 1-second granularity mtime to check if a file has changed. But if two updates happen within a calendar second, and knotd notices the first one and reloads the file, it might never notice the second change and continue serving the old file. We can see this happening in intermittent test suite failures in the debian continuous integration servers: https://ci.debian.net/packages/k/knot/unstable/amd64 Using nanosecond-granularity timestamps should make these problems go away. Signed-off-by: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
-rw-r--r--src/knot/events/handlers/load.c6
-rw-r--r--src/knot/zone/zone.c2
-rw-r--r--src/knot/zone/zone.h2
-rw-r--r--src/knot/zone/zonedb-load.c6
-rw-r--r--src/knot/zone/zonefile.c4
-rw-r--r--src/knot/zone/zonefile.h2
6 files changed, 13 insertions, 9 deletions
diff --git a/src/knot/events/handlers/load.c b/src/knot/events/handlers/load.c
index a32262078..f845398ad 100644
--- a/src/knot/events/handlers/load.c
+++ b/src/knot/events/handlers/load.c
@@ -74,10 +74,12 @@ int event_load(conf_t *conf, zone_t *zone)
// If configured, attempt to load zonefile.
if (zf_from != ZONEFILE_LOAD_NONE) {
- time_t mtime;
+ struct timespec mtime;
char *filename = conf_zonefile(conf, zone->name);
ret = zonefile_exists(filename, &mtime);
- bool zonefile_unchanged = (zone->zonefile.exists && zone->zonefile.mtime == mtime);
+ bool zonefile_unchanged = (zone->zonefile.exists &&
+ zone->zonefile.mtime.tv_sec == mtime.tv_sec &&
+ zone->zonefile.mtime.tv_nsec == mtime.tv_nsec);
free(filename);
if (ret == KNOT_EOK) {
ret = zone_load_contents(conf, zone->name, &zf_conts);
diff --git a/src/knot/zone/zone.c b/src/knot/zone/zone.c
index 34e29d2f5..597027cab 100644
--- a/src/knot/zone/zone.c
+++ b/src/knot/zone/zone.c
@@ -127,7 +127,7 @@ static int flush_journal(conf_t *conf, zone_t *zone, bool allow_empty_zone)
/* Update zone file attributes. */
zone->zonefile.exists = true;
- zone->zonefile.mtime = st.st_mtime;
+ zone->zonefile.mtime = st.st_mtim;
zone->zonefile.serial = serial_to;
zone->zonefile.resigned = false;
diff --git a/src/knot/zone/zone.h b/src/knot/zone/zone.h
index dd9a8fe21..f6b82ed3c 100644
--- a/src/knot/zone/zone.h
+++ b/src/knot/zone/zone.h
@@ -53,7 +53,7 @@ typedef struct zone
/*! \brief Zonefile parameters. */
struct {
- time_t mtime;
+ struct timespec mtime;
uint32_t serial;
bool exists;
bool resigned;
diff --git a/src/knot/zone/zonedb-load.c b/src/knot/zone/zonedb-load.c
index 9df71aa49..58161628f 100644
--- a/src/knot/zone/zonedb-load.c
+++ b/src/knot/zone/zonedb-load.c
@@ -35,12 +35,14 @@ static bool zone_file_updated(conf_t *conf, const zone_t *old_zone,
assert(zone_name);
char *zonefile = conf_zonefile(conf, zone_name);
- time_t mtime;
+ struct timespec mtime;
int ret = zonefile_exists(zonefile, &mtime);
free(zonefile);
return (ret == KNOT_EOK && old_zone != NULL &&
- !(old_zone->zonefile.exists && old_zone->zonefile.mtime == mtime));
+ !(old_zone->zonefile.exists &&
+ old_zone->zonefile.mtime.tv_sec == mtime.tv_sec &&
+ old_zone->zonefile.mtime.tv_nsec == mtime.tv_nsec));
}
static zone_t *create_zone_from(const knot_dname_t *name, server_t *server)
diff --git a/src/knot/zone/zonefile.c b/src/knot/zone/zonefile.c
index 9811abc59..2cbc4faf3 100644
--- a/src/knot/zone/zonefile.c
+++ b/src/knot/zone/zonefile.c
@@ -249,7 +249,7 @@ fail:
return NULL;
}
-int zonefile_exists(const char *path, time_t *mtime)
+int zonefile_exists(const char *path, struct timespec *mtime)
{
if (path == NULL) {
return KNOT_EINVAL;
@@ -261,7 +261,7 @@ int zonefile_exists(const char *path, time_t *mtime)
}
if (mtime != NULL) {
- *mtime = zonefile_st.st_mtime;
+ *mtime = zonefile_st.st_mtim;
}
return KNOT_EOK;
diff --git a/src/knot/zone/zonefile.h b/src/knot/zone/zonefile.h
index bbab1a9f2..df7c161fe 100644
--- a/src/knot/zone/zonefile.h
+++ b/src/knot/zone/zonefile.h
@@ -79,7 +79,7 @@ zone_contents_t *zonefile_load(zloader_t *loader);
*
* \return KNOT_E*
*/
-int zonefile_exists(const char *path, time_t *mtime);
+int zonefile_exists(const char *path, struct timespec *mtime);
/*!
* \brief Write zone contents to zone file.