summaryrefslogtreecommitdiffstats
path: root/debian/patches/0002-zonefile-Verify-mtime-against-full-precision-timesta.patch
blob: fa79f5d556c787bf0c460eff49175c259dbc8f84 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
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.