diff options
author | Daniel Kahn Gillmor <dkg@fifthhorseman.net> | 2019-02-22 22:05:38 +0100 |
---|---|---|
committer | Daniel Kahn Gillmor <dkg@fifthhorseman.net> | 2019-02-22 22:47:47 +0100 |
commit | b03c97c78a8b516d107d3d1b431e06d2265e82b1 (patch) | |
tree | 95a420e80d1c676e610e9af3f817ef57dc3a679f | |
parent | tests: mute warning on OpenBSD (diff) | |
download | knot-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.c | 6 | ||||
-rw-r--r-- | src/knot/zone/zone.c | 2 | ||||
-rw-r--r-- | src/knot/zone/zone.h | 2 | ||||
-rw-r--r-- | src/knot/zone/zonedb-load.c | 6 | ||||
-rw-r--r-- | src/knot/zone/zonefile.c | 4 | ||||
-rw-r--r-- | src/knot/zone/zonefile.h | 2 |
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. |