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)