From 4193fb1d8e5023289e7a600a8dabc864b99f24a2 Mon Sep 17 00:00:00 2001
From: Ken Gaillot <kgaillot@redhat.com>
Date: Tue, 10 Dec 2024 14:56:20 -0600
Subject: [PATCH] Low: controller: round timeout when checking remaining remote
 command time

Use pcmk__timeout_ms2s() to ensure that remote command timeout values
are properly rounded.

Also, refactor to drop remaining_timeout from remote_ra_cmd_t. The value
was only ever used locally when calculated and doesn't need to be
remembered.
---
 daemons/controld/controld_remote_ra.c | 33 +++++++++++++++++----------
 1 file changed, 21 insertions(+), 12 deletions(-)

diff --git a/daemons/controld/controld_remote_ra.c b/daemons/controld/controld_remote_ra.c
index 060a231d74..df4e0bd6fc 100644
--- a/daemons/controld/controld_remote_ra.c
+++ b/daemons/controld/controld_remote_ra.c
@@ -55,7 +55,6 @@ typedef struct remote_ra_cmd_s {
     int delay_id;
     /*! timeout in ms for cmd */
     int timeout;
-    int remaining_timeout;
     /*! recurring interval in ms */
     guint interval_ms;
     /*! interval timer id */
@@ -512,10 +511,18 @@ report_remote_ra_result(remote_ra_cmd_t * cmd)
     lrmd__reset_result(&op);
 }
 
-static void
-update_remaining_timeout(remote_ra_cmd_t * cmd)
+/*!
+ * \internal
+ * \brief Return a remote command's remaining timeout in seconds
+ *
+ * \param[in] cmd  Remote command to check
+ *
+ * \return Command's remaining timeout in seconds
+ */
+static int
+remaining_timeout_sec(const remote_ra_cmd_t *cmd)
 {
-    cmd->remaining_timeout = ((cmd->timeout / 1000) - (time(NULL) - cmd->start_time)) * 1000;
+    return pcmk__timeout_ms2s(cmd->timeout) - (time(NULL) - cmd->start_time);
 }
 
 static gboolean
@@ -525,6 +532,7 @@ retry_start_cmd_cb(gpointer data)
     remote_ra_data_t *ra_data = lrm_state->remote_ra_data;
     remote_ra_cmd_t *cmd = NULL;
     int rc = ETIME;
+    int remaining = 0;
 
     if (!ra_data || !ra_data->cur_cmd) {
         return FALSE;
@@ -534,10 +542,10 @@ retry_start_cmd_cb(gpointer data)
                               PCMK_ACTION_MIGRATE_FROM, NULL)) {
         return FALSE;
     }
-    update_remaining_timeout(cmd);
 
-    if (cmd->remaining_timeout > 0) {
-        rc = handle_remote_ra_start(lrm_state, cmd, cmd->remaining_timeout);
+    remaining = remaining_timeout_sec(cmd);
+    if (remaining > 0) {
+        rc = handle_remote_ra_start(lrm_state, cmd, remaining * 1000);
     } else {
         pcmk__set_result(&(cmd->result), PCMK_OCF_UNKNOWN_ERROR,
                          PCMK_EXEC_TIMEOUT,
@@ -723,7 +731,7 @@ remote_lrm_op_callback(lrmd_event_data_t * op)
         && pcmk__strcase_any_of(cmd->action, PCMK_ACTION_START,
                                 PCMK_ACTION_MIGRATE_FROM, NULL)) {
         if (op->connection_rc < 0) {
-            update_remaining_timeout(cmd);
+            int remaining = remaining_timeout_sec(cmd);
 
             if ((op->connection_rc == -ENOKEY)
                 || (op->connection_rc == -EKEYREJECTED)) {
@@ -732,14 +740,15 @@ remote_lrm_op_callback(lrmd_event_data_t * op)
                                  PCMK_EXEC_ERROR,
                                  pcmk_strerror(op->connection_rc));
 
-            } else if (cmd->remaining_timeout > 3000) {
-                crm_trace("rescheduling start, remaining timeout %d", cmd->remaining_timeout);
+            } else if (remaining > 3) {
+                crm_trace("Rescheduling start (%ds remains before timeout)",
+                          remaining);
                 pcmk__create_timer(1000, retry_start_cmd_cb, lrm_state);
                 return;
 
             } else {
-                crm_trace("can't reschedule start, remaining timeout too small %d",
-                          cmd->remaining_timeout);
+                crm_trace("Not enough time before timeout (%ds) "
+                          "to reschedule start", remaining);
                 pcmk__format_result(&(cmd->result), PCMK_OCF_UNKNOWN_ERROR,
                                     PCMK_EXEC_TIMEOUT,
                                     "%s without enough time to retry",
-- 
2.43.0

