From b638d19d126646d2a8f6da11067c5f392a62525e Mon Sep 17 00:00:00 2001 From: Guang Yang Date: Fri, 9 May 2014 09:21:23 +0000 Subject: [PATCH] msg: Fix inconsistent message sequence negotiation during connection reset Backport: firefly, emperor, dumpling Signed-off-by: Guang Yang (yguang@yahoo-inc.com) Reviewed-by: Greg Farnum (cherry picked from commit bdee119076dd0eb65334840d141ccdf06091e3c9) --- src/msg/Pipe.cc | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/msg/Pipe.cc b/src/msg/Pipe.cc index ac13058a68bda..f981fa545a493 100644 --- a/src/msg/Pipe.cc +++ b/src/msg/Pipe.cc @@ -231,6 +231,10 @@ int Pipe::accept() bool authorizer_valid; uint64_t feat_missing; bool replaced = false; + // this variable denotes if the connection attempt from peer is a hard + // reset or not, it is true if there is an existing connection and the + // connection sequence from peer is equal to zero + bool is_reset_from_peer = false; CryptoKey session_key; int removed; // single-use down below @@ -445,6 +449,8 @@ int Pipe::accept() if (connect.connect_seq == 0 && existing->connect_seq > 0) { ldout(msgr->cct,0) << "accept peer reset, then tried to connect to us, replacing" << dendl; + // this is a hard reset from peer + is_reset_from_peer = true; if (policy.resetcheck) existing->was_session_reset(); // this resets out_queue, msg_ and connect_seq #'s goto replace; @@ -567,7 +573,8 @@ int Pipe::accept() replace: assert(existing->pipe_lock.is_locked()); assert(pipe_lock.is_locked()); - if (connect.features & CEPH_FEATURE_RECONNECT_SEQ) { + // if it is a hard reset from peer, we don't need a round-trip to negotiate in/out sequence + if ((connect.features & CEPH_FEATURE_RECONNECT_SEQ) && !is_reset_from_peer) { reply_tag = CEPH_MSGR_TAG_SEQ; existing_seq = existing->in_seq; } @@ -601,7 +608,10 @@ int Pipe::accept() uint64_t replaced_conn_id = conn_id; conn_id = existing->conn_id; existing->conn_id = replaced_conn_id; - in_seq = existing->in_seq; + + // reset the in_seq if this is a hard reset from peer, + // otherwise we respect our original connection's value + in_seq = is_reset_from_peer ? 0 : existing->in_seq; in_seq_acked = in_seq; // steal outgoing queue and out_seq -- 2.39.5