]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd/migration/HttpClient: avoid hitting an assert in advance_state()
authorIlya Dryomov <idryomov@gmail.com>
Wed, 11 Dec 2024 15:25:13 +0000 (16:25 +0100)
committerIlya Dryomov <idryomov@gmail.com>
Fri, 13 Dec 2024 12:44:45 +0000 (13:44 +0100)
If the shutdown gets delayed until the state transition from
STATE_RESET_CONNECTING completes and the reconnect is successful
(i.e. next_state is STATE_READY), we eventually hit "unexpected
state transition" assert in advance_state().  The reason is that
advance_state() would update m_state and call disconnect() under
STATE_READY instead of STATE_SHUTTING_DOWN.  After the disconnect
maybe_finalize_shutdown() would enter advance_state() again with
STATE_SHUTDOWN as next_state, but the transition to that from
STATE_READY is invalid.

Plug this by not transitioning to next_state if current_state is
STATE_SHUTTING_DOWN.

Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
src/librbd/migration/HttpClient.cc

index 86a4adf4c597abf6814115314ffae3d5e5c8aa8c..a55c2dd0480fb08b66a250fbb9521df27e21f166 100644 (file)
@@ -63,14 +63,13 @@ public:
     m_on_shutdown = on_finish;
 
     auto current_state = m_state;
+    m_state = STATE_SHUTTING_DOWN;
+
     if (current_state == STATE_UNINITIALIZED) {
       // never initialized or resolve/connect failed
       on_finish->complete(0);
       return;
-    }
-
-    m_state = STATE_SHUTTING_DOWN;
-    if (current_state != STATE_READY) {
+    } else if (current_state != STATE_READY) {
       // delay shutdown until current state transition completes
       return;
     }
@@ -501,7 +500,10 @@ private:
                    << "next_state=" << next_state << ", "
                    << "r=" << r << dendl;
 
-    m_state = next_state;
+    if (current_state != STATE_SHUTTING_DOWN) {
+      m_state = next_state;
+    }
+
     if (current_state == STATE_CONNECTING) {
       if (next_state == STATE_UNINITIALIZED) {
         shutdown_socket();