From 1fd1bd600f446a307028d024a32c855695ece3a5 Mon Sep 17 00:00:00 2001 From: Ilya Dryomov Date: Wed, 11 Dec 2024 16:25:13 +0100 Subject: [PATCH] librbd/migration/HttpClient: avoid hitting an assert in advance_state() 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 (cherry picked from commit 1046d610e3d6852258e6c4bf0355d0d13fb197b4) --- src/librbd/migration/HttpClient.cc | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/librbd/migration/HttpClient.cc b/src/librbd/migration/HttpClient.cc index 86a4adf4c597a..a55c2dd0480fb 100644 --- a/src/librbd/migration/HttpClient.cc +++ b/src/librbd/migration/HttpClient.cc @@ -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(); -- 2.39.5