pacemaker/SOURCES/001-crm_resource_wait.patch
2026-03-30 10:50:56 -04:00

132 lines
4.4 KiB
Diff

From 17a2d7acffc86e06b2fa8b49c96c33d72466e7f7 Mon Sep 17 00:00:00 2001
From: Reid Wahl <nrwahl@protonmail.com>
Date: Fri, 5 Sep 2025 20:35:31 -0700
Subject: [PATCH] Fix: tools: Handle large timeouts correctly in crm_resource
--wait
Previously, if the --timeout value parsed to a value greater than
(UINT_MAX - 999), the wait timeout would overflow. The effective timeout
would be either 0 seconds or 1 second. This is because 999 was added to
the guint value before passing it to pcmk__timeout_ms2s().
Now, we simply pass the timeout in milliseconds to
pcmk__timeout_ms2s(), without adding 999.
This implies a slight behavior change. Previously, timeouts were always
rounded up to the next greatest second. Now, they're rounded to the
nearest second. For example, previously:
* timeout values between 1ms and 500ms => wait timeout of 1 second
* timeout values between 501ms and 1500ms => wait timeout of 2 seconds
* timeout values between 1501ms and 2500ms => wait timeout of 3 seconds
* and so on
Now:
* timeout values between 1ms and 1499ms => wait timeout of 1 second
* timeout values between 1500ms and 2499ms => wait timeout of 2 seconds
* timeout values between 2500ms and 3499ms => wait timeout of 3 seconds
* and so on
The previous rounding behavior has existed since crm_resource --wait was
added by 424afcdf.
Update the help text to note the granularity and rounding behavior. The
exact behavior of the restart command is confusing, and its logic should
be cleaned up in the future.
Fixes RHEL-45869
Fixes RHEL-86148
Closes T841
Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
---
include/crm/common/internal.h | 1 +
lib/common/utils.c | 30 ++++++++++++++++++++++++++++++
tools/crm_resource.c | 4 +++-
tools/crm_resource_runtime.c | 2 +-
4 files changed, 35 insertions(+), 2 deletions(-)
diff --git a/include/crm/common/internal.h b/include/crm/common/internal.h
index 7d1e95f..ee26321 100644
--- a/include/crm/common/internal.h
+++ b/include/crm/common/internal.h
@@ -249,6 +249,7 @@ void pcmk__daemonize(const char *name, const char *pidfile);
void pcmk__panic(const char *origin);
pid_t pcmk__locate_sbd(void);
void pcmk__sleep_ms(unsigned int ms);
+guint pcmk__timeout_ms2s(guint timeout_ms);
extern int pcmk__score_red;
extern int pcmk__score_green;
diff --git a/lib/common/utils.c b/lib/common/utils.c
index 9e44c22..0a38811 100644
--- a/lib/common/utils.c
+++ b/lib/common/utils.c
@@ -413,6 +413,36 @@ pcmk__sleep_ms(unsigned int ms)
#endif
}
+/*!
+ * \internal
+ * \brief Convert milliseconds to seconds
+ *
+ * \param[in] timeout_ms The interval, in ms
+ *
+ * \return If \p timeout_ms is 0, return 0. Otherwise, return the number of
+ * seconds, rounded to the nearest integer, with a minimum of 1.
+ */
+guint
+pcmk__timeout_ms2s(guint timeout_ms)
+{
+ guint quot, rem;
+
+ if (timeout_ms == 0) {
+ return 0;
+ } else if (timeout_ms < 1000) {
+ return 1;
+ }
+
+ quot = timeout_ms / 1000;
+ rem = timeout_ms % 1000;
+
+ if (rem >= 500) {
+ quot += 1;
+ }
+
+ return quot;
+}
+
// Deprecated functions kept only for backward API compatibility
// LCOV_EXCL_START
diff --git a/tools/crm_resource.c b/tools/crm_resource.c
index 898c21e..ac50c5e 100644
--- a/tools/crm_resource.c
+++ b/tools/crm_resource.c
@@ -766,7 +766,9 @@ static GOptionEntry addl_entries[] = {
"ID" },
{ "timeout", 'T', G_OPTION_FLAG_NONE, G_OPTION_ARG_CALLBACK, timeout_cb,
"(Advanced) Abort if command does not finish in this time (with\n"
- INDENT "--restart, --wait, --force-*)",
+ INDENT "--restart, --wait, --force-*). The --restart command uses a\n"
+ INDENT "two-second granularity and the --wait command uses a one-second\n"
+ INDENT "granularity, with rounding.",
"N" },
{ "all", 0, G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &options.all,
"List all options, including advanced and deprecated (with\n"
diff --git a/tools/crm_resource_runtime.c b/tools/crm_resource_runtime.c
index 7350f07..286c10c 100644
--- a/tools/crm_resource_runtime.c
+++ b/tools/crm_resource_runtime.c
@@ -1977,7 +1977,7 @@ wait_till_stable(pcmk__output_t *out, guint timeout_ms, cib_t * cib)
if (timeout_ms == 0) {
expire_time += WAIT_DEFAULT_TIMEOUT_S;
} else {
- expire_time += (timeout_ms + 999) / 1000;
+ expire_time += pcmk__timeout_ms2s(timeout_ms);
}
scheduler = pe_new_working_set();
--
2.47.1