summaryrefslogtreecommitdiffstats
path: root/debian/patches/0002-zonefile-Verify-mtime-against-full-precision-timesta.patch
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches/0002-zonefile-Verify-mtime-against-full-precision-timesta.patch')
-rw-r--r--debian/patches/0002-zonefile-Verify-mtime-against-full-precision-timesta.patch129
1 files changed, 129 insertions, 0 deletions
diff --git a/debian/patches/0002-zonefile-Verify-mtime-against-full-precision-timesta.patch b/debian/patches/0002-zonefile-Verify-mtime-against-full-precision-timesta.patch
new file mode 100644
index 0000000..fa79f5d
--- /dev/null
+++ b/debian/patches/0002-zonefile-Verify-mtime-against-full-precision-timesta.patch
@@ -0,0 +1,129 @@
+From: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+Date: Fri, 22 Feb 2019 16:05:38 -0500
+Subject: 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>
+---
+ src/knot/events/handlers/load.c | 6 ++++--
+ src/knot/zone/zone.c | 2 +-
+ src/knot/zone/zone.h | 2 +-
+ src/knot/zone/zonedb-load.c | 6 ++++--
+ src/knot/zone/zonefile.c | 4 ++--
+ 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 7410d30..1f8f368 100644
+--- a/src/knot/events/handlers/load.c
++++ b/src/knot/events/handlers/load.c
+@@ -73,10 +73,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 efc0caa..0ec29f1 100644
+--- a/src/knot/zone/zone.c
++++ b/src/knot/zone/zone.c
+@@ -145,7 +145,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 360e222..09c92cc 100644
+--- a/src/knot/zone/zone.h
++++ b/src/knot/zone/zone.h
+@@ -50,7 +50,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 a6e9834..f23b4b1 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 37fc90b..0e02d21 100644
+--- a/src/knot/zone/zonefile.c
++++ b/src/knot/zone/zonefile.c
+@@ -248,7 +248,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;
+@@ -260,7 +260,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 90283ee..9d0542e 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.