]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rbd-mirror: re-generate new image id upon collision
authorJason Dillaman <dillaman@redhat.com>
Wed, 16 May 2018 15:11:37 +0000 (11:11 -0400)
committerJason Dillaman <dillaman@redhat.com>
Mon, 24 Sep 2018 19:11:02 +0000 (15:11 -0400)
Fixes: http://tracker.ceph.com/issues/24139
Signed-off-by: Jason Dillaman <dillaman@redhat.com>
src/test/rbd_mirror/image_replayer/test_mock_BootstrapRequest.cc
src/tools/rbd_mirror/image_replayer/BootstrapRequest.cc
src/tools/rbd_mirror/image_replayer/BootstrapRequest.h
src/tools/rbd_mirror/image_replayer/CreateImageRequest.cc

index 82112d24a434df7f6a7f8f9cc344e89c71d849fa..6c7c30a2cfde5f605b3591c7f46cdb099f90cdbd 100644 (file)
@@ -1113,6 +1113,83 @@ TEST_F(TestMockImageReplayerBootstrapRequest, PrimaryRemoteLocalDeleted) {
   ASSERT_EQ(0, ctx.wait());
 }
 
+TEST_F(TestMockImageReplayerBootstrapRequest, LocalImageIdCollision) {
+  create_local_image();
+
+  InSequence seq;
+
+  // lookup remote image tag class
+  cls::journal::Client client;
+  librbd::journal::ClientData client_data{
+    librbd::journal::ImageClientMeta{123}};
+  encode(client_data, client.data);
+  ::journal::MockJournaler mock_journaler;
+  expect_journaler_get_client(mock_journaler,
+                              librbd::Journal<>::IMAGE_CLIENT_ID,
+                              client, 0);
+
+  // open the remote image
+  librbd::MockJournal mock_journal;
+  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
+  MockOpenImageRequest mock_open_image_request;
+  expect_open_image(mock_open_image_request, m_remote_io_ctx,
+                    mock_remote_image_ctx.id, mock_remote_image_ctx, 0);
+
+  // test if remote image is primary
+  MockIsPrimaryRequest mock_is_primary_request;
+  expect_is_primary(mock_is_primary_request, true, 0);
+
+  // update client state back to syncing
+  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
+  mock_local_image_ctx.journal = &mock_journal;
+
+  librbd::util::s_image_id = mock_local_image_ctx.id;
+  librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta;
+  mirror_peer_client_meta.image_id = mock_local_image_ctx.id;
+  mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
+  client_data.client_meta = mirror_peer_client_meta;
+  client.data.clear();
+  encode(client_data, client.data);
+  expect_journaler_update_client(mock_journaler, client_data, 0);
+
+  // create the local image
+  MockCreateImageRequest mock_create_image_request;
+  expect_create_image(mock_create_image_request, mock_local_image_ctx.id,
+                      -EBADF);
+
+  expect_journaler_update_client(mock_journaler, client_data, 0);
+  expect_create_image(mock_create_image_request, mock_local_image_ctx.id, 0);
+
+  // open the local image
+  MockOpenLocalImageRequest mock_open_local_image_request;
+  expect_open_local_image(mock_open_local_image_request, m_local_io_ctx,
+                          mock_local_image_ctx.id, &mock_local_image_ctx, 0);
+  expect_is_resync_requested(mock_journal, false, 0);
+
+  expect_journal_get_tag_tid(mock_journal, 345);
+  expect_journal_get_tag_data(mock_journal, {"remote mirror uuid"});
+
+  // sync the remote image to the local image
+  MockImageSync mock_image_sync;
+  expect_image_sync(mock_image_sync, 0);
+
+  MockCloseImageRequest mock_close_image_request;
+  expect_close_image(mock_close_image_request, mock_remote_image_ctx, 0);
+
+  C_SaferCond ctx;
+  MockThreads mock_threads(m_threads);
+  MockInstanceWatcher mock_instance_watcher;
+  cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
+  mirror_peer_client_meta.image_id = "";
+  mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
+  MockBootstrapRequest *request = create_request(
+    &mock_threads, &mock_instance_watcher, mock_journaler, "",
+    mock_remote_image_ctx.id, "global image id", "local mirror uuid",
+    "remote mirror uuid", &client_state, &mirror_peer_client_meta, &ctx);
+  request->send();
+  ASSERT_EQ(0, ctx.wait());
+}
+
 } // namespace image_replayer
 } // namespace mirror
 } // namespace rbd
index 5025adc48e9ea2e6006864fcb1673ecf8dc40e36..26d4188c18bdec69b9310b656363d6511f4c810c 100644 (file)
@@ -496,7 +496,12 @@ template <typename I>
 void BootstrapRequest<I>::handle_create_local_image(int r) {
   dout(20) << ": r=" << r << dendl;
 
-  if (r < 0) {
+  if (r == -EBADF) {
+    dout(5) << ": image id " << m_local_image_id << " already in-use" << dendl;
+    m_local_image_id = "";
+    update_client_image();
+    return;
+  } else if (r < 0) {
     if (r == -ENOENT) {
       dout(10) << ": parent image does not exist" << dendl;
     } else {
index 59fd893927059f26276b4f2f56cf5438f0130f47..ea9f856523f57bd38d85141a2b7d4881f9d6b036 100644 (file)
@@ -106,8 +106,9 @@ private:
    *    |                                               *   *   |
    *    | (remote image primary, no local image id)     *   *   |
    *    \----> UPDATE_CLIENT_IMAGE  * * * * * * * * * * *   *   |
-   *    |         |                                     *   *   |
-   *    |         v                                     *   *   |
+   *    |         |   ^                                 *   *   |
+   *    |         |   * (duplicate image id)            *   *   |
+   *    |         v   *                                 *   *   |
    *    \----> CREATE_LOCAL_IMAGE * * * * * * * * * * * *   *   |
    *    |         |                                     *   *   |
    *    |         v                                     *   *   |
index eb34a5e915f8338585185e3c66b3a35ca7062046..27e0895097041198d4bb0559f425c98bcbe1a011 100644 (file)
@@ -88,7 +88,11 @@ void CreateImageRequest<I>::create_image() {
 template <typename I>
 void CreateImageRequest<I>::handle_create_image(int r) {
   dout(10) << "r=" << r << dendl;
-  if (r < 0) {
+  if (r == -EBADF) {
+    dout(5) << "image id " << m_local_image_id << " already in-use" << dendl;
+    finish(r);
+    return;
+  } else if (r < 0) {
     derr << "failed to create local image: " << cpp_strerror(r) << dendl;
     finish(r);
     return;
@@ -343,7 +347,11 @@ void CreateImageRequest<I>::clone_image() {
 template <typename I>
 void CreateImageRequest<I>::handle_clone_image(int r) {
   dout(10) << "r=" << r << dendl;
-  if (r < 0) {
+  if (r == -EBADF) {
+    dout(5) << "image id " << m_local_image_id << " already in-use" << dendl;
+    finish(r);
+    return;
+  } else if (r < 0) {
     derr << "failed to clone image " << m_parent_pool_name << "/"
          << m_remote_parent_spec.image_id << " to "
          << m_local_image_name << dendl;