From 452f70cce1316ed512fedd8ed4b0742faa769bbf Mon Sep 17 00:00:00 2001 From: Davide Cavalca Date: Dec 08 2022 00:09:43 +0000 Subject: Merge branch 'c8s' into c8s-sig-hyperscale --- diff --git a/SOURCES/0085-libuuid-Implement-continuous-clock-handling-for-time.patch b/SOURCES/0085-libuuid-Implement-continuous-clock-handling-for-time.patch new file mode 100644 index 0000000..ef9798b --- /dev/null +++ b/SOURCES/0085-libuuid-Implement-continuous-clock-handling-for-time.patch @@ -0,0 +1,375 @@ +From ce49a152fd8a830b1c9c0a8b745ea71feff71697 Mon Sep 17 00:00:00 2001 +From: Michael Trapp +Date: Mon, 20 Jun 2022 17:10:36 +0200 +Subject: libuuid: Implement continuous clock handling for time based UUIDs + +In a uuidd setup, the daemon is a singleton and can maintain it's own +resources for time based UUID generation. This requires a dedicated +'clock sequence range' but does not need any further lock/update of +the LIBUUID_CLOCK_FILE from uuidd. The range of available clock values +is extended by a continuous handling of the clock updates - instead of +updating the value to the current timestamp, it is incremented by +the number of requested UUIDs. + +[kzak@redhat.com: - backport from upstream v2.39 to to RHEL-8] + +Upstream: http://github.com/util-linux/util-linux/commit/3cfba7d39b66eff4307218fefd8bb34bb1621f83 +Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=2141969 +Signed-off-by: Karel Zak +--- + libuuid/src/gen_uuid.c | 91 ++++++++++++++++++++++++++++++++++++++--- + libuuid/src/libuuid.sym | 1 + + libuuid/src/uuidd.h | 1 + + misc-utils/uuidd.8.in | 12 ++++++ + misc-utils/uuidd.c | 86 ++++++++++++++++++++++++++++++++++++-- + 5 files changed, 182 insertions(+), 9 deletions(-) + +diff --git a/libuuid/src/gen_uuid.c b/libuuid/src/gen_uuid.c +index 27c135db5..f557053f7 100644 +--- a/libuuid/src/gen_uuid.c ++++ b/libuuid/src/gen_uuid.c +@@ -209,6 +209,8 @@ static int get_node_id(unsigned char *node_id) + + /* Assume that the gettimeofday() has microsecond granularity */ + #define MAX_ADJUSTMENT 10 ++/* Reserve a clock_seq value for the 'continuous clock' implementation */ ++#define CLOCK_SEQ_CONT 0 + + /* + * Get clock from global sequence clock counter. +@@ -275,8 +277,10 @@ static int get_clock(uint32_t *clock_high, uint32_t *clock_low, + } + + if ((last.tv_sec == 0) && (last.tv_usec == 0)) { +- random_get_bytes(&clock_seq, sizeof(clock_seq)); +- clock_seq &= 0x3FFF; ++ do { ++ random_get_bytes(&clock_seq, sizeof(clock_seq)); ++ clock_seq &= 0x3FFF; ++ } while (clock_seq == CLOCK_SEQ_CONT); + gettimeofday(&last, NULL); + last.tv_sec--; + } +@@ -286,7 +290,9 @@ try_again: + if ((tv.tv_sec < last.tv_sec) || + ((tv.tv_sec == last.tv_sec) && + (tv.tv_usec < last.tv_usec))) { +- clock_seq = (clock_seq+1) & 0x3FFF; ++ do { ++ clock_seq = (clock_seq+1) & 0x3FFF; ++ } while (clock_seq == CLOCK_SEQ_CONT); + adjustment = 0; + last = tv; + } else if ((tv.tv_sec == last.tv_sec) && +@@ -331,6 +337,64 @@ try_again: + return ret; + } + ++/* ++ * Get current time in 100ns ticks. ++ */ ++static uint64_t get_clock_counter(void) ++{ ++ struct timeval tv; ++ uint64_t clock_reg; ++ ++ gettimeofday(&tv, NULL); ++ clock_reg = tv.tv_usec*10; ++ clock_reg += ((uint64_t) tv.tv_sec) * 10000000ULL; ++ ++ return clock_reg; ++} ++ ++/* ++ * Get continuous clock value. ++ * ++ * Return -1 if there is no further 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. ++ */ ++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. */ ++ const uint64_t reg_offset = (((uint64_t) 0x01B21DD2) << 32) + 0x13814000; ++ static uint64_t last_clock_reg = 0; ++ uint64_t clock_reg; ++ ++ if (last_clock_reg == 0) ++ last_clock_reg = get_clock_counter(); ++ ++ clock_reg = get_clock_counter(); ++ 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; ++ } ++ ++ clock_reg += MAX_ADJUSTMENT; ++ ++ if ((last_clock_reg + num) >= clock_reg) ++ return -1; ++ ++ *clock_high = (last_clock_reg + reg_offset) >> 32; ++ *clock_low = last_clock_reg + reg_offset; ++ last_clock_reg += num; ++ ++ return 0; ++} ++ + #if defined(HAVE_UUIDD) && defined(HAVE_SYS_UN_H) + + /* +@@ -403,7 +467,7 @@ static int get_uuid_via_daemon(int op __attribute__((__unused__)), + } + #endif + +-int __uuid_generate_time(uuid_t out, int *num) ++static int __uuid_generate_time_internal(uuid_t out, int *num, uint32_t cont_offset) + { + static unsigned char node_id[6]; + static int has_init = 0; +@@ -423,7 +487,14 @@ int __uuid_generate_time(uuid_t out, int *num) + } + has_init = 1; + } +- ret = get_clock(&clock_mid, &uu.time_low, &uu.clock_seq, num); ++ if (cont_offset) { ++ ret = get_clock_cont(&clock_mid, &uu.time_low, *num, cont_offset); ++ uu.clock_seq = CLOCK_SEQ_CONT; ++ if (ret != 0) /* fallback to previous implpementation */ ++ ret = get_clock(&clock_mid, &uu.time_low, &uu.clock_seq, num); ++ } else { ++ ret = get_clock(&clock_mid, &uu.time_low, &uu.clock_seq, num); ++ } + uu.clock_seq |= 0x8000; + uu.time_mid = (uint16_t) clock_mid; + uu.time_hi_and_version = ((clock_mid >> 16) & 0x0FFF) | 0x1000; +@@ -432,6 +503,16 @@ int __uuid_generate_time(uuid_t out, int *num) + return ret; + } + ++int __uuid_generate_time(uuid_t out, int *num) ++{ ++ return __uuid_generate_time_internal(out, num, 0); ++} ++ ++int __uuid_generate_time_cont(uuid_t out, int *num, uint32_t cont_offset) ++{ ++ return __uuid_generate_time_internal(out, num, cont_offset); ++} ++ + /* + * Generate time-based UUID and store it to @out + * +diff --git a/libuuid/src/libuuid.sym b/libuuid/src/libuuid.sym +index 9e3e80035..0a072b703 100644 +--- a/libuuid/src/libuuid.sym ++++ b/libuuid/src/libuuid.sym +@@ -51,6 +51,7 @@ global: + UUIDD_PRIVATE { + global: + __uuid_generate_time; ++ __uuid_generate_time_cont; + __uuid_generate_random; + local: + *; +diff --git a/libuuid/src/uuidd.h b/libuuid/src/uuidd.h +index e55c86f2f..14a01ade2 100644 +--- a/libuuid/src/uuidd.h ++++ b/libuuid/src/uuidd.h +@@ -50,5 +50,6 @@ + + extern int __uuid_generate_time(uuid_t out, int *num); + extern void __uuid_generate_random(uuid_t out, int *num); ++extern int __uuid_generate_time_cont(uuid_t out, int *num, uint32_t cont); + + #endif /* _UUID_UUID_H */ +diff --git a/misc-utils/uuidd.8.in b/misc-utils/uuidd.8.in +index 0a5cf471b..28bcb48b5 100644 +--- a/misc-utils/uuidd.8.in ++++ b/misc-utils/uuidd.8.in +@@ -16,6 +16,18 @@ universally unique identifiers (UUIDs), especially time-based UUIDs, + in a secure and guaranteed-unique fashion, even in the face of large + numbers of threads running on different CPUs trying to grab UUIDs. + .SH OPTIONS ++ ++.TP ++.BR \-C , " \-\-cont\-clock " [\fInumber\fR] ++Activate continuous clock handling for time based UUIDs. uuidd could use all ++possible clock values, beginning with the daemon's start time. The optional ++argument can be used to set a value for the max_clock_offset. This gurantees, ++that a clock value of a UUID will always be within the range of the ++max_clock_offset. '-C' or '--cont-clock' enables the feature with a default ++max_clock_offset of 2 hours. '-C[hd]' or '--cont-clock=[hd]' enables ++the feature with a max_clock_offset of NUM seconds. In case of an appended h or ++d, the NUM value is read in hours or days. The minimum value is 60 seconds, the ++maximum value is 365 days. + .TP + .BR \-d , " \-\-debug " + Run uuidd in debugging mode. This prevents uuidd from running as a daemon. +diff --git a/misc-utils/uuidd.c b/misc-utils/uuidd.c +index 8b83d91c0..e3c0abad7 100644 +--- a/misc-utils/uuidd.c ++++ b/misc-utils/uuidd.c +@@ -49,6 +49,8 @@ struct uuidd_cxt_t { + const char *cleanup_pidfile; + const char *cleanup_socket; + uint32_t timeout; ++ uint32_t cont_clock_offset; ++ + unsigned int debug: 1, + quiet: 1, + no_fork: 1, +@@ -73,6 +75,8 @@ static void __attribute__((__noreturn__)) usage(void) + fputs(_(" -P, --no-pid do not create pid file\n"), out); + fputs(_(" -F, --no-fork do not daemonize using double-fork\n"), out); + fputs(_(" -S, --socket-activation do not create listening socket\n"), out); ++ fputs(_(" -C, --cont-clock[=[hd]]\n"), out); ++ fputs(_(" activate continuous clock handling\n"), out); + fputs(_(" -d, --debug run in debugging mode\n"), out); + fputs(_(" -q, --quiet turn on quiet mode\n"), out); + fputs(USAGE_SEPARATOR, out); +@@ -401,6 +405,15 @@ 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 ? +@@ -458,7 +471,7 @@ static void server_loop(const char *socket_path, const char *pidfile_path, + break; + case UUIDD_OP_TIME_UUID: + num = 1; +- __uuid_generate_time(uu, &num); ++ __uuid_generate_time_cont(uu, &num, uuidd_cxt->cont_clock_offset); + if (uuidd_cxt->debug) { + uuid_unparse(uu, str); + fprintf(stderr, _("Generated time UUID: %s\n"), str); +@@ -477,7 +490,7 @@ static void server_loop(const char *socket_path, const char *pidfile_path, + reply_len = sizeof(uu); + break; + case UUIDD_OP_BULK_TIME_UUID: +- __uuid_generate_time(uu, &num); ++ __uuid_generate_time_cont(uu, &num, uuidd_cxt->cont_clock_offset); + if (uuidd_cxt->debug) { + uuid_unparse(uu, str); + fprintf(stderr, P_("Generated time UUID %s " +@@ -530,6 +543,64 @@ static void __attribute__ ((__noreturn__)) unexpected_size(int size) + errx(EXIT_FAILURE, _("Unexpected reply length from server %d"), size); + } + ++/* Backport from v2.39 lib/strutils.c */ ++static int ul_strtos64(const char *str, int64_t *num, int base) ++{ ++ char *end = NULL; ++ ++ if (str == NULL || *str == '\0') ++ return -(errno = EINVAL); ++ ++ errno = 0; ++ *num = (int64_t) strtoimax(str, &end, base); ++ ++ if (errno != 0) ++ return -errno; ++ if (str == end || (end && *end)) ++ return -(errno = EINVAL); ++ return 0; ++} ++ ++/* Backport from v2.39 lib/strutils.c */ ++static int64_t str2num_or_err(const char *str, int base, const char *errmesg, ++ int64_t low, int64_t up) ++{ ++ int64_t num = 0; ++ int rc; ++ ++ rc = ul_strtos64(str, &num, base); ++ if (rc == 0 && ((low && num < low) || (up && num > up))) ++ rc = -(errno = ERANGE); ++ ++ if (rc) { ++ if (errno == ERANGE) ++ err(EXIT_FAILURE, "%s: '%s'", errmesg, str); ++ errx(EXIT_FAILURE, "%s: '%s'", errmesg, str); ++ } ++ return num; ++} ++ ++static uint32_t parse_cont_clock(char *arg) ++{ ++ uint32_t min_val = 60, ++ max_val = (3600 * 24 * 365), ++ factor = 1; ++ char *p = &arg[strlen(arg)-1]; ++ ++ if ('h' == *p) { ++ *p = '\0'; ++ factor = 3600; ++ min_val = 1; ++ } ++ if ('d' == *p) { ++ *p = '\0'; ++ factor = 24 * 3600; ++ min_val = 1; ++ } ++ return factor * str2num_or_err(optarg, 10, _("failed to parse --cont-clock/-C"), ++ min_val, max_val / factor); ++} ++ + int main(int argc, char **argv) + { + const char *socket_path = UUIDD_SOCKET_PATH; +@@ -543,7 +614,7 @@ int main(int argc, char **argv) + int no_pid = 0; + int s_flag = 0; + +- struct uuidd_cxt_t uuidd_cxt = { .timeout = 0 }; ++ struct uuidd_cxt_t uuidd_cxt = { .timeout = 0, .cont_clock_offset = 0 }; + + static const struct option longopts[] = { + {"pid", required_argument, NULL, 'p'}, +@@ -556,6 +627,7 @@ int main(int argc, char **argv) + {"no-pid", no_argument, NULL, 'P'}, + {"no-fork", no_argument, NULL, 'F'}, + {"socket-activation", no_argument, NULL, 'S'}, ++ {"cont-clock", optional_argument, NULL, 'C'}, + {"debug", no_argument, NULL, 'd'}, + {"quiet", no_argument, NULL, 'q'}, + {"version", no_argument, NULL, 'V'}, +@@ -576,10 +648,16 @@ int main(int argc, char **argv) + atexit(close_stdout); + + while ((c = +- getopt_long(argc, argv, "p:s:T:krtn:PFSdqVh", longopts, ++ getopt_long(argc, argv, "p:s:T:krtn:PFSC::dqVh", longopts, + NULL)) != -1) { + err_exclusive_options(c, longopts, excl, excl_st); + switch (c) { ++ case 'C': ++ if (optarg != NULL) ++ uuidd_cxt.cont_clock_offset = parse_cont_clock(optarg); ++ else ++ uuidd_cxt.cont_clock_offset = 7200; /* default 2h */ ++ break; + case 'd': + uuidd_cxt.debug = 1; + break; +-- +2.38.1 + diff --git a/SOURCES/0086-libuuid-check-clock-value-from-LIBUUID_CLOCK_FILE.patch b/SOURCES/0086-libuuid-check-clock-value-from-LIBUUID_CLOCK_FILE.patch new file mode 100644 index 0000000..401c52a --- /dev/null +++ b/SOURCES/0086-libuuid-check-clock-value-from-LIBUUID_CLOCK_FILE.patch @@ -0,0 +1,35 @@ +From fffaa2c0856de8c42b17c52a641cbc5d00ec012b Mon Sep 17 00:00:00 2001 +From: Michael Trapp +Date: Tue, 2 Aug 2022 14:16:43 +0200 +Subject: libuuid: check clock value from LIBUUID_CLOCK_FILE + +The clock value from the LIBUUID_CLOCK_FILE must be checked in +case of an update of libuuid. If clock==CLOCK_SEQ_CONT it must +be set to a new value. + +Signed-off-by: Karel Zak +Upstream: http://github.com/util-linux/util-linux/commit/5d1424d85ac9e2a1369ee920038825c154ee5443 +Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=2141969 +--- + libuuid/src/gen_uuid.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/libuuid/src/gen_uuid.c b/libuuid/src/gen_uuid.c +index f557053f7..8dc38559f 100644 +--- a/libuuid/src/gen_uuid.c ++++ b/libuuid/src/gen_uuid.c +@@ -274,6 +274,11 @@ static int get_clock(uint32_t *clock_high, uint32_t *clock_low, + last.tv_usec = tv2; + adjustment = a; + } ++ // reset in case of reserved CLOCK_SEQ_CONT ++ if (clock_seq == CLOCK_SEQ_CONT) { ++ last.tv_sec = 0; ++ last.tv_usec = 0; ++ } + } + + if ((last.tv_sec == 0) && (last.tv_usec == 0)) { +-- +2.38.1 + diff --git a/SPECS/util-linux.spec b/SPECS/util-linux.spec index 8a4c731..a4c0fa1 100644 --- a/SPECS/util-linux.spec +++ b/SPECS/util-linux.spec @@ -2,7 +2,7 @@ Summary: A collection of basic system utilities Name: util-linux Version: 2.32.1 -Release: 38.1%{?dist} +Release: 39.1%{?dist} License: GPLv2 and GPLv2+ and LGPLv2+ and BSD with advertising and Public Domain Group: System Environment/Base URL: http://en.wikipedia.org/wiki/Util-linux @@ -261,6 +261,12 @@ Patch82: 0082-lslogins-improve-prefixes-interpretation.patch Patch83: 0083-tests-update-atari-blkid-tests.patch Patch84: 0084-tests-update-atari-partx-tests.patch +### RHEL-8.7.Z +### +# 2141969 - Add --cont-clock feature for libuuid and uuidd +Patch85: 0085-libuuid-Implement-continuous-clock-handling-for-time.patch +Patch86: 0086-libuuid-check-clock-value-from-LIBUUID_CLOCK_FILE.patch + ### Hyperscale (1000-9999) ### Patch1000: 1000-setpriv-add-reset-env.patch @@ -268,7 +274,6 @@ Patch1001: 1001-losetup-avoid-infinite-busy-loop.patch Patch1002: 1002-losetup-increase-limit-of-setup-attempts.patch Patch1003: 1003-lib-loopdev-perform-retry-on-EAGAIN.patch - %description The util-linux package contains a large variety of low-level system utilities that are necessary for a Linux system to function. Among @@ -1122,6 +1127,12 @@ fi %{_libdir}/python*/site-packages/libmount/ %changelog +* Wed Dec 07 2022 Davide Cavalca 2.32.1-39.1 +- Merge upsteam changes in Hyperscale + +* Wed Nov 16 2022 Karel Zak 2.32.1-39 +- fix #2141969 - Add --cont-clock feature for libuuid and uuidd + * Wed Nov 02 2022 Anita Zhang 2.32.1-38.1 - Merge C8s upstream changes - Fix 1000-setpriv-add-reset-env.patch merge conflicts