[PATCH] uuidd: add cont_clock persistence

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



cont_clock requires a correct time setup and therefore it
must be possible to detect a step back between uuidd starts.

Reserving the next 10 seconds in clock-cont.txt is sufficient
and should not have a noticeable performance impact.
It will also provide the possibility to start with the clock_reg
from the previous session when the system was rebooted.

Whith that, the early cont_clock initialization in uuidd
should be removed because writing the cont_clock persitence
when -C was not set is useless and might be confusing.
---
 libuuid/src/gen_uuid.c | 78 ++++++++++++++++++++++++++++++++++++------
 libuuid/src/uuidP.h    |  1 +
 misc-utils/uuidd.c     |  9 -----
 3 files changed, 69 insertions(+), 19 deletions(-)

diff --git a/libuuid/src/gen_uuid.c b/libuuid/src/gen_uuid.c
index 826cd2245..94b99f1bd 100644
--- a/libuuid/src/gen_uuid.c
+++ b/libuuid/src/gen_uuid.c
@@ -355,44 +355,102 @@ static uint64_t get_clock_counter(void)
 /*
  * Get continuous clock value.
  *
- * Return -1 if there is no further clock counter available,
+ * Return -1 if there is no valid clock counter available,
  * otherwise return 0.
  *
  * This implementation doesn't deliver clock counters based on
  * the current time because last_clock_reg is only incremented
  * by the number of requested UUIDs.
  * max_clock_offset is used to limit the offset of last_clock_reg.
+ * used/reserved UUIDs are written to LIBUUID_CLOCK_CONT_FILE.
  */
 static int get_clock_cont(uint32_t *clock_high,
 			  uint32_t *clock_low,
 			  int num,
 			  uint32_t max_clock_offset)
 {
-	/* 100ns based time offset according to RFC 4122. 4.1.4. */
+	/* all 64bit clock_reg values in this function represent '100ns ticks'
+         * due to the combination of tv_usec + MAX_ADJUSTMENT */
+
+	enum { fd_init = -2, fd_error = -1 };
+	/* time offset according to RFC 4122. 4.1.4. */
 	const uint64_t reg_offset = (((uint64_t) 0x01B21DD2) << 32) + 0x13814000;
 	static uint64_t last_clock_reg = 0;
-	uint64_t clock_reg;
+	static uint64_t saved_clock_reg = 0;
+	static int state_fd = fd_init;
+	static FILE *state_f = NULL;
+	uint64_t clock_reg, next_clock_reg;
 
-	if (last_clock_reg == 0)
-		last_clock_reg = get_clock_counter();
+	if (state_fd == fd_error)
+		return -1;
 
 	clock_reg = get_clock_counter();
+
+	if (state_fd == fd_init) {
+		mode_t save_umask;
+		struct stat st;
+
+		save_umask = umask(0);
+		state_fd = open(LIBUUID_CLOCK_CONT_FILE, O_RDWR|O_CREAT|O_CLOEXEC, 0660);
+		(void) umask(save_umask);
+		if (state_fd == fd_error)
+			return -1;
+
+		state_f = fdopen(state_fd, "r+" UL_CLOEXECSTR);
+		if (!state_f)
+			goto error;
+
+		if (fstat(state_fd, &st))
+			goto error;
+
+		if (st.st_size) {
+			rewind(state_f);
+			if (fscanf(state_f, "cont: %lu\n", &last_clock_reg) != 1)
+				goto error;
+		} else
+			last_clock_reg = clock_reg;
+
+		saved_clock_reg = last_clock_reg;
+	}
+
 	if (max_clock_offset) {
-		uint64_t clock_offset = max_clock_offset * 10000000ULL;
-		if (last_clock_reg < (clock_reg - clock_offset))
-			last_clock_reg = clock_reg - clock_offset;
+		uint64_t co = 10000000ULL * (uint64_t)max_clock_offset;	// clock_offset in [100ns]
+
+		if ((last_clock_reg + co) < clock_reg)
+			last_clock_reg = clock_reg - co;
 	}
 
 	clock_reg += MAX_ADJUSTMENT;
 
-	if ((last_clock_reg + num) >= clock_reg)
+	next_clock_reg = last_clock_reg + (uint64_t)num;
+	if (next_clock_reg >= clock_reg)
 		return -1;
 
+	if (next_clock_reg >= saved_clock_reg) {
+		uint64_t cl = next_clock_reg + 100000000ULL;	// 10s interval in [100ns]
+		int l;
+
+		rewind(state_f);
+		l = fprintf(state_f, "cont: %020lu                   \n", cl);
+		if (l < 30 || fflush(state_f))
+			goto error;
+		saved_clock_reg = cl;
+	}
+
 	*clock_high = (last_clock_reg + reg_offset) >> 32;
 	*clock_low = last_clock_reg + reg_offset;
-	last_clock_reg += num;
+	last_clock_reg = next_clock_reg;
 
 	return 0;
+
+error:
+	if (state_fd >= 0)
+		close(state_fd);
+	if (state_f)
+		fclose(state_f);
+	state_fd = fd_error;
+	state_f = NULL;
+	return -1;
 }
 
 #if defined(HAVE_UUIDD) && defined(HAVE_SYS_UN_H)
diff --git a/libuuid/src/uuidP.h b/libuuid/src/uuidP.h
index 200702c1e..fef7e6cb5 100644
--- a/libuuid/src/uuidP.h
+++ b/libuuid/src/uuidP.h
@@ -40,6 +40,7 @@
 #include "uuid.h"
 
 #define LIBUUID_CLOCK_FILE	"/var/lib/libuuid/clock.txt"
+#define LIBUUID_CLOCK_CONT_FILE	"/var/lib/libuuid/clock-cont.txt"
 
 /*
  * Offset between 15-Oct-1582 and 1-Jan-70
diff --git a/misc-utils/uuidd.c b/misc-utils/uuidd.c
index fd121c5bc..42a252dd0 100644
--- a/misc-utils/uuidd.c
+++ b/misc-utils/uuidd.c
@@ -442,15 +442,6 @@ static void server_loop(const char *socket_path, const char *pidfile_path,
 	pfd[POLLFD_SOCKET].fd = s;
 	pfd[POLLFD_SIGNAL].events = pfd[POLLFD_SOCKET].events = POLLIN | POLLERR | POLLHUP;
 
-	num = 1;
-	if (uuidd_cxt->cont_clock_offset) {
-		/* trigger initialization */
-		(void) __uuid_generate_time_cont(uu, &num, uuidd_cxt->cont_clock_offset);
-		if (uuidd_cxt->debug)
-			fprintf(stderr, _("max_clock_offset = %u sec\n"),
-				uuidd_cxt->cont_clock_offset);
-	}
-
 	while (1) {
 		ret = poll(pfd, ARRAY_SIZE(pfd),
 				uuidd_cxt->timeout ?
-- 
2.39.3 (Apple Git-145)





[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux