Project

General

Profile

Actions

Bug #52913

closed

[rbd-mirror] snapshot replayer is shut down with "local image linked to unknown peer" error on force promote

Added by Ilya Dryomov over 2 years ago. Updated 6 months ago.

Status:
Resolved
Priority:
Normal
Target version:
-
% Done:

0%

Source:
Tags:
backport_processed
Backport:
pacific,quincy,reef
Regression:
No
Severity:
3 - minor
Reviewed:
Affected Versions:
ceph-qa-suite:
Pull request ID:
Crash signature (v1):
Crash signature (v2):

Description

The special case of an orphan snapshot that is created as part of force promotion isn't detected:

2021-10-05T13:01:16.475+0000 7f10199ec700 -1 rbd::mirror::image_replayer::snapshot::Replayer: 0x561333850000 scan_local_mirror_snapshots: local image linked to unknown peer:
2021-10-05T13:01:16.481+0000 7f10199ec700 -1 rbd::mirror::image_replayer::snapshot::Replayer: 0x561332c23800 scan_local_mirror_snapshots: local image linked to unknown peer:
2021-10-05T13:01:46.552+0000 7f10199ec700 -1 rbd::mirror::image_replayer::snapshot::Replayer: 0x56133383c800 scan_local_mirror_snapshots: local image linked to unknown peer:
2021-10-05T13:01:46.556+0000 7f10199ec700 -1 rbd::mirror::image_replayer::snapshot::Replayer: 0x561332cf8c00 scan_local_mirror_snapshots: local image linked to unknown peer:
2021-10-05T13:02:16.480+0000 7f10191eb700 -1 rbd::mirror::image_replayer::snapshot::Replayer: 0x561332cda000 scan_local_mirror_snapshots: local image linked to unknown peer:
2021-10-05T13:02:16.485+0000 7f10199ec700 -1 rbd::mirror::image_replayer::snapshot::Replayer: 0x561333856000 scan_local_mirror_snapshots: local image linked to unknown peer:
2021-10-05T13:02:46.474+0000 7f10191eb700 -1 rbd::mirror::image_replayer::snapshot::Replayer: 0x56133383cc00 scan_local_mirror_snapshots: local image linked to unknown peer:
2021-10-05T13:02:46.481+0000 7f10191eb700 -1 rbd::mirror::image_replayer::snapshot::Replayer: 0x56133383dc00 scan_local_mirror_snapshots: local image linked to unknown peer:
2021-10-05T13:03:16.482+0000 7f10199ec700 -1 rbd::mirror::image_replayer::snapshot::Replayer: 0x561332c62c00 scan_local_mirror_snapshots: local image linked to unknown peer:
2021-10-05T13:03:16.486+0000 7f10199ec700 -1 rbd::mirror::image_replayer::snapshot::Replayer: 0x5613331c5000 scan_local_mirror_snapshots: local image linked to unknown peer:
2021-10-05T13:03:46.475+0000 7f10199ec700 -1 rbd::mirror::image_replayer::snapshot::Replayer: 0x561332c04400 scan_local_mirror_snapshots: local image linked to unknown peer:
2021-10-05T13:03:46.482+0000 7f10191eb700 -1 rbd::mirror::image_replayer::snapshot::Replayer: 0x561334068000 scan_local_mirror_snapshots: local image linked to unknown peer:

The replayer should be shut down gracefully with "orphan (force promote)" status.


Files

logs.bz2 (559 KB) logs.bz2 Prasanna Kumar Kalever, 06/06/2023 05:49 PM

Related issues 3 (0 open3 closed)

Copied to rbd - Backport #61893: reef: [rbd-mirror] snapshot replayer is shut down with "local image linked to unknown peer" error on force promoteResolvedIlya DryomovActions
Copied to rbd - Backport #61894: quincy: [rbd-mirror] snapshot replayer is shut down with "local image linked to unknown peer" error on force promoteResolvedIlya DryomovActions
Copied to rbd - Backport #61895: pacific: [rbd-mirror] snapshot replayer is shut down with "local image linked to unknown peer" error on force promoteResolvedIlya DryomovActions
Actions #1

Updated by Ilya Dryomov 11 months ago

  • Assignee changed from Ilya Dryomov to Prasanna Kumar Kalever
  • Backport set to pacific,quincy
Actions #2

Updated by Prasanna Kumar Kalever 11 months ago

Steps to reproduce:
1. Build the code with https://github.com/ceph/ceph/pull/51540
2. Setup mirroring on two clusters, enable mirroring on an image.
3. Kill site-a which is current primary and also kill site-a mirror daemon
4. Force promote image on site-b

Was able to hit below two scenarios (after decent 50 retries):

Scenario 1: Case where it is in {state=up+stopped, description=force promoted} forever!!!

void ImageReplayer<I>::shut_down(int r)
[...]
void ImageReplayer<I>::handle_shut_down(int r)  --> sets the m_state = STATE_STOPPED;

Please note `ImageReplayer<I>::handle_shut_down` calls itself a couple of times conditionally after the initial invocation.

Conditions which invokes `ImageReplayer<I>::handle_shut_down` from itself in this usecase include:

void ImageReplayer<I>::handle_shut_down(int r) {
  [...]
  if (!m_in_flight_op_tracker.empty()) {
  ┆ dout(15) << "waiting for in-flight operations to complete" << dendl;
  ┆ m_in_flight_op_tracker.wait_for_ops(new LambdaContext([this, r](int) {
  ┆ ┆ ┆ handle_shut_down(r);
  ┆ ┆ }));
  ┆ return;
  }
  if (!m_status_removed) {
  ┆ auto ctx = new LambdaContext([this, r](int) {
  ┆ ┆ m_status_removed = true;
  ┆ ┆ handle_shut_down(r);
  ┆ });
  ┆ remove_image_status(m_delete_in_progress, ctx);
  ┆ return;
  }
  [...]
  dout(10) << "stop complete" << dendl;
  [...]
  {
  [...]
  ┆ m_state = STATE_STOPPED;                                              
  }
}

So you shouldn't be surprised to see m_state not set to STATE_STOPPED after the initial couple of invocations.

While ImageReplayer<I>::handle_shut_down still didn't progress to "stop complete" ( m_state not yet = STATE_STOPPED; )


InstanceReplayer<I>::queue_start_image_replayers()
  -> InstanceReplayer<I>::start_image_replayers
    -> InstanceReplayer<I>::start_image_replayer
returns from here ..! i.e. it doesn't start a image replayer.

void InstanceReplayer<I>::start_image_replayer(
  [...]
  if (!image_replayer->is_stopped()) {
   return;
  }
  [...]
}

Note: InstanceReplayer<I>::queue_start_image_replayers() --> is invoked every 5 seconds base on `rbd_mirror_image_state_check_interval`

While `ImageReplayer<I>::handle_shut_down` is still at
1) "waiting for in-flight operations to complete"
or
2) remove_image_status, but not yet reached "stop complete"....

void RemotePoolPoller<I>::schedule_task(int r) --> polls every POLL_INTERVAL_SECONDS = 30 seconds
  -> void RemotePoolPoller<I>::handle_task()
    -> void RemotePoolPoller<I>::get_mirror_uuid()
      -> void RemotePoolPoller<I>::handle_get_mirror_uuid(int r)
        -> void RemotePoolPoller<I>::mirror_peer_ping()
          -> void RemotePoolPoller<I>::handle_mirror_peer_ping(int r)
            -> void RemotePoolPoller<I>::mirror_peer_list()
              -> void RemotePoolPoller<I>::handle_mirror_peer_list(int r)
                -> void RemotePoolPoller<I>::notify_listener()  --> m_listener.handle_updated()

struct PoolReplayer<I>::RemotePoolPollerListener
  : public remote_pool_poller::Listener {
  [...]
  void handle_updated(const RemotePoolMeta& remote_pool_meta) override {
    m_pool_replayer->handle_remote_pool_meta_updated(remote_pool_meta);
  }  
};
  -> void PoolReplayer<I>::handle_remote_pool_meta_updated() {
       [...]
       derr << "remote pool metadata updated unexpectedly" << dendl;
       m_stopping = true;
       m_cond.notify_all();
    }

Note m_stopping = true; now...
Not to remind `ImageReplayer<I>::handle_shut_down` is still at 1. "waiting for in-flight operations to complete" or 2. remove_image_status, but not reached "stop complete" yet .... i.e. m_state in the image replayer is still not at STATE_STOPPED.

Even any call to queue_start_image_replayers() -> start_image_replayers -> start_image_replayer and returns..! i.e. it doesn't start a image replayer.

On the next update_pool_replayers() --> invoked every 30 seconds, based on `rbd_mirror_pool_replayers_refresh_interval`


void Mirror::update_pool_replayers()
  -> "restarting failed pool replayer for" 
  -> pool_replayer->shut_down();
  -> pool_replayer->init(site_name);

Mean while, the pool replayer shut down will lead to all the other components shutdown.


void PoolReplayer<I>::shut_down()
  -> void LeaderWatcher<I>::shut_down(Context *on_finish)
    -> void LeaderWatcher<I>::cancel_timer_task()
    -> void LeaderWatcher<I>::shut_down_leader_lock()
      -> m_leader_lock->shut_down(ctx);
void NamespaceReplayer<I>::shut_down(Context *on_finish)
  -> void NamespaceReplayer<I>::stop_instance_replayer()
    -> void NamespaceReplayer<I>::handle_stop_instance_replayer(int r) 
      -> void NamespaceReplayer<I>::shut_down_instance_watcher()
        -> void NamespaceReplayer<I>::handle_shut_down_instance_watcher(int r)
          -> void NamespaceReplayer<I>::shut_down_instance_replayer()
            -> void InstanceReplayer<I>::shut_down()
              -> void InstanceReplayer<I>::cancel_image_state_check_task()
              -> void InstanceReplayer<I>::wait_for_ops()
                -> void InstanceReplayer<I>::handle_wait_for_ops(int r)
                  -> void InstanceReplayer<I>::stop_image_replayers()
                    ...

  -> void NamespaceReplayer<I>::handle_release_leader(Context *on_finish)
    -> void NamespaceReplayer<I>::shut_down_image_deleter(Context* on_finish)
      -> void NamespaceReplayer<I>::handle_shut_down_image_deleter(Context* on_finish)
        -> void NamespaceReplayer<I>::shut_down_pool_watchers(Context *on_finish)
          -> void NamespaceReplayer<I>::handle_shut_down_pool_watchers()
            -> void NamespaceReplayer<I>::shut_down_image_map(Context *on_finish)
              -> void NamespaceReplayer<I>::handle_shut_down_image_map()
                -> void InstanceReplayer<I>::release_all(Context *on_finish)
                  -> void InstanceReplayer<I>::stop_image_replayer()
                  ...

This is exactly where the `ImageReplayer<I>::handle_shut_down()` will reach "stop complete" i.e. finally m_state = STATE_STOPPED, but this is too late and the pool replayer and few other replayers are on their way winding-off.


2023-06-06T16:55:02.322+0530 7f1b019c4640 10 rbd::mirror::ImageReplayer: 0x5560178dfb00 [1/30158057-9bf1-49ca-8780-a4b2d0e502e2] handle_shut_down: stop complete

Trying to `pool_replayer->init(site_name)` leads to failure in the init_rados for the remote client:


void PoolReplayer<I>::init(const std::string& site_name)
  -> int PoolReplayer<I>::init_rados()
    -> r = (*rados_ref)->connect();
       if (r < 0) {
         derr << "error connecting to " << description << ": " 
              << cpp_strerror(r) << dendl;
         return;
       }


2023-05-29T17:31:45.710+0530 7fd02101a840 -1 rbd::mirror::PoolReplayer: 0x55ac9ec5d180 init_rados: error connecting to remote peer uuid: 1ce59938-8e03-41f8-8d41-38aa51882026 cluster: f6852128-353e-4c71-8b2d-ab84c8a62229 client: client.rbd-mirror-peer: (110) Connection timed out

Hence it returns from there every time `Mirror::update_pool_replayers()` is invoked, probably forever? (as I have destroyed the site-a)!!!! As a result PoolReplayer is never started for site-a.

Scenario 2: Different states but not "desc: local image is primary"

i.e. it jumps b/w various states:
1. {state=up+stopped, description=force promoted}
2. {state=up+starting_replay, description=starting replay}
3. {state=up+stopped, description=stopped}


2023-06-06T15:25:55.423+0530 7f07e573c640 10 rbd::mirror::ImageReplayer: 0x5606d6f45b00 [1/86183050-c11a-4046-aadb-1668fad83e58] handle_shut_down: stop complete
2023-06-06T15:26:09.828+0530 7f07ef750640 10 rbd::mirror::InstanceReplayer: 0x5606d64ca820 queue_start_image_replayers: 
2023-06-06T15:26:09.828+0530 7f07f2756640 10 rbd::mirror::InstanceReplayer: 0x5606d64ca820 start_image_replayers: 
2023-06-06T15:26:09.828+0530 7f07f2756640 10 rbd::mirror::InstanceReplayer: 0x5606d64ca820 start_image_replayers: PRASANNAXXX: staring image replayer
2023-06-06T15:26:09.828+0530 7f07f2756640 10 rbd::mirror::InstanceReplayer: 0x5606d64ca820 start_image_replayer: global_image_id=86183050-c11a-4046-aadb-1668fad83e58
2023-06-06T15:26:09.828+0530 7f07f2756640 15 rbd::mirror::MirrorStatusUpdater 0x5606d14bb1e0 set_mirror_image_status: global_image_id=86183050-c11a-4046-aadb-1668fad83e58, mirror_image_site_status={state=up+starting_replay, description=starting replay, last_update=0.000000]}
[...]
2023-06-06T15:26:09.874+0530 7f07e573c640  5 rbd::mirror::PoolReplayer: 0x5606d14d3180 handle_remote_pool_meta_updated: remote_pool_meta=mirror_uuid=, mirror_peer_uuid=
2023-06-06T15:26:09.874+0530 7f07e573c640 -1 rbd::mirror::PoolReplayer: 0x5606d14d3180 handle_remote_pool_meta_updated: remote pool metadata updated unexpectedly

In this Scenario `ImageReplayer<I>::handle_shut_down` reaches "stop complete" i.e. m_state = STATE_STOPPED even before `PoolReplayer<I>::handle_remote_pool_meta_updated` sets `m_stopping = true;` hence `update_pool_replayers` will not restart pool replayer. As a result the next,

queue_start_image_replayers() -> start_image_replayers -> start_image_replayer() actually succeeds and starts a new image replayer, when flips the changes from {state=up+stopped, description=force promoted} -> {state=up+starting_replay, description=starting replay}

Once the `PoolReplayer<I>::handle_remote_pool_meta_updated` sets `m_stopping = true;` the upcoming `Mirror::update_pool_replayers()` will try to restart the PoolReplayer, as part of the it will again invoke `ImageReplayer<I>::handle_shut_down` which will set {state=up+stopped, description=stopped}

Post this will endup with init_rados() failures like in the previous scenario.

Summary:
  • Its this way, because we do not have a way to order/synchronize the shut downs of various components like, ImageReplayer, PoolReplayer, NameSpaceReplayer, InstanceReplayer, RemotePoolPoller etc ... i.e. once the PoolReplayer is set to shut_down (As part of the update_pool_replayers) we do not wait for anything, we simply will invoke the ImageReplayer shut_down (and call other components shut downs)
  • Also note if the `rbd_mirror_pool_replayers_refresh_interval` is tweaked to < 30 (current default) the ratio of hitting `Scenario 1` increases.
  • Right now, we do not cleanup the remote client but rather fail in the init_rados() of remote site as part of the PoolReplayer initialization.

Please find the log files for both the cases, attached.

Actions #3

Updated by Prasanna Kumar Kalever 11 months ago

Forget to mention that I also have below additional diff in the code along with https://github.com/ceph/ceph/pull/51540 :

diff --git a/src/tools/rbd_mirror/image_replayer/snapshot/Replayer.cc b/src/tools/rbd_mirror/image_replayer/snapshot/Replayer.cc
index b4da280bf1b..c76505d58d8 100644
--- a/src/tools/rbd_mirror/image_replayer/snapshot/Replayer.cc
+++ b/src/tools/rbd_mirror/image_replayer/snapshot/Replayer.cc
@@ -539,7 +539,13 @@ void Replayer<I>::scan_local_mirror_snapshots(
   }

   if (m_local_snap_id_start > 0 || m_local_snap_id_end != CEPH_NOSNAP) {
-    if (m_local_mirror_snap_ns.is_non_primary() &&
+    if ((m_local_mirror_snap_ns.state ==
+                 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY) ||
+         m_local_mirror_snap_ns.is_orphan()) {
+      dout(5) << "local image promoted" << dendl;
+      handle_replay_complete(locker, 0, "force promoted");
+      return;
+    } else if (m_local_mirror_snap_ns.is_non_primary() &&
         m_local_mirror_snap_ns.primary_mirror_uuid !=
           m_state_builder->remote_mirror_uuid) {
       // TODO support multiple peers
@@ -548,11 +554,6 @@ void Replayer<I>::scan_local_mirror_snapshots(
       handle_replay_complete(locker, -EEXIST,
                              "local image linked to unknown peer");
       return;
-    } else if (m_local_mirror_snap_ns.state ==
-                 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY) {
-      dout(5) << "local image promoted" << dendl;
-      handle_replay_complete(locker, 0, "force promoted");
-      return;
     }

     dout(10) << "found local mirror snapshot: " 

Actions #4

Updated by Prasanna Kumar Kalever 11 months ago

  • Pull request ID set to 52086
Actions #5

Updated by Ilya Dryomov 10 months ago

  • Status changed from In Progress to Fix Under Review
  • Backport changed from pacific,quincy to pacific,quincy,reef
Actions #6

Updated by Ilya Dryomov 10 months ago

  • Status changed from Fix Under Review to Pending Backport
Actions #7

Updated by Backport Bot 10 months ago

  • Copied to Backport #61893: reef: [rbd-mirror] snapshot replayer is shut down with "local image linked to unknown peer" error on force promote added
Actions #8

Updated by Backport Bot 10 months ago

  • Copied to Backport #61894: quincy: [rbd-mirror] snapshot replayer is shut down with "local image linked to unknown peer" error on force promote added
Actions #9

Updated by Backport Bot 10 months ago

  • Copied to Backport #61895: pacific: [rbd-mirror] snapshot replayer is shut down with "local image linked to unknown peer" error on force promote added
Actions #10

Updated by Backport Bot 10 months ago

  • Tags set to backport_processed
Actions #11

Updated by Ilya Dryomov 6 months ago

  • Status changed from Pending Backport to Resolved

While running with --resolve-parent, the script "backport-create-issue" noticed that all backports of this issue are in status "Resolved" or "Rejected".

Actions

Also available in: Atom PDF