]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rbd-mirror: use generalized deep copy for image sync
authorMykola Golub <mgolub@mirantis.com>
Wed, 27 Sep 2017 10:10:55 +0000 (12:10 +0200)
committerMykola Golub <to.my.trociny@gmail.com>
Mon, 6 Nov 2017 08:29:44 +0000 (10:29 +0200)
Signed-off-by: Mykola Golub <mgolub@mirantis.com>
21 files changed:
src/test/rbd_mirror/CMakeLists.txt
src/test/rbd_mirror/image_replayer/test_mock_BootstrapRequest.cc
src/test/rbd_mirror/image_sync/test_mock_ImageCopyRequest.cc [deleted file]
src/test/rbd_mirror/image_sync/test_mock_MetadataCopyRequest.cc [deleted file]
src/test/rbd_mirror/image_sync/test_mock_ObjectCopyRequest.cc [deleted file]
src/test/rbd_mirror/image_sync/test_mock_SnapshotCopyRequest.cc [deleted file]
src/test/rbd_mirror/image_sync/test_mock_SnapshotCreateRequest.cc [deleted file]
src/test/rbd_mirror/test_mock_ImageSync.cc
src/tools/rbd_mirror/CMakeLists.txt
src/tools/rbd_mirror/ImageSync.cc
src/tools/rbd_mirror/ImageSync.h
src/tools/rbd_mirror/image_sync/ImageCopyRequest.cc [deleted file]
src/tools/rbd_mirror/image_sync/ImageCopyRequest.h [deleted file]
src/tools/rbd_mirror/image_sync/MetadataCopyRequest.cc [deleted file]
src/tools/rbd_mirror/image_sync/MetadataCopyRequest.h [deleted file]
src/tools/rbd_mirror/image_sync/ObjectCopyRequest.cc [deleted file]
src/tools/rbd_mirror/image_sync/ObjectCopyRequest.h [deleted file]
src/tools/rbd_mirror/image_sync/SnapshotCopyRequest.cc [deleted file]
src/tools/rbd_mirror/image_sync/SnapshotCopyRequest.h [deleted file]
src/tools/rbd_mirror/image_sync/SnapshotCreateRequest.cc [deleted file]
src/tools/rbd_mirror/image_sync/SnapshotCreateRequest.h [deleted file]

index dc8aafe8ec3700d6a3f7af3c0a188e069a05ac24..a11db807426d41c610a417ffdcfce7e684033f7b 100644 (file)
@@ -29,11 +29,6 @@ add_executable(unittest_rbd_mirror
   image_replayer/test_mock_GetMirrorImageIdRequest.cc
   image_replayer/test_mock_PrepareLocalImageRequest.cc
   image_replayer/test_mock_PrepareRemoteImageRequest.cc
-  image_sync/test_mock_ImageCopyRequest.cc
-  image_sync/test_mock_MetadataCopyRequest.cc
-  image_sync/test_mock_ObjectCopyRequest.cc
-  image_sync/test_mock_SnapshotCopyRequest.cc
-  image_sync/test_mock_SnapshotCreateRequest.cc
   image_sync/test_mock_SyncPointCreateRequest.cc
   image_sync/test_mock_SyncPointPruneRequest.cc
   pool_watcher/test_mock_RefreshImagesRequest.cc
index 3d4c16a820d55e43d74d3952032976a87a394b4a..ee5e49811e31e9b033bd79bf1b4c27b9713a05b4 100644 (file)
@@ -63,8 +63,8 @@ struct ImageSync<librbd::MockTestImageCtx> {
   static ImageSync* create(
       librbd::MockTestImageCtx *local_image_ctx,
       librbd::MockTestImageCtx *remote_image_ctx,
-      SafeTimer *timer, Mutex *timer_lock, const std::string &mirror_uuid,
-      ::journal::MockJournaler *journaler,
+      SafeTimer *timer, Mutex *timer_lock,
+      const std::string &mirror_uuid, ::journal::MockJournaler *journaler,
       librbd::journal::MirrorPeerClientMeta *client_meta, ContextWQ *work_queue,
       InstanceWatcher<librbd::MockTestImageCtx> *instance_watcher,
       Context *on_finish, ProgressContext *progress_ctx) {
diff --git a/src/test/rbd_mirror/image_sync/test_mock_ImageCopyRequest.cc b/src/test/rbd_mirror/image_sync/test_mock_ImageCopyRequest.cc
deleted file mode 100644 (file)
index 81c0ea9..0000000
+++ /dev/null
@@ -1,649 +0,0 @@
-// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
-// vim: ts=8 sw=2 smarttab
-
-#include "test/rbd_mirror/test_mock_fixture.h"
-#include "include/rbd/librbd.hpp"
-#include "librbd/ImageCtx.h"
-#include "librbd/ImageState.h"
-#include "librbd/Operations.h"
-#include "librbd/journal/TypeTraits.h"
-#include "test/journal/mock/MockJournaler.h"
-#include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
-#include "test/librbd/mock/MockImageCtx.h"
-#include "tools/rbd_mirror/image_sync/ImageCopyRequest.h"
-#include "tools/rbd_mirror/image_sync/ObjectCopyRequest.h"
-#include "tools/rbd_mirror/Threads.h"
-#include <boost/scope_exit.hpp>
-
-namespace librbd {
-
-namespace {
-
-struct MockTestImageCtx : public librbd::MockImageCtx {
-  MockTestImageCtx(librbd::ImageCtx &image_ctx)
-    : librbd::MockImageCtx(image_ctx) {
-  }
-};
-
-} // anonymous namespace
-
-namespace journal {
-
-template <>
-struct TypeTraits<librbd::MockTestImageCtx> {
-  typedef ::journal::MockJournaler Journaler;
-};
-
-} // namespace journal
-} // namespace librbd
-
-namespace rbd {
-namespace mirror {
-namespace image_sync {
-
-template <>
-struct ObjectCopyRequest<librbd::MockTestImageCtx> {
-  static ObjectCopyRequest* s_instance;
-  static ObjectCopyRequest* create(librbd::MockTestImageCtx *local_image_ctx,
-                                   librbd::MockTestImageCtx *remote_image_ctx,
-                                   const ImageCopyRequest<librbd::MockTestImageCtx>::SnapMap *snap_map,
-                                   uint64_t object_number, Context *on_finish) {
-    assert(s_instance != nullptr);
-    Mutex::Locker locker(s_instance->lock);
-    s_instance->snap_map = snap_map;
-    s_instance->object_contexts[object_number] = on_finish;
-    s_instance->cond.Signal();
-    return s_instance;
-  }
-
-  MOCK_METHOD0(send, void());
-
-  Mutex lock;
-  Cond cond;
-
-  const ImageCopyRequest<librbd::MockTestImageCtx>::SnapMap *snap_map = nullptr;
-  std::map<uint64_t, Context *> object_contexts;
-
-  ObjectCopyRequest() : lock("lock") {
-    s_instance = this;
-  }
-};
-
-ObjectCopyRequest<librbd::MockTestImageCtx>* ObjectCopyRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
-
-} // namespace image_sync
-} // namespace mirror
-} // namespace rbd
-
-// template definitions
-#include "tools/rbd_mirror/image_sync/ImageCopyRequest.cc"
-template class rbd::mirror::image_sync::ImageCopyRequest<librbd::MockTestImageCtx>;
-
-namespace rbd {
-namespace mirror {
-namespace image_sync {
-
-using ::testing::_;
-using ::testing::InSequence;
-using ::testing::Invoke;
-using ::testing::Return;
-using ::testing::WithArg;
-using ::testing::InvokeWithoutArgs;
-
-class TestMockImageSyncImageCopyRequest : public TestMockFixture {
-public:
-  typedef ImageCopyRequest<librbd::MockTestImageCtx> MockImageCopyRequest;
-  typedef ObjectCopyRequest<librbd::MockTestImageCtx> MockObjectCopyRequest;
-
-  void SetUp() override {
-    TestMockFixture::SetUp();
-
-    librbd::RBD rbd;
-    ASSERT_EQ(0, create_image(rbd, m_remote_io_ctx, m_image_name, m_image_size));
-    ASSERT_EQ(0, open_image(m_remote_io_ctx, m_image_name, &m_remote_image_ctx));
-
-    ASSERT_EQ(0, create_image(rbd, m_local_io_ctx, m_image_name, m_image_size));
-    ASSERT_EQ(0, open_image(m_local_io_ctx, m_image_name, &m_local_image_ctx));
-  }
-
-  void expect_get_snap_id(librbd::MockTestImageCtx &mock_image_ctx) {
-    EXPECT_CALL(mock_image_ctx, get_snap_id(_, _))
-      .WillRepeatedly(Invoke([&mock_image_ctx](cls::rbd::SnapshotNamespace snap_namespace,
-                                              std::string snap_name) {
-        assert(mock_image_ctx.image_ctx->snap_lock.is_locked());
-        return mock_image_ctx.image_ctx->get_snap_id(snap_namespace, snap_name);
-      }));
-  }
-
-  void expect_get_object_count(librbd::MockTestImageCtx &mock_image_ctx,
-                               uint64_t count) {
-    EXPECT_CALL(mock_image_ctx, get_object_count(_))
-      .WillOnce(Return(count)).RetiresOnSaturation();
-  }
-
-  void expect_update_client(journal::MockJournaler &mock_journaler, int r) {
-    EXPECT_CALL(mock_journaler, update_client(_, _))
-      .WillOnce(WithArg<1>(CompleteContext(r)));
-  }
-
-  void expect_object_copy_send(MockObjectCopyRequest &mock_object_copy_request) {
-    EXPECT_CALL(mock_object_copy_request, send());
-  }
-
-  bool complete_object_copy(MockObjectCopyRequest &mock_object_copy_request,
-                               uint64_t object_num, int r,
-                               std::function<void()> fn = []() {}) {
-    Mutex::Locker locker(mock_object_copy_request.lock);
-    while (mock_object_copy_request.object_contexts.count(object_num) == 0) {
-      if (mock_object_copy_request.cond.WaitInterval(mock_object_copy_request.lock,
-                                                     utime_t(10, 0)) != 0) {
-        return false;
-      }
-    }
-
-    FunctionContext *wrapper_ctx = new FunctionContext(
-      [&mock_object_copy_request, object_num, fn] (int r) {
-        fn();
-        mock_object_copy_request.object_contexts[object_num]->complete(r);
-      });
-    m_threads->work_queue->queue(wrapper_ctx, r);
-    return true;
-  }
-
-  MockImageCopyRequest::SnapMap wait_for_snap_map(MockObjectCopyRequest &mock_object_copy_request) {
-    Mutex::Locker locker(mock_object_copy_request.lock);
-    while (mock_object_copy_request.snap_map == nullptr) {
-      if (mock_object_copy_request.cond.WaitInterval(mock_object_copy_request.lock,
-                                                     utime_t(10, 0)) != 0) {
-        return MockImageCopyRequest::SnapMap();
-      }
-    }
-    return *mock_object_copy_request.snap_map;
-  }
-
-  MockImageCopyRequest *create_request(librbd::MockTestImageCtx &mock_remote_image_ctx,
-                                       librbd::MockTestImageCtx &mock_local_image_ctx,
-                                       journal::MockJournaler &mock_journaler,
-                                       librbd::journal::MirrorPeerSyncPoint &sync_point,
-                                       Context *ctx) {
-    return new MockImageCopyRequest(&mock_local_image_ctx,
-                                    &mock_remote_image_ctx,
-                                    m_threads->timer, &m_threads->timer_lock,
-                                    &mock_journaler, &m_client_meta,
-                                    &sync_point, ctx);
-  }
-
-  using TestFixture::create_snap;
-  int create_snap(const char* snap_name) {
-    librados::snap_t remote_snap_id;
-    int r = create_snap(m_remote_image_ctx, snap_name, &remote_snap_id);
-    if (r < 0) {
-      return r;
-    }
-
-    librados::snap_t local_snap_id;
-    r = create_snap(m_local_image_ctx, snap_name, &local_snap_id);
-    if (r < 0) {
-      return r;
-    }
-
-    // collection of all existing snaps in local image
-    MockImageCopyRequest::SnapIds local_snap_ids({local_snap_id});
-    if (!m_snap_map.empty()) {
-      local_snap_ids.insert(local_snap_ids.end(),
-                            m_snap_map.rbegin()->second.begin(),
-                            m_snap_map.rbegin()->second.end());
-    }
-    m_snap_map[remote_snap_id] = local_snap_ids;
-    m_client_meta.snap_seqs[remote_snap_id] = local_snap_id;
-    return 0;
-  }
-
-  librbd::ImageCtx *m_remote_image_ctx;
-  librbd::ImageCtx *m_local_image_ctx;
-  librbd::journal::MirrorPeerClientMeta m_client_meta;
-  MockImageCopyRequest::SnapMap m_snap_map;
-};
-
-TEST_F(TestMockImageSyncImageCopyRequest, SimpleImage) {
-  ASSERT_EQ(0, create_snap("snap1"));
-  m_client_meta.sync_points = {{cls::rbd::UserSnapshotNamespace(),
-                               "snap1",
-                               boost::none}};
-
-  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-  journal::MockJournaler mock_journaler;
-  MockObjectCopyRequest mock_object_copy_request;
-
-  expect_get_snap_id(mock_remote_image_ctx);
-
-  InSequence seq;
-  expect_get_object_count(mock_remote_image_ctx, 1);
-  expect_get_object_count(mock_remote_image_ctx, 0);
-  expect_update_client(mock_journaler, 0);
-  expect_object_copy_send(mock_object_copy_request);
-  expect_update_client(mock_journaler, 0);
-
-  C_SaferCond ctx;
-  MockImageCopyRequest *request = create_request(mock_remote_image_ctx,
-                                                 mock_local_image_ctx,
-                                                 mock_journaler,
-                                                 m_client_meta.sync_points.front(),
-                                                 &ctx);
-  request->send();
-
-  ASSERT_EQ(m_snap_map, wait_for_snap_map(mock_object_copy_request));
-  ASSERT_TRUE(complete_object_copy(mock_object_copy_request, 0, 0));
-  ASSERT_EQ(0, ctx.wait());
-}
-
-TEST_F(TestMockImageSyncImageCopyRequest, Throttled) {
-  ASSERT_EQ(0, create_snap("snap1"));
-  m_client_meta.sync_points = {{cls::rbd::UserSnapshotNamespace(),
-                               "snap1",
-                               boost::none}};
-
-  std::string update_sync_age;;
-  ASSERT_EQ(0, _rados->conf_get("rbd_mirror_sync_point_update_age", update_sync_age));
-  ASSERT_EQ(0, _rados->conf_set("rbd_mirror_sync_point_update_age", "1"));
-  BOOST_SCOPE_EXIT( (update_sync_age) ) {
-    ASSERT_EQ(0, _rados->conf_set("rbd_mirror_sync_point_update_age", update_sync_age.c_str()));
-  } BOOST_SCOPE_EXIT_END;
-
-
-  std::string max_ops_str;
-  ASSERT_EQ(0, _rados->conf_get("rbd_concurrent_management_ops", max_ops_str));
-  int max_ops = std::stoi(max_ops_str);
-
-  uint64_t object_count = 55;
-
-  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-  journal::MockJournaler mock_journaler;
-  MockObjectCopyRequest mock_object_copy_request;
-
-  expect_get_snap_id(mock_remote_image_ctx);
-
-  expect_get_object_count(mock_remote_image_ctx, object_count);
-  expect_get_object_count(mock_remote_image_ctx, 0);
-
-  EXPECT_CALL(mock_object_copy_request, send()).Times(object_count);
-
-  boost::optional<uint64_t> expected_object_number(boost::none);
-  EXPECT_CALL(mock_journaler, update_client(_, _))
-    .WillRepeatedly(
-        Invoke([&expected_object_number, max_ops, object_count, this]
-               (bufferlist data, Context *ctx) {
-          ASSERT_EQ(expected_object_number,
-                    m_client_meta.sync_points.front().object_number);
-          if (!expected_object_number) {
-            expected_object_number = (max_ops - 1);
-          } else {
-            expected_object_number = expected_object_number.get() + max_ops;
-          }
-
-          if (expected_object_number.get() > (object_count - 1)) {
-            expected_object_number = (object_count - 1);
-          }
-
-          m_threads->work_queue->queue(ctx, 0);
-      }));
-
-
-  C_SaferCond ctx;
-  MockImageCopyRequest *request = create_request(mock_remote_image_ctx,
-                                                 mock_local_image_ctx,
-                                                 mock_journaler,
-                                                 m_client_meta.sync_points.front(),
-                                                 &ctx);
-  request->send();
-
-  std::function<void()> sleep_fn = [request]() {
-    sleep(2);
-  };
-
-  ASSERT_EQ(m_snap_map, wait_for_snap_map(mock_object_copy_request));
-  for (uint64_t i = 0; i < object_count; ++i) {
-    if (i % 10 == 0) {
-      ASSERT_TRUE(complete_object_copy(mock_object_copy_request, i, 0, sleep_fn));
-    } else {
-      ASSERT_TRUE(complete_object_copy(mock_object_copy_request, i, 0));
-    }
-  }
-  ASSERT_EQ(0, ctx.wait());
-}
-
-TEST_F(TestMockImageSyncImageCopyRequest, SnapshotSubset) {
-  ASSERT_EQ(0, create_snap("snap1"));
-  ASSERT_EQ(0, create_snap("snap2"));
-  ASSERT_EQ(0, create_snap("snap3"));
-  m_client_meta.sync_points = {{cls::rbd::UserSnapshotNamespace(),
-                               "snap3", "snap2", boost::none}};
-
-  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-  journal::MockJournaler mock_journaler;
-  MockObjectCopyRequest mock_object_copy_request;
-
-  expect_get_snap_id(mock_remote_image_ctx);
-
-  InSequence seq;
-  expect_get_object_count(mock_remote_image_ctx, 1);
-  expect_get_object_count(mock_remote_image_ctx, 0);
-  expect_get_object_count(mock_remote_image_ctx, 1);
-  expect_get_object_count(mock_remote_image_ctx, 1);
-  expect_update_client(mock_journaler, 0);
-  expect_object_copy_send(mock_object_copy_request);
-  expect_update_client(mock_journaler, 0);
-
-  C_SaferCond ctx;
-  MockImageCopyRequest *request = create_request(mock_remote_image_ctx,
-                                                 mock_local_image_ctx,
-                                                 mock_journaler,
-                                                 m_client_meta.sync_points.front(),
-                                                 &ctx);
-  request->send();
-
-  MockImageCopyRequest::SnapMap snap_map(m_snap_map);
-  snap_map.erase(snap_map.begin());
-  ASSERT_EQ(snap_map, wait_for_snap_map(mock_object_copy_request));
-
-  ASSERT_TRUE(complete_object_copy(mock_object_copy_request, 0, 0));
-  ASSERT_EQ(0, ctx.wait());
-}
-
-TEST_F(TestMockImageSyncImageCopyRequest, RestartCatchup) {
-  ASSERT_EQ(0, create_snap("snap1"));
-  ASSERT_EQ(0, create_snap("snap2"));
-  m_client_meta.sync_points = {{cls::rbd::UserSnapshotNamespace(), "snap1", boost::none},
-                               {cls::rbd::UserSnapshotNamespace(), "snap2", "snap1", boost::none}};
-
-  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-  journal::MockJournaler mock_journaler;
-  MockObjectCopyRequest mock_object_copy_request;
-
-  expect_get_snap_id(mock_remote_image_ctx);
-
-  InSequence seq;
-  expect_get_object_count(mock_remote_image_ctx, 1);
-  expect_get_object_count(mock_remote_image_ctx, 0);
-  expect_get_object_count(mock_remote_image_ctx, 0);
-  expect_update_client(mock_journaler, 0);
-  expect_object_copy_send(mock_object_copy_request);
-  expect_update_client(mock_journaler, 0);
-
-  C_SaferCond ctx;
-  MockImageCopyRequest *request = create_request(mock_remote_image_ctx,
-                                                 mock_local_image_ctx,
-                                                 mock_journaler,
-                                                 m_client_meta.sync_points.back(),
-                                                 &ctx);
-  request->send();
-
-  ASSERT_EQ(m_snap_map, wait_for_snap_map(mock_object_copy_request));
-  ASSERT_TRUE(complete_object_copy(mock_object_copy_request, 0, 0));
-  ASSERT_EQ(0, ctx.wait());
-}
-
-TEST_F(TestMockImageSyncImageCopyRequest, RestartPartialSync) {
-  ASSERT_EQ(0, create_snap("snap1"));
-  m_client_meta.sync_points = {{cls::rbd::UserSnapshotNamespace(),
-                               "snap1",
-                               librbd::journal::MirrorPeerSyncPoint::ObjectNumber{0U}}};
-
-  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-  journal::MockJournaler mock_journaler;
-  MockObjectCopyRequest mock_object_copy_request;
-
-  expect_get_snap_id(mock_remote_image_ctx);
-
-  InSequence seq;
-  expect_get_object_count(mock_remote_image_ctx, 1);
-  expect_get_object_count(mock_remote_image_ctx, 2);
-  expect_update_client(mock_journaler, 0);
-  expect_object_copy_send(mock_object_copy_request);
-  expect_update_client(mock_journaler, 0);
-
-  C_SaferCond ctx;
-  MockImageCopyRequest *request = create_request(mock_remote_image_ctx,
-                                                 mock_local_image_ctx,
-                                                 mock_journaler,
-                                                 m_client_meta.sync_points.front(),
-                                                 &ctx);
-  request->send();
-
-  ASSERT_TRUE(complete_object_copy(mock_object_copy_request, 1, 0));
-  ASSERT_EQ(0, ctx.wait());
-}
-
-TEST_F(TestMockImageSyncImageCopyRequest, Cancel) {
-  std::string max_ops_str;
-  ASSERT_EQ(0, _rados->conf_get("rbd_concurrent_management_ops", max_ops_str));
-  ASSERT_EQ(0, _rados->conf_set("rbd_concurrent_management_ops", "1"));
-  BOOST_SCOPE_EXIT( (max_ops_str) ) {
-    ASSERT_EQ(0, _rados->conf_set("rbd_concurrent_management_ops", max_ops_str.c_str()));
-  } BOOST_SCOPE_EXIT_END;
-
-  ASSERT_EQ(0, create_snap("snap1"));
-  m_client_meta.sync_points = {{cls::rbd::UserSnapshotNamespace(), "snap1", boost::none}};
-
-  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-  journal::MockJournaler mock_journaler;
-  MockObjectCopyRequest mock_object_copy_request;
-
-  expect_get_snap_id(mock_remote_image_ctx);
-
-  InSequence seq;
-  expect_get_object_count(mock_remote_image_ctx, 2);
-  expect_get_object_count(mock_remote_image_ctx, 2);
-  expect_update_client(mock_journaler, 0);
-  expect_object_copy_send(mock_object_copy_request);
-
-  C_SaferCond ctx;
-  MockImageCopyRequest *request = create_request(mock_remote_image_ctx,
-                                                 mock_local_image_ctx,
-                                                 mock_journaler,
-                                                 m_client_meta.sync_points.front(),
-                                                 &ctx);
-  request->send();
-
-  ASSERT_EQ(m_snap_map, wait_for_snap_map(mock_object_copy_request));
-  request->cancel();
-
-  ASSERT_TRUE(complete_object_copy(mock_object_copy_request, 0, 0));
-  ASSERT_EQ(-ECANCELED, ctx.wait());
-}
-
-TEST_F(TestMockImageSyncImageCopyRequest, Cancel_Inflight_Sync) {
-  std::string update_sync_age;;
-  ASSERT_EQ(0, _rados->conf_get("rbd_mirror_sync_point_update_age", update_sync_age));
-  ASSERT_EQ(0, _rados->conf_set("rbd_mirror_sync_point_update_age", "1"));
-  BOOST_SCOPE_EXIT( (update_sync_age) ) {
-    ASSERT_EQ(0, _rados->conf_set("rbd_mirror_sync_point_update_age", update_sync_age.c_str()));
-  } BOOST_SCOPE_EXIT_END;
-
-  std::string max_ops_str;
-  ASSERT_EQ(0, _rados->conf_get("rbd_concurrent_management_ops", max_ops_str));
-  ASSERT_EQ(0, _rados->conf_set("rbd_concurrent_management_ops", "3"));
-  BOOST_SCOPE_EXIT( (max_ops_str) ) {
-    ASSERT_EQ(0, _rados->conf_set("rbd_concurrent_management_ops", max_ops_str.c_str()));
-  } BOOST_SCOPE_EXIT_END;
-
-  ASSERT_EQ(0, create_snap("snap1"));
-  m_client_meta.sync_points = {{cls::rbd::UserSnapshotNamespace(), "snap1", boost::none}};
-
-  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-  journal::MockJournaler mock_journaler;
-  MockObjectCopyRequest mock_object_copy_request;
-
-  expect_get_snap_id(mock_remote_image_ctx);
-
-  expect_get_object_count(mock_remote_image_ctx, 10);
-  expect_get_object_count(mock_remote_image_ctx, 0);
-
-  EXPECT_CALL(mock_object_copy_request, send()).Times(6);
-
-  EXPECT_CALL(mock_journaler, update_client(_, _))
-    .WillRepeatedly(Invoke([this] (bufferlist data, Context *ctx) {
-          m_threads->work_queue->queue(ctx, 0);
-      }));
-
-
-  C_SaferCond ctx;
-  MockImageCopyRequest *request = create_request(mock_remote_image_ctx,
-                                                 mock_local_image_ctx,
-                                                 mock_journaler,
-                                                 m_client_meta.sync_points.front(),
-                                                 &ctx);
-  request->send();
-
-  ASSERT_EQ(m_snap_map, wait_for_snap_map(mock_object_copy_request));
-
-  std::function<void()> cancel_fn = [request]() {
-    sleep(2);
-    request->cancel();
-  };
-
-  ASSERT_TRUE(complete_object_copy(mock_object_copy_request, 0, 0));
-  ASSERT_TRUE(complete_object_copy(mock_object_copy_request, 1, 0));
-  ASSERT_TRUE(complete_object_copy(mock_object_copy_request, 2, 0));
-  ASSERT_TRUE(complete_object_copy(mock_object_copy_request, 3, 0, cancel_fn));
-  ASSERT_TRUE(complete_object_copy(mock_object_copy_request, 4, 0));
-  ASSERT_TRUE(complete_object_copy(mock_object_copy_request, 5, 0));
-
-  ASSERT_EQ(-ECANCELED, ctx.wait());
-  ASSERT_EQ(5u, m_client_meta.sync_points.front().object_number.get());
-}
-
-TEST_F(TestMockImageSyncImageCopyRequest, Cancel1) {
-  ASSERT_EQ(0, create_snap("snap1"));
-  m_client_meta.sync_points = {{cls::rbd::UserSnapshotNamespace(), "snap1", boost::none}};
-
-  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-  journal::MockJournaler mock_journaler;
-  MockObjectCopyRequest mock_object_copy_request;
-
-  C_SaferCond ctx;
-  MockImageCopyRequest *request = create_request(mock_remote_image_ctx,
-                                                 mock_local_image_ctx,
-                                                 mock_journaler,
-                                                 m_client_meta.sync_points.front(),
-                                                 &ctx);
-
-  expect_get_snap_id(mock_remote_image_ctx);
-
-  InSequence seq;
-  expect_get_object_count(mock_remote_image_ctx, 1);
-  expect_get_object_count(mock_remote_image_ctx, 0);
-  EXPECT_CALL(mock_journaler, update_client(_, _))
-    .WillOnce(DoAll(InvokeWithoutArgs([request]() {
-           request->cancel();
-         }),
-       WithArg<1>(CompleteContext(0))));
-
-  request->send();
-  ASSERT_EQ(-ECANCELED, ctx.wait());
-}
-
-TEST_F(TestMockImageSyncImageCopyRequest, MissingSnap) {
-  ASSERT_EQ(0, create_snap("snap1"));
-  m_client_meta.sync_points = {{cls::rbd::UserSnapshotNamespace(), "missing-snap", boost::none}};
-
-  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-  journal::MockJournaler mock_journaler;
-
-  expect_get_snap_id(mock_remote_image_ctx);
-
-  C_SaferCond ctx;
-  MockImageCopyRequest *request = create_request(mock_remote_image_ctx,
-                                                 mock_local_image_ctx,
-                                                 mock_journaler,
-                                                 m_client_meta.sync_points.front(),
-                                                 &ctx);
-  request->send();
-  ASSERT_EQ(-ENOENT, ctx.wait());
-}
-
-TEST_F(TestMockImageSyncImageCopyRequest, MissingFromSnap) {
-  ASSERT_EQ(0, create_snap("snap1"));
-  m_client_meta.sync_points = {{cls::rbd::UserSnapshotNamespace(),
-                               "snap1",
-                               "missing-snap",
-                               boost::none}};
-
-  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-  journal::MockJournaler mock_journaler;
-
-  expect_get_snap_id(mock_remote_image_ctx);
-
-  C_SaferCond ctx;
-  MockImageCopyRequest *request = create_request(mock_remote_image_ctx,
-                                                 mock_local_image_ctx,
-                                                 mock_journaler,
-                                                 m_client_meta.sync_points.front(),
-                                                 &ctx);
-  request->send();
-  ASSERT_EQ(-ENOENT, ctx.wait());
-}
-
-TEST_F(TestMockImageSyncImageCopyRequest, EmptySnapMap) {
-  ASSERT_EQ(0, create_snap("snap1"));
-  ASSERT_EQ(0, create_snap("snap2"));
-  m_client_meta.snap_seqs = {{0, 0}};
-  m_client_meta.sync_points = {{cls::rbd::UserSnapshotNamespace(),
-                               "snap2",
-                               "snap1",
-                               boost::none}};
-
-  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-  journal::MockJournaler mock_journaler;
-
-  expect_get_snap_id(mock_remote_image_ctx);
-
-  C_SaferCond ctx;
-  MockImageCopyRequest *request = create_request(mock_remote_image_ctx,
-                                                 mock_local_image_ctx,
-                                                 mock_journaler,
-                                                 m_client_meta.sync_points.front(),
-                                                 &ctx);
-  request->send();
-  ASSERT_EQ(-EINVAL, ctx.wait());
-}
-
-TEST_F(TestMockImageSyncImageCopyRequest, EmptySnapSeqs) {
-  ASSERT_EQ(0, create_snap("snap1"));
-  ASSERT_EQ(0, create_snap("snap2"));
-  m_client_meta.snap_seqs = {};
-  m_client_meta.sync_points = {{cls::rbd::UserSnapshotNamespace(),
-                               "snap2",
-                               "snap1",
-                               boost::none}};
-
-  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-  journal::MockJournaler mock_journaler;
-
-  expect_get_snap_id(mock_remote_image_ctx);
-
-  C_SaferCond ctx;
-  MockImageCopyRequest *request = create_request(mock_remote_image_ctx,
-                                                 mock_local_image_ctx,
-                                                 mock_journaler,
-                                                 m_client_meta.sync_points.front(),
-                                                 &ctx);
-  request->send();
-  ASSERT_EQ(-EINVAL, ctx.wait());
-}
-
-} // namespace image_sync
-} // namespace mirror
-} // namespace rbd
diff --git a/src/test/rbd_mirror/image_sync/test_mock_MetadataCopyRequest.cc b/src/test/rbd_mirror/image_sync/test_mock_MetadataCopyRequest.cc
deleted file mode 100644 (file)
index 35e663f..0000000
+++ /dev/null
@@ -1,176 +0,0 @@
-// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
-// vim: ts=8 sw=2 smarttab
-
-#include "test/rbd_mirror/test_mock_fixture.h"
-#include "include/rbd/librbd.hpp"
-#include "include/stringify.h"
-#include "librbd/ImageCtx.h"
-#include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
-#include "test/librbd/mock/MockImageCtx.h"
-#include "tools/rbd_mirror/image_sync/MetadataCopyRequest.h"
-#include <map>
-
-namespace librbd {
-namespace {
-
-struct MockTestImageCtx : public librbd::MockImageCtx {
-  MockTestImageCtx(librbd::ImageCtx &image_ctx)
-    : librbd::MockImageCtx(image_ctx) {
-  }
-};
-
-} // anonymous namespace
-} // namespace librbd
-
-// template definitions
-#include "tools/rbd_mirror/image_sync/MetadataCopyRequest.cc"
-
-namespace rbd {
-namespace mirror {
-namespace image_sync {
-
-using ::testing::_;
-using ::testing::DoAll;
-using ::testing::InSequence;
-using ::testing::Return;
-using ::testing::StrEq;
-using ::testing::WithArg;
-
-class TestMockImageSyncMetadataCopyRequest : public TestMockFixture {
-public:
-  typedef MetadataCopyRequest<librbd::MockTestImageCtx> MockMetadataCopyRequest;
-  typedef std::map<std::string, bufferlist> Metadata;
-
-  void SetUp() override {
-    TestMockFixture::SetUp();
-
-    librbd::RBD rbd;
-    ASSERT_EQ(0, create_image(rbd, m_remote_io_ctx, m_image_name, m_image_size));
-    ASSERT_EQ(0, open_image(m_remote_io_ctx, m_image_name, &m_remote_image_ctx));
-
-    ASSERT_EQ(0, create_image(rbd, m_local_io_ctx, m_image_name, m_image_size));
-    ASSERT_EQ(0, open_image(m_local_io_ctx, m_image_name, &m_local_image_ctx));
-  }
-
-  void expect_metadata_list(librbd::MockTestImageCtx &mock_image_ctx,
-                            const Metadata& metadata, int r) {
-    bufferlist out_bl;
-    ::encode(metadata, out_bl);
-
-    EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
-                exec(mock_image_ctx.header_oid, _, StrEq("rbd"),
-                     StrEq("metadata_list"), _, _, _))
-                  .WillOnce(DoAll(WithArg<5>(CopyInBufferlist(out_bl)),
-                                  Return(r)));
-  }
-
-  void expect_metadata_set(librbd::MockTestImageCtx &mock_image_ctx,
-                           const Metadata& metadata, int r) {
-    bufferlist in_bl;
-    ::encode(metadata, in_bl);
-
-    EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
-                exec(mock_image_ctx.header_oid, _, StrEq("rbd"),
-                     StrEq("metadata_set"), ContentsEqual(in_bl), _, _))
-                  .WillOnce(Return(r));
-  }
-
-  librbd::ImageCtx *m_remote_image_ctx;
-  librbd::ImageCtx *m_local_image_ctx;
-};
-
-TEST_F(TestMockImageSyncMetadataCopyRequest, Success) {
-  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-
-  size_t idx = 1;
-  Metadata key_values_1;
-  for (; idx <= 128; ++idx) {
-    bufferlist bl;
-    bl.append("value" + stringify(idx));
-    key_values_1.emplace("key" + stringify(idx), bl);
-  }
-
-  Metadata key_values_2;
-  for (; idx <= 255; ++idx) {
-    bufferlist bl;
-    bl.append("value" + stringify(idx));
-    key_values_2.emplace("key" + stringify(idx), bl);
-  }
-
-  InSequence seq;
-  expect_metadata_list(mock_remote_image_ctx, key_values_1, 0);
-  expect_metadata_set(mock_local_image_ctx, key_values_1, 0);
-  expect_metadata_list(mock_remote_image_ctx, key_values_2, 0);
-  expect_metadata_set(mock_local_image_ctx, key_values_2, 0);
-
-  C_SaferCond ctx;
-  auto request = MockMetadataCopyRequest::create(&mock_local_image_ctx,
-                                                 &mock_remote_image_ctx,
-                                                 &ctx);
-  request->send();
-
-  ASSERT_EQ(0, ctx.wait());
-}
-
-TEST_F(TestMockImageSyncMetadataCopyRequest, Empty) {
-  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-
-  Metadata key_values;
-
-  InSequence seq;
-  expect_metadata_list(mock_remote_image_ctx, key_values, 0);
-
-  C_SaferCond ctx;
-  auto request = MockMetadataCopyRequest::create(&mock_local_image_ctx,
-                                                 &mock_remote_image_ctx,
-                                                 &ctx);
-  request->send();
-
-  ASSERT_EQ(0, ctx.wait());
-}
-
-TEST_F(TestMockImageSyncMetadataCopyRequest, MetadataListError) {
-  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-
-  Metadata key_values;
-
-  InSequence seq;
-  expect_metadata_list(mock_remote_image_ctx, key_values, -EINVAL);
-
-  C_SaferCond ctx;
-  auto request = MockMetadataCopyRequest::create(&mock_local_image_ctx,
-                                                 &mock_remote_image_ctx,
-                                                 &ctx);
-  request->send();
-
-  ASSERT_EQ(-EINVAL, ctx.wait());
-}
-
-TEST_F(TestMockImageSyncMetadataCopyRequest, MetadataSetError) {
-  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-
-  Metadata key_values;
-  bufferlist bl;
-  bl.append("value");
-  key_values.emplace("key", bl);
-
-  InSequence seq;
-  expect_metadata_list(mock_remote_image_ctx, key_values, 0);
-  expect_metadata_set(mock_local_image_ctx, key_values, -EINVAL);
-
-  C_SaferCond ctx;
-  auto request = MockMetadataCopyRequest::create(&mock_local_image_ctx,
-                                                 &mock_remote_image_ctx,
-                                                 &ctx);
-  request->send();
-
-  ASSERT_EQ(-EINVAL, ctx.wait());
-}
-
-} // namespace image_sync
-} // namespace mirror
-} // namespace rbd
diff --git a/src/test/rbd_mirror/image_sync/test_mock_ObjectCopyRequest.cc b/src/test/rbd_mirror/image_sync/test_mock_ObjectCopyRequest.cc
deleted file mode 100644 (file)
index f70df5c..0000000
+++ /dev/null
@@ -1,759 +0,0 @@
-// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
-// vim: ts=8 sw=2 smarttab
-
-#include "test/rbd_mirror/test_mock_fixture.h"
-#include "include/interval_set.h"
-#include "include/rbd/librbd.hpp"
-#include "include/rbd/object_map_types.h"
-#include "librbd/ImageCtx.h"
-#include "librbd/ImageState.h"
-#include "librbd/internal.h"
-#include "librbd/Operations.h"
-#include "librbd/io/ImageRequestWQ.h"
-#include "librbd/io/ReadResult.h"
-#include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
-#include "test/librbd/mock/MockImageCtx.h"
-#include "tools/rbd_mirror/Threads.h"
-#include "tools/rbd_mirror/image_sync/ObjectCopyRequest.h"
-
-namespace librbd {
-namespace {
-
-struct MockTestImageCtx : public librbd::MockImageCtx {
-  MockTestImageCtx(librbd::ImageCtx &image_ctx)
-    : librbd::MockImageCtx(image_ctx) {
-  }
-};
-
-} // anonymous namespace
-} // namespace librbd
-
-// template definitions
-#include "tools/rbd_mirror/image_sync/ObjectCopyRequest.cc"
-template class rbd::mirror::image_sync::ObjectCopyRequest<librbd::MockTestImageCtx>;
-
-bool operator==(const SnapContext& rhs, const SnapContext& lhs) {
-  return (rhs.seq == lhs.seq && rhs.snaps == lhs.snaps);
-}
-
-namespace rbd {
-namespace mirror {
-namespace image_sync {
-
-using ::testing::_;
-using ::testing::DoAll;
-using ::testing::DoDefault;
-using ::testing::InSequence;
-using ::testing::Invoke;
-using ::testing::Return;
-using ::testing::ReturnNew;
-using ::testing::WithArg;
-
-namespace {
-
-void scribble(librbd::ImageCtx *image_ctx, int num_ops, size_t max_size,
-              interval_set<uint64_t> *what)
-{
-  uint64_t object_size = 1 << image_ctx->order;
-  for (int i=0; i<num_ops; i++) {
-    uint64_t off = rand() % (object_size - max_size + 1);
-    uint64_t len = 1 + rand() % max_size;
-
-    bufferlist bl;
-    bl.append(std::string(len, '1'));
-
-    int r = image_ctx->io_work_queue->write(off, len, std::move(bl), 0);
-    ASSERT_EQ(static_cast<int>(len), r);
-
-    interval_set<uint64_t> w;
-    w.insert(off, len);
-    what->union_of(w);
-  }
-  std::cout << " wrote " << *what << std::endl;
-}
-
-} // anonymous namespace
-
-class TestMockImageSyncObjectCopyRequest : public TestMockFixture {
-public:
-  typedef ObjectCopyRequest<librbd::MockTestImageCtx> MockObjectCopyRequest;
-
-  void SetUp() override {
-    TestMockFixture::SetUp();
-
-    librbd::RBD rbd;
-    ASSERT_EQ(0, create_image(rbd, m_remote_io_ctx, m_image_name, m_image_size));
-    ASSERT_EQ(0, open_image(m_remote_io_ctx, m_image_name, &m_remote_image_ctx));
-
-    ASSERT_EQ(0, create_image(rbd, m_local_io_ctx, m_image_name, m_image_size));
-    ASSERT_EQ(0, open_image(m_local_io_ctx, m_image_name, &m_local_image_ctx));
-  }
-
-  void expect_start_op(librbd::MockExclusiveLock &mock_exclusive_lock) {
-    EXPECT_CALL(mock_exclusive_lock, start_op()).WillOnce(
-      ReturnNew<FunctionContext>([](int) {}));
-  }
-
-  void expect_list_snaps(librbd::MockTestImageCtx &mock_image_ctx,
-                         librados::MockTestMemIoCtxImpl &mock_io_ctx,
-                         const librados::snap_set_t &snap_set) {
-    expect_set_snap_read(mock_io_ctx, CEPH_SNAPDIR);
-    EXPECT_CALL(mock_io_ctx,
-                list_snaps(mock_image_ctx.image_ctx->get_object_name(0), _))
-      .WillOnce(DoAll(WithArg<1>(Invoke([&snap_set](librados::snap_set_t *out_snap_set) {
-                          *out_snap_set = snap_set;
-                        })),
-                      Return(0)));
-  }
-
-  void expect_list_snaps(librbd::MockTestImageCtx &mock_image_ctx,
-                         librados::MockTestMemIoCtxImpl &mock_io_ctx, int r) {
-    expect_set_snap_read(mock_io_ctx, CEPH_SNAPDIR);
-    auto &expect = EXPECT_CALL(mock_io_ctx,
-                               list_snaps(mock_image_ctx.image_ctx->get_object_name(0),
-                                          _));
-    if (r < 0) {
-      expect.WillOnce(Return(r));
-    } else {
-      expect.WillOnce(DoDefault());
-    }
-  }
-
-  void expect_get_object_name(librbd::MockTestImageCtx &mock_image_ctx) {
-    EXPECT_CALL(mock_image_ctx, get_object_name(0))
-                  .WillOnce(Return(mock_image_ctx.image_ctx->get_object_name(0)));
-  }
-
-  MockObjectCopyRequest *create_request(librbd::MockTestImageCtx &mock_remote_image_ctx,
-                                        librbd::MockTestImageCtx &mock_local_image_ctx,
-                                        Context *on_finish) {
-    expect_get_object_name(mock_local_image_ctx);
-    expect_get_object_name(mock_remote_image_ctx);
-    return new MockObjectCopyRequest(&mock_local_image_ctx,
-                                     &mock_remote_image_ctx, &m_snap_map,
-                                     0, on_finish);
-  }
-
-  void expect_set_snap_read(librados::MockTestMemIoCtxImpl &mock_io_ctx,
-                            uint64_t snap_id) {
-    EXPECT_CALL(mock_io_ctx, set_snap_read(snap_id));
-  }
-
-  void expect_sparse_read(librados::MockTestMemIoCtxImpl &mock_io_ctx, uint64_t offset,
-                          uint64_t length, int r) {
-
-    auto &expect = EXPECT_CALL(mock_io_ctx, sparse_read(_, offset, length, _, _));
-    if (r < 0) {
-      expect.WillOnce(Return(r));
-    } else {
-      expect.WillOnce(DoDefault());
-    }
-  }
-
-  void expect_sparse_read(librados::MockTestMemIoCtxImpl &mock_io_ctx,
-                   const interval_set<uint64_t> &extents, int r) {
-    for (auto extent : extents) {
-      expect_sparse_read(mock_io_ctx, extent.first, extent.second, r);
-      if (r < 0) {
-        break;
-      }
-    }
-  }
-
-  void expect_write(librados::MockTestMemIoCtxImpl &mock_io_ctx,
-                    uint64_t offset, uint64_t length,
-                    const SnapContext &snapc, int r) {
-    auto &expect = EXPECT_CALL(mock_io_ctx, write(_, _, length, offset, snapc));
-    if (r < 0) {
-      expect.WillOnce(Return(r));
-    } else {
-      expect.WillOnce(DoDefault());
-    }
-  }
-
-  void expect_write(librados::MockTestMemIoCtxImpl &mock_io_ctx,
-                    const interval_set<uint64_t> &extents,
-                    const SnapContext &snapc, int r) {
-    for (auto extent : extents) {
-      expect_write(mock_io_ctx, extent.first, extent.second, snapc, r);
-      if (r < 0) {
-        break;
-      }
-    }
-  }
-
-  void expect_truncate(librados::MockTestMemIoCtxImpl &mock_io_ctx,
-                       uint64_t offset, int r) {
-    auto &expect = EXPECT_CALL(mock_io_ctx, truncate(_, offset, _));
-    if (r < 0) {
-      expect.WillOnce(Return(r));
-    } else {
-      expect.WillOnce(DoDefault());
-    }
-  }
-
-  void expect_remove(librados::MockTestMemIoCtxImpl &mock_io_ctx, int r) {
-    auto &expect = EXPECT_CALL(mock_io_ctx, remove(_, _));
-    if (r < 0) {
-      expect.WillOnce(Return(r));
-    } else {
-      expect.WillOnce(DoDefault());
-    }
-  }
-
-  void expect_update_object_map(librbd::MockTestImageCtx &mock_image_ctx,
-                                librbd::MockObjectMap &mock_object_map,
-                                librados::snap_t snap_id, uint8_t state,
-                                int r) {
-    if (mock_image_ctx.image_ctx->object_map != nullptr) {
-      auto &expect = EXPECT_CALL(mock_object_map, aio_update(snap_id, 0, 1, state, _, _, _));
-      if (r < 0) {
-        expect.WillOnce(DoAll(WithArg<6>(Invoke([this, r](Context *ctx) {
-                                  m_threads->work_queue->queue(ctx, r);
-                                })),
-                              Return(true)));
-      } else {
-        expect.WillOnce(DoAll(WithArg<6>(Invoke([&mock_image_ctx, snap_id, state, r](Context *ctx) {
-                                  assert(mock_image_ctx.image_ctx->snap_lock.is_locked());
-                                  assert(mock_image_ctx.image_ctx->object_map_lock.is_wlocked());
-                                  mock_image_ctx.image_ctx->object_map->aio_update<Context>(
-                                    snap_id, 0, 1, state, boost::none, {}, ctx);
-                                })),
-                              Return(true)));
-      }
-    }
-  }
-
-  using TestFixture::create_snap;
-  int create_snap(const char* snap_name) {
-    librados::snap_t remote_snap_id;
-    int r = create_snap(m_remote_image_ctx, snap_name, &remote_snap_id);
-    if (r < 0) {
-      return r;
-    }
-
-    librados::snap_t local_snap_id;
-    r = create_snap(m_local_image_ctx, snap_name, &local_snap_id);
-    if (r < 0) {
-      return r;
-    }
-
-    // collection of all existing snaps in local image
-    MockObjectCopyRequest::SnapIds local_snap_ids({local_snap_id});
-    if (!m_snap_map.empty()) {
-      local_snap_ids.insert(local_snap_ids.end(),
-                            m_snap_map.rbegin()->second.begin(),
-                            m_snap_map.rbegin()->second.end());
-    }
-    m_snap_map[remote_snap_id] = local_snap_ids;
-    m_remote_snap_ids.push_back(remote_snap_id);
-    m_local_snap_ids.push_back(local_snap_id);
-
-    return 0;
-  }
-
-  std::string get_snap_name(librbd::ImageCtx *image_ctx,
-                            librados::snap_t snap_id) {
-    auto it = std::find_if(image_ctx->snap_ids.begin(),
-                           image_ctx->snap_ids.end(),
-                           [snap_id](const std::pair<std::pair<cls::rbd::SnapshotNamespace,
-                                                              std::string>,
-                                                    librados::snap_t> &pair) {
-        return (pair.second == snap_id);
-      });
-    if (it == image_ctx->snap_ids.end()) {
-      return "";
-    }
-    return it->first.second;
-  }
-
-  int compare_objects() {
-    MockObjectCopyRequest::SnapMap snap_map(m_snap_map);
-    if (snap_map.empty()) {
-      return -ENOENT;
-    }
-
-    int r;
-    uint64_t object_size = 1 << m_remote_image_ctx->order;
-    while (!snap_map.empty()) {
-      librados::snap_t remote_snap_id = snap_map.begin()->first;
-      librados::snap_t local_snap_id = *snap_map.begin()->second.begin();
-      snap_map.erase(snap_map.begin());
-
-      std::string snap_name = get_snap_name(m_remote_image_ctx, remote_snap_id);
-      if (snap_name.empty()) {
-        return -ENOENT;
-      }
-
-      std::cout << "comparing '" << snap_name << " (" << remote_snap_id
-                << " to " << local_snap_id << ")" << std::endl;
-
-      r = librbd::snap_set(m_remote_image_ctx,
-                          cls::rbd::UserSnapshotNamespace(),
-                          snap_name.c_str());
-      if (r < 0) {
-        return r;
-      }
-
-      r = librbd::snap_set(m_local_image_ctx,
-                          cls::rbd::UserSnapshotNamespace(),
-                          snap_name.c_str());
-      if (r < 0) {
-        return r;
-      }
-
-      bufferlist remote_bl;
-      remote_bl.append(std::string(object_size, '1'));
-      r = m_remote_image_ctx->io_work_queue->read(
-        0, object_size, librbd::io::ReadResult{&remote_bl}, 0);
-      if (r < 0) {
-        return r;
-      }
-
-      bufferlist local_bl;
-      local_bl.append(std::string(object_size, '1'));
-      r = m_local_image_ctx->io_work_queue->read(
-        0, object_size, librbd::io::ReadResult{&local_bl}, 0);
-      if (r < 0) {
-        return r;
-      }
-
-      if (!remote_bl.contents_equal(local_bl)) {
-        return -EBADMSG;
-      }
-    }
-
-    r = librbd::snap_set(m_remote_image_ctx,
-                        cls::rbd::UserSnapshotNamespace(),
-                        nullptr);
-    if (r < 0) {
-      return r;
-    }
-    r = librbd::snap_set(m_local_image_ctx,
-                        cls::rbd::UserSnapshotNamespace(),
-                        nullptr);
-    if (r < 0) {
-      return r;
-    }
-
-    return 0;
-  }
-
-  librbd::ImageCtx *m_remote_image_ctx;
-  librbd::ImageCtx *m_local_image_ctx;
-
-  MockObjectCopyRequest::SnapMap m_snap_map;
-  std::vector<librados::snap_t> m_remote_snap_ids;
-  std::vector<librados::snap_t> m_local_snap_ids;
-};
-
-TEST_F(TestMockImageSyncObjectCopyRequest, DNE) {
-  ASSERT_EQ(0, create_snap("sync"));
-  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-
-  librbd::MockExclusiveLock mock_exclusive_lock;
-  mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
-
-  librbd::MockObjectMap mock_object_map;
-  mock_local_image_ctx.object_map = &mock_object_map;
-  expect_test_features(mock_local_image_ctx);
-
-  C_SaferCond ctx;
-  MockObjectCopyRequest *request = create_request(mock_remote_image_ctx,
-                                                  mock_local_image_ctx, &ctx);
-
-  librados::MockTestMemIoCtxImpl &mock_remote_io_ctx(get_mock_io_ctx(
-    request->get_remote_io_ctx()));
-
-  InSequence seq;
-  expect_list_snaps(mock_remote_image_ctx, mock_remote_io_ctx, -ENOENT);
-
-  request->send();
-  ASSERT_EQ(0, ctx.wait());
-}
-
-TEST_F(TestMockImageSyncObjectCopyRequest, Write) {
-  // scribble some data
-  interval_set<uint64_t> one;
-  scribble(m_remote_image_ctx, 10, 102400, &one);
-
-  ASSERT_EQ(0, create_snap("sync"));
-  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-
-  librbd::MockExclusiveLock mock_exclusive_lock;
-  mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
-
-  librbd::MockObjectMap mock_object_map;
-  mock_local_image_ctx.object_map = &mock_object_map;
-
-  expect_test_features(mock_local_image_ctx);
-
-  C_SaferCond ctx;
-  MockObjectCopyRequest *request = create_request(mock_remote_image_ctx,
-                                                  mock_local_image_ctx, &ctx);
-
-  librados::MockTestMemIoCtxImpl &mock_remote_io_ctx(get_mock_io_ctx(
-    request->get_remote_io_ctx()));
-  librados::MockTestMemIoCtxImpl &mock_local_io_ctx(get_mock_io_ctx(
-    request->get_local_io_ctx()));
-
-  InSequence seq;
-  expect_list_snaps(mock_remote_image_ctx, mock_remote_io_ctx, 0);
-  expect_set_snap_read(mock_remote_io_ctx, m_remote_snap_ids[0]);
-  expect_sparse_read(mock_remote_io_ctx, 0, one.range_end(), 0);
-  expect_start_op(mock_exclusive_lock);
-  expect_write(mock_local_io_ctx, 0, one.range_end(), {0, {}}, 0);
-  expect_start_op(mock_exclusive_lock);
-  expect_update_object_map(mock_local_image_ctx, mock_object_map,
-                           m_local_snap_ids[0], OBJECT_EXISTS, 0);
-
-  request->send();
-  ASSERT_EQ(0, ctx.wait());
-  ASSERT_EQ(0, compare_objects());
-}
-
-TEST_F(TestMockImageSyncObjectCopyRequest, ReadMissingStaleSnapSet) {
-  ASSERT_EQ(0, create_snap("one"));
-  ASSERT_EQ(0, create_snap("two"));
-
-  // scribble some data
-  interval_set<uint64_t> one;
-  scribble(m_remote_image_ctx, 10, 102400, &one);
-  ASSERT_EQ(0, create_snap("three"));
-
-  ASSERT_EQ(0, create_snap("sync"));
-  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-
-  librbd::MockExclusiveLock mock_exclusive_lock;
-  mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
-
-  librbd::MockObjectMap mock_object_map;
-  mock_local_image_ctx.object_map = &mock_object_map;
-
-  expect_test_features(mock_local_image_ctx);
-
-  C_SaferCond ctx;
-  MockObjectCopyRequest *request = create_request(mock_remote_image_ctx,
-                                                  mock_local_image_ctx, &ctx);
-
-  librados::MockTestMemIoCtxImpl &mock_remote_io_ctx(get_mock_io_ctx(
-    request->get_remote_io_ctx()));
-  librados::MockTestMemIoCtxImpl &mock_local_io_ctx(get_mock_io_ctx(
-    request->get_local_io_ctx()));
-
-  librados::clone_info_t dummy_clone_info;
-  dummy_clone_info.cloneid = librados::SNAP_HEAD;
-  dummy_clone_info.size = 123;
-
-  librados::snap_set_t dummy_snap_set1;
-  dummy_snap_set1.clones.push_back(dummy_clone_info);
-
-  dummy_clone_info.size = 234;
-  librados::snap_set_t dummy_snap_set2;
-  dummy_snap_set2.clones.push_back(dummy_clone_info);
-
-  InSequence seq;
-  expect_list_snaps(mock_remote_image_ctx, mock_remote_io_ctx, dummy_snap_set1);
-  expect_set_snap_read(mock_remote_io_ctx, m_remote_snap_ids[3]);
-  expect_sparse_read(mock_remote_io_ctx, 0, 123, -ENOENT);
-  expect_list_snaps(mock_remote_image_ctx, mock_remote_io_ctx, dummy_snap_set2);
-  expect_set_snap_read(mock_remote_io_ctx, m_remote_snap_ids[3]);
-  expect_sparse_read(mock_remote_io_ctx, 0, 234, -ENOENT);
-  expect_list_snaps(mock_remote_image_ctx, mock_remote_io_ctx, 0);
-  expect_set_snap_read(mock_remote_io_ctx, m_remote_snap_ids[3]);
-  expect_sparse_read(mock_remote_io_ctx, 0, one.range_end(), 0);
-  expect_start_op(mock_exclusive_lock);
-  expect_write(mock_local_io_ctx, 0, one.range_end(),
-               {m_local_snap_ids[1], {m_local_snap_ids[1],
-                                      m_local_snap_ids[0]}},
-                0);
-  expect_start_op(mock_exclusive_lock);
-  expect_update_object_map(mock_local_image_ctx, mock_object_map,
-                           m_local_snap_ids[2], OBJECT_EXISTS, 0);
-  expect_start_op(mock_exclusive_lock);
-  expect_update_object_map(mock_local_image_ctx, mock_object_map,
-                           m_local_snap_ids[3], OBJECT_EXISTS_CLEAN, 0);
-
-  request->send();
-  ASSERT_EQ(0, ctx.wait());
-  ASSERT_EQ(0, compare_objects());
-}
-
-TEST_F(TestMockImageSyncObjectCopyRequest, ReadMissingUpToDateSnapMap) {
-  // scribble some data
-  interval_set<uint64_t> one;
-  scribble(m_remote_image_ctx, 10, 102400, &one);
-
-  ASSERT_EQ(0, create_snap("sync"));
-  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-
-  librbd::MockExclusiveLock mock_exclusive_lock;
-  mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
-
-  librbd::MockObjectMap mock_object_map;
-  mock_local_image_ctx.object_map = &mock_object_map;
-
-  expect_test_features(mock_local_image_ctx);
-
-  C_SaferCond ctx;
-  MockObjectCopyRequest *request = create_request(mock_remote_image_ctx,
-                                                  mock_local_image_ctx, &ctx);
-
-  librados::MockTestMemIoCtxImpl &mock_remote_io_ctx(get_mock_io_ctx(
-    request->get_remote_io_ctx()));
-
-  InSequence seq;
-  expect_list_snaps(mock_remote_image_ctx, mock_remote_io_ctx, 0);
-  expect_set_snap_read(mock_remote_io_ctx, m_remote_snap_ids[0]);
-  expect_sparse_read(mock_remote_io_ctx, 0, one.range_end(), -ENOENT);
-  expect_list_snaps(mock_remote_image_ctx, mock_remote_io_ctx, 0);
-
-  request->send();
-  ASSERT_EQ(-ENOENT, ctx.wait());
-}
-
-TEST_F(TestMockImageSyncObjectCopyRequest, ReadError) {
-  // scribble some data
-  interval_set<uint64_t> one;
-  scribble(m_remote_image_ctx, 10, 102400, &one);
-
-  ASSERT_EQ(0, create_snap("sync"));
-  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-
-  librbd::MockExclusiveLock mock_exclusive_lock;
-  mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
-
-  librbd::MockObjectMap mock_object_map;
-  mock_local_image_ctx.object_map = &mock_object_map;
-
-  expect_test_features(mock_local_image_ctx);
-
-  C_SaferCond ctx;
-  MockObjectCopyRequest *request = create_request(mock_remote_image_ctx,
-                                                  mock_local_image_ctx, &ctx);
-
-  librados::MockTestMemIoCtxImpl &mock_remote_io_ctx(get_mock_io_ctx(
-    request->get_remote_io_ctx()));
-
-  InSequence seq;
-  expect_list_snaps(mock_remote_image_ctx, mock_remote_io_ctx, 0);
-  expect_set_snap_read(mock_remote_io_ctx, m_remote_snap_ids[0]);
-  expect_sparse_read(mock_remote_io_ctx, 0, one.range_end(),  -EINVAL);
-
-  request->send();
-  ASSERT_EQ(-EINVAL, ctx.wait());
-}
-
-TEST_F(TestMockImageSyncObjectCopyRequest, WriteError) {
-  // scribble some data
-  interval_set<uint64_t> one;
-  scribble(m_remote_image_ctx, 10, 102400, &one);
-
-  ASSERT_EQ(0, create_snap("sync"));
-  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-
-  librbd::MockExclusiveLock mock_exclusive_lock;
-  mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
-
-  librbd::MockObjectMap mock_object_map;
-  mock_local_image_ctx.object_map = &mock_object_map;
-
-  expect_test_features(mock_local_image_ctx);
-
-  C_SaferCond ctx;
-  MockObjectCopyRequest *request = create_request(mock_remote_image_ctx,
-                                                  mock_local_image_ctx, &ctx);
-
-  librados::MockTestMemIoCtxImpl &mock_remote_io_ctx(get_mock_io_ctx(
-    request->get_remote_io_ctx()));
-  librados::MockTestMemIoCtxImpl &mock_local_io_ctx(get_mock_io_ctx(
-    request->get_local_io_ctx()));
-
-  InSequence seq;
-  expect_list_snaps(mock_remote_image_ctx, mock_remote_io_ctx, 0);
-  expect_set_snap_read(mock_remote_io_ctx, m_remote_snap_ids[0]);
-  expect_sparse_read(mock_remote_io_ctx, 0, one.range_end(), 0);
-  expect_start_op(mock_exclusive_lock);
-  expect_write(mock_local_io_ctx, 0, one.range_end(), {0, {}}, -EINVAL);
-
-  request->send();
-  ASSERT_EQ(-EINVAL, ctx.wait());
-}
-
-TEST_F(TestMockImageSyncObjectCopyRequest, WriteSnaps) {
-  // scribble some data
-  interval_set<uint64_t> one;
-  scribble(m_remote_image_ctx, 10, 102400, &one);
-  ASSERT_EQ(0, create_snap("one"));
-
-  interval_set<uint64_t> two;
-  scribble(m_remote_image_ctx, 10, 102400, &two);
-  ASSERT_EQ(0, create_snap("two"));
-
-  if (one.range_end() < two.range_end()) {
-    interval_set<uint64_t> resize_diff;
-    resize_diff.insert(one.range_end(), two.range_end() - one.range_end());
-    two.union_of(resize_diff);
-  }
-
-  ASSERT_EQ(0, create_snap("sync"));
-  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-
-  librbd::MockExclusiveLock mock_exclusive_lock;
-  mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
-
-  librbd::MockObjectMap mock_object_map;
-  mock_local_image_ctx.object_map = &mock_object_map;
-
-  expect_test_features(mock_local_image_ctx);
-
-  C_SaferCond ctx;
-  MockObjectCopyRequest *request = create_request(mock_remote_image_ctx,
-                                                  mock_local_image_ctx, &ctx);
-
-  librados::MockTestMemIoCtxImpl &mock_remote_io_ctx(get_mock_io_ctx(
-    request->get_remote_io_ctx()));
-  librados::MockTestMemIoCtxImpl &mock_local_io_ctx(get_mock_io_ctx(
-    request->get_local_io_ctx()));
-
-  InSequence seq;
-  expect_list_snaps(mock_remote_image_ctx, mock_remote_io_ctx, 0);
-  expect_set_snap_read(mock_remote_io_ctx, m_remote_snap_ids[0]);
-  expect_sparse_read(mock_remote_io_ctx, 0, one.range_end(), 0);
-  expect_start_op(mock_exclusive_lock);
-  expect_write(mock_local_io_ctx, 0, one.range_end(), {0, {}}, 0);
-  expect_set_snap_read(mock_remote_io_ctx, m_remote_snap_ids[2]);
-  expect_sparse_read(mock_remote_io_ctx, two, 0);
-  expect_start_op(mock_exclusive_lock);
-  expect_write(mock_local_io_ctx, two,
-               {m_local_snap_ids[0], {m_local_snap_ids[0]}}, 0);
-  expect_start_op(mock_exclusive_lock);
-  expect_update_object_map(mock_local_image_ctx, mock_object_map,
-                           m_local_snap_ids[0], OBJECT_EXISTS, 0);
-  expect_start_op(mock_exclusive_lock);
-  expect_update_object_map(mock_local_image_ctx, mock_object_map,
-                           m_local_snap_ids[1], OBJECT_EXISTS, 0);
-  expect_start_op(mock_exclusive_lock);
-  expect_update_object_map(mock_local_image_ctx, mock_object_map,
-                           m_local_snap_ids[2], OBJECT_EXISTS_CLEAN, 0);
-
-  request->send();
-  ASSERT_EQ(0, ctx.wait());
-  ASSERT_EQ(0, compare_objects());
-}
-
-TEST_F(TestMockImageSyncObjectCopyRequest, Trim) {
-  ASSERT_EQ(0, m_remote_image_ctx->operations->metadata_set(
-              "conf_rbd_skip_partial_discard", "false"));
-  // scribble some data
-  interval_set<uint64_t> one;
-  scribble(m_remote_image_ctx, 10, 102400, &one);
-  ASSERT_EQ(0, create_snap("one"));
-
-  // trim the object
-  uint64_t trim_offset = rand() % one.range_end();
-  ASSERT_LE(0, m_remote_image_ctx->io_work_queue->discard(
-    trim_offset, one.range_end() - trim_offset, m_remote_image_ctx->skip_partial_discard));
-  ASSERT_EQ(0, create_snap("sync"));
-
-  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-
-  librbd::MockExclusiveLock mock_exclusive_lock;
-  mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
-
-  librbd::MockObjectMap mock_object_map;
-  mock_local_image_ctx.object_map = &mock_object_map;
-
-  expect_test_features(mock_local_image_ctx);
-
-  C_SaferCond ctx;
-  MockObjectCopyRequest *request = create_request(mock_remote_image_ctx,
-                                                  mock_local_image_ctx, &ctx);
-
-  librados::MockTestMemIoCtxImpl &mock_remote_io_ctx(get_mock_io_ctx(
-    request->get_remote_io_ctx()));
-  librados::MockTestMemIoCtxImpl &mock_local_io_ctx(get_mock_io_ctx(
-    request->get_local_io_ctx()));
-
-  InSequence seq;
-  expect_list_snaps(mock_remote_image_ctx, mock_remote_io_ctx, 0);
-  expect_set_snap_read(mock_remote_io_ctx, m_remote_snap_ids[0]);
-  expect_sparse_read(mock_remote_io_ctx, 0, one.range_end(), 0);
-  expect_start_op(mock_exclusive_lock);
-  expect_write(mock_local_io_ctx, 0, one.range_end(), {0, {}}, 0);
-  expect_start_op(mock_exclusive_lock);
-  expect_truncate(mock_local_io_ctx, trim_offset, 0);
-  expect_start_op(mock_exclusive_lock);
-  expect_update_object_map(mock_local_image_ctx, mock_object_map,
-                           m_local_snap_ids[0], OBJECT_EXISTS, 0);
-  expect_start_op(mock_exclusive_lock);
-  expect_update_object_map(mock_local_image_ctx, mock_object_map,
-                           m_local_snap_ids[1], OBJECT_EXISTS, 0);
-
-  request->send();
-  ASSERT_EQ(0, ctx.wait());
-  ASSERT_EQ(0, compare_objects());
-}
-
-TEST_F(TestMockImageSyncObjectCopyRequest, Remove) {
-  // scribble some data
-  interval_set<uint64_t> one;
-  scribble(m_remote_image_ctx, 10, 102400, &one);
-  ASSERT_EQ(0, create_snap("one"));
-  ASSERT_EQ(0, create_snap("two"));
-
-  // remove the object
-  uint64_t object_size = 1 << m_remote_image_ctx->order;
-  ASSERT_LE(0, m_remote_image_ctx->io_work_queue->discard(0, object_size, m_remote_image_ctx->skip_partial_discard));
-  ASSERT_EQ(0, create_snap("sync"));
-  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-
-  librbd::MockExclusiveLock mock_exclusive_lock;
-  mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
-
-  librbd::MockObjectMap mock_object_map;
-  mock_local_image_ctx.object_map = &mock_object_map;
-
-  expect_test_features(mock_local_image_ctx);
-
-  C_SaferCond ctx;
-  MockObjectCopyRequest *request = create_request(mock_remote_image_ctx,
-                                                  mock_local_image_ctx, &ctx);
-
-  librados::MockTestMemIoCtxImpl &mock_remote_io_ctx(get_mock_io_ctx(
-    request->get_remote_io_ctx()));
-  librados::MockTestMemIoCtxImpl &mock_local_io_ctx(get_mock_io_ctx(
-    request->get_local_io_ctx()));
-
-  InSequence seq;
-  expect_list_snaps(mock_remote_image_ctx, mock_remote_io_ctx, 0);
-  expect_set_snap_read(mock_remote_io_ctx, m_remote_snap_ids[1]);
-  expect_sparse_read(mock_remote_io_ctx, 0, one.range_end(), 0);
-  expect_start_op(mock_exclusive_lock);
-  expect_write(mock_local_io_ctx, 0, one.range_end(), {0, {}}, 0);
-  expect_start_op(mock_exclusive_lock);
-  expect_remove(mock_local_io_ctx, 0);
-  expect_start_op(mock_exclusive_lock);
-  expect_update_object_map(mock_local_image_ctx, mock_object_map,
-                           m_local_snap_ids[0], OBJECT_EXISTS, 0);
-  expect_start_op(mock_exclusive_lock);
-  expect_update_object_map(mock_local_image_ctx, mock_object_map,
-                           m_local_snap_ids[1], OBJECT_EXISTS_CLEAN, 0);
-
-  request->send();
-  ASSERT_EQ(0, ctx.wait());
-  ASSERT_EQ(0, compare_objects());
-}
-
-} // namespace image_sync
-} // namespace mirror
-} // namespace rbd
diff --git a/src/test/rbd_mirror/image_sync/test_mock_SnapshotCopyRequest.cc b/src/test/rbd_mirror/image_sync/test_mock_SnapshotCopyRequest.cc
deleted file mode 100644 (file)
index 7801b66..0000000
+++ /dev/null
@@ -1,764 +0,0 @@
-// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
-// vim: ts=8 sw=2 smarttab
-
-#include "test/rbd_mirror/test_mock_fixture.h"
-#include "include/rbd/librbd.hpp"
-#include "librbd/ImageCtx.h"
-#include "librbd/ImageState.h"
-#include "librbd/Operations.h"
-#include "librbd/journal/TypeTraits.h"
-#include "test/journal/mock/MockJournaler.h"
-#include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
-#include "test/librbd/mock/MockImageCtx.h"
-#include "tools/rbd_mirror/image_sync/SnapshotCopyRequest.h"
-#include "tools/rbd_mirror/image_sync/SnapshotCreateRequest.h"
-#include "tools/rbd_mirror/Threads.h"
-
-namespace librbd {
-
-namespace {
-
-struct MockTestImageCtx : public librbd::MockImageCtx {
-  MockTestImageCtx(librbd::ImageCtx &image_ctx)
-    : librbd::MockImageCtx(image_ctx) {
-  }
-};
-
-} // anonymous namespace
-
-namespace journal {
-
-template <>
-struct TypeTraits<librbd::MockTestImageCtx> {
-  typedef ::journal::MockJournaler Journaler;
-};
-
-} // namespace journal
-} // namespace librbd
-
-namespace rbd {
-namespace mirror {
-namespace image_sync {
-
-template <>
-struct SnapshotCreateRequest<librbd::MockTestImageCtx> {
-  static SnapshotCreateRequest* s_instance;
-  static SnapshotCreateRequest* create(librbd::MockTestImageCtx* image_ctx,
-                                       const std::string &snap_name,
-                                       const cls::rbd::SnapshotNamespace &snap_namespace,
-                                       uint64_t size,
-                                       const librbd::ParentSpec &parent_spec,
-                                       uint64_t parent_overlap,
-                                       Context *on_finish) {
-    assert(s_instance != nullptr);
-    s_instance->on_finish = on_finish;
-    return s_instance;
-  }
-
-  Context *on_finish = nullptr;
-
-  SnapshotCreateRequest() {
-    s_instance = this;
-  }
-
-  MOCK_METHOD0(send, void());
-};
-
-SnapshotCreateRequest<librbd::MockTestImageCtx>* SnapshotCreateRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
-
-} // namespace image_sync
-} // namespace mirror
-} // namespace rbd
-
-// template definitions
-#include "tools/rbd_mirror/image_sync/SnapshotCopyRequest.cc"
-template class rbd::mirror::image_sync::SnapshotCopyRequest<librbd::MockTestImageCtx>;
-
-namespace rbd {
-namespace mirror {
-namespace image_sync {
-
-using ::testing::_;
-using ::testing::DoAll;
-using ::testing::DoDefault;
-using ::testing::InSequence;
-using ::testing::Invoke;
-using ::testing::InvokeWithoutArgs;
-using ::testing::Return;
-using ::testing::ReturnNew;
-using ::testing::SetArgPointee;
-using ::testing::StrEq;
-using ::testing::WithArg;
-
-class TestMockImageSyncSnapshotCopyRequest : public TestMockFixture {
-public:
-  typedef SnapshotCopyRequest<librbd::MockTestImageCtx> MockSnapshotCopyRequest;
-  typedef SnapshotCreateRequest<librbd::MockTestImageCtx> MockSnapshotCreateRequest;
-
-  void SetUp() override {
-    TestMockFixture::SetUp();
-
-    librbd::RBD rbd;
-    ASSERT_EQ(0, create_image(rbd, m_remote_io_ctx, m_image_name, m_image_size));
-    ASSERT_EQ(0, open_image(m_remote_io_ctx, m_image_name, &m_remote_image_ctx));
-
-    ASSERT_EQ(0, create_image(rbd, m_local_io_ctx, m_image_name, m_image_size));
-    ASSERT_EQ(0, open_image(m_local_io_ctx, m_image_name, &m_local_image_ctx));
-  }
-
-  void expect_start_op(librbd::MockExclusiveLock &mock_exclusive_lock) {
-    EXPECT_CALL(mock_exclusive_lock, start_op()).WillOnce(
-      ReturnNew<FunctionContext>([](int) {}));
-  }
-
-  void expect_get_snap_namespace(librbd::MockTestImageCtx &mock_image_ctx,
-                                 uint64_t snap_id) {
-    EXPECT_CALL(mock_image_ctx, get_snap_namespace(snap_id, _))
-      .WillOnce(DoAll(SetArgPointee<1>(cls::rbd::UserSnapshotNamespace()),
-                      Return(0)));
-  }
-
-  void expect_snap_create(librbd::MockTestImageCtx &mock_image_ctx,
-                          MockSnapshotCreateRequest &mock_snapshot_create_request,
-                          const std::string &snap_name, uint64_t snap_id, int r) {
-    EXPECT_CALL(mock_snapshot_create_request, send())
-      .WillOnce(DoAll(Invoke([&mock_image_ctx, snap_id, snap_name]() {
-                        inject_snap(mock_image_ctx, snap_id, snap_name);
-                      }),
-                      Invoke([this, &mock_snapshot_create_request, r]() {
-                        m_threads->work_queue->queue(mock_snapshot_create_request.on_finish, r);
-                      })));
-  }
-
-  void expect_snap_remove(librbd::MockTestImageCtx &mock_image_ctx,
-                          const std::string &snap_name, int r) {
-    EXPECT_CALL(*mock_image_ctx.operations, execute_snap_remove(_, StrEq(snap_name), _))
-                  .WillOnce(WithArg<2>(Invoke([this, r](Context *ctx) {
-                              m_threads->work_queue->queue(ctx, r);
-                            })));
-  }
-
-  void expect_snap_protect(librbd::MockTestImageCtx &mock_image_ctx,
-                           const std::string &snap_name, int r) {
-    EXPECT_CALL(*mock_image_ctx.operations, execute_snap_protect(_, StrEq(snap_name), _))
-                  .WillOnce(WithArg<2>(Invoke([this, r](Context *ctx) {
-                              m_threads->work_queue->queue(ctx, r);
-                            })));
-  }
-
-  void expect_snap_unprotect(librbd::MockTestImageCtx &mock_image_ctx,
-                             const std::string &snap_name, int r) {
-    EXPECT_CALL(*mock_image_ctx.operations, execute_snap_unprotect(_, StrEq(snap_name), _))
-                  .WillOnce(WithArg<2>(Invoke([this, r](Context *ctx) {
-                              m_threads->work_queue->queue(ctx, r);
-                            })));
-  }
-
-  void expect_snap_is_protected(librbd::MockTestImageCtx &mock_image_ctx,
-                                uint64_t snap_id, bool is_protected, int r) {
-    EXPECT_CALL(mock_image_ctx, is_snap_protected(snap_id, _))
-                  .WillOnce(DoAll(SetArgPointee<1>(is_protected),
-                                  Return(r)));
-  }
-
-  void expect_snap_is_unprotected(librbd::MockTestImageCtx &mock_image_ctx,
-                                  uint64_t snap_id, bool is_unprotected, int r) {
-    EXPECT_CALL(mock_image_ctx, is_snap_unprotected(snap_id, _))
-                  .WillOnce(DoAll(SetArgPointee<1>(is_unprotected),
-                                  Return(r)));
-  }
-
-  void expect_update_client(journal::MockJournaler &mock_journaler, int r) {
-    EXPECT_CALL(mock_journaler, update_client(_, _))
-                  .WillOnce(WithArg<1>(CompleteContext(r)));
-  }
-
-  static void inject_snap(librbd::MockTestImageCtx &mock_image_ctx,
-                          uint64_t snap_id, const std::string &snap_name) {
-    mock_image_ctx.snap_ids[{cls::rbd::UserSnapshotNamespace(),
-                            snap_name}] = snap_id;
-  }
-
-  MockSnapshotCopyRequest *create_request(librbd::MockTestImageCtx &mock_remote_image_ctx,
-                                          librbd::MockTestImageCtx &mock_local_image_ctx,
-                                          journal::MockJournaler &mock_journaler,
-                                          Context *on_finish) {
-    return new MockSnapshotCopyRequest(&mock_local_image_ctx,
-                                       &mock_remote_image_ctx, &m_snap_map,
-                                       &mock_journaler, &m_client_meta,
-                                       m_threads->work_queue, on_finish);
-  }
-
-  int create_snap(librbd::ImageCtx *image_ctx, const std::string &snap_name,
-                  bool protect = false) {
-    int r = image_ctx->operations->snap_create(cls::rbd::UserSnapshotNamespace(),
-                                              snap_name.c_str());
-    if (r < 0) {
-      return r;
-    }
-
-    if (protect) {
-      r = image_ctx->operations->snap_protect(cls::rbd::UserSnapshotNamespace(),
-                                             snap_name.c_str());
-      if (r < 0) {
-        return r;
-      }
-    }
-
-    r = image_ctx->state->refresh();
-    if (r < 0) {
-      return r;
-    }
-    return 0;
-  }
-
-  void validate_snap_seqs(const librbd::journal::MirrorPeerClientMeta::SnapSeqs &snap_seqs) {
-    ASSERT_EQ(snap_seqs, m_client_meta.snap_seqs);
-  }
-
-  void validate_snap_map(const MockSnapshotCopyRequest::SnapMap &snap_map) {
-    ASSERT_EQ(snap_map, m_snap_map);
-  }
-
-  librbd::ImageCtx *m_remote_image_ctx;
-  librbd::ImageCtx *m_local_image_ctx;
-
-  MockSnapshotCopyRequest::SnapMap m_snap_map;
-  librbd::journal::MirrorPeerClientMeta m_client_meta;
-};
-
-TEST_F(TestMockImageSyncSnapshotCopyRequest, Empty) {
-  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-  journal::MockJournaler mock_journaler;
-
-  librbd::MockExclusiveLock mock_exclusive_lock;
-  mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
-
-  InSequence seq;
-  expect_update_client(mock_journaler, 0);
-
-  C_SaferCond ctx;
-  MockSnapshotCopyRequest *request = create_request(mock_remote_image_ctx,
-                                                    mock_local_image_ctx,
-                                                    mock_journaler, &ctx);
-  request->send();
-  ASSERT_EQ(0, ctx.wait());
-
-  validate_snap_map({});
-  validate_snap_seqs({});
-}
-
-TEST_F(TestMockImageSyncSnapshotCopyRequest, UpdateClientError) {
-  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-  journal::MockJournaler mock_journaler;
-
-  librbd::MockExclusiveLock mock_exclusive_lock;
-  mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
-
-  InSequence seq;
-  expect_update_client(mock_journaler, -EINVAL);
-
-  C_SaferCond ctx;
-  MockSnapshotCopyRequest *request = create_request(mock_remote_image_ctx,
-                                                    mock_local_image_ctx,
-                                                    mock_journaler, &ctx);
-  request->send();
-  ASSERT_EQ(-EINVAL, ctx.wait());
-}
-
-TEST_F(TestMockImageSyncSnapshotCopyRequest, UpdateClientCancel) {
-  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-  journal::MockJournaler mock_journaler;
-
-  librbd::MockExclusiveLock mock_exclusive_lock;
-  mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
-
-  C_SaferCond ctx;
-  MockSnapshotCopyRequest *request = create_request(mock_remote_image_ctx,
-                                                    mock_local_image_ctx,
-                                                    mock_journaler, &ctx);
-  InSequence seq;
-  EXPECT_CALL(mock_journaler, update_client(_, _))
-    .WillOnce(DoAll(InvokeWithoutArgs([request]() {
-           request->cancel();
-         }),
-       WithArg<1>(CompleteContext(0))));
-
-  request->send();
-  ASSERT_EQ(-ECANCELED, ctx.wait());
-}
-
-TEST_F(TestMockImageSyncSnapshotCopyRequest, SnapCreate) {
-  ASSERT_EQ(0, create_snap(m_remote_image_ctx, "snap1"));
-  ASSERT_EQ(0, create_snap(m_remote_image_ctx, "snap2"));
-
-  uint64_t remote_snap_id1 = m_remote_image_ctx->snap_ids[
-    {cls::rbd::UserSnapshotNamespace(), "snap1"}];
-  uint64_t remote_snap_id2 = m_remote_image_ctx->snap_ids[
-    {cls::rbd::UserSnapshotNamespace(), "snap2"}];
-
-  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-  MockSnapshotCreateRequest mock_snapshot_create_request;
-  journal::MockJournaler mock_journaler;
-
-  librbd::MockExclusiveLock mock_exclusive_lock;
-  mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
-
-  InSequence seq;
-  expect_get_snap_namespace(mock_remote_image_ctx, remote_snap_id1);
-  expect_start_op(mock_exclusive_lock);
-  expect_snap_create(mock_local_image_ctx, mock_snapshot_create_request, "snap1", 12, 0);
-  expect_get_snap_namespace(mock_remote_image_ctx, remote_snap_id2);
-  expect_start_op(mock_exclusive_lock);
-  expect_snap_create(mock_local_image_ctx, mock_snapshot_create_request, "snap2", 14, 0);
-  expect_snap_is_protected(mock_remote_image_ctx, remote_snap_id1, false, 0);
-  expect_snap_is_protected(mock_remote_image_ctx, remote_snap_id2, false, 0);
-  expect_update_client(mock_journaler, 0);
-
-  C_SaferCond ctx;
-  MockSnapshotCopyRequest *request = create_request(mock_remote_image_ctx,
-                                                    mock_local_image_ctx,
-                                                    mock_journaler, &ctx);
-  request->send();
-  ASSERT_EQ(0, ctx.wait());
-
-  validate_snap_map({{remote_snap_id1, {12}}, {remote_snap_id2, {14, 12}}});
-  validate_snap_seqs({{remote_snap_id1, 12}, {remote_snap_id2, 14}});
-}
-
-TEST_F(TestMockImageSyncSnapshotCopyRequest, SnapCreateError) {
-  ASSERT_EQ(0, create_snap(m_remote_image_ctx, "snap1"));
-
-  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-  MockSnapshotCreateRequest mock_snapshot_create_request;
-  journal::MockJournaler mock_journaler;
-
-  librbd::MockExclusiveLock mock_exclusive_lock;
-  mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
-
-  uint64_t remote_snap_id1 = mock_remote_image_ctx.snap_ids[
-    {cls::rbd::UserSnapshotNamespace(), "snap1"}];
-  InSequence seq;
-  expect_get_snap_namespace(mock_remote_image_ctx, remote_snap_id1);
-  expect_start_op(mock_exclusive_lock);
-  expect_snap_create(mock_local_image_ctx, mock_snapshot_create_request, "snap1", 12, -EINVAL);
-
-  C_SaferCond ctx;
-  MockSnapshotCopyRequest *request = create_request(mock_remote_image_ctx,
-                                                    mock_local_image_ctx,
-                                                    mock_journaler, &ctx);
-  request->send();
-  ASSERT_EQ(-EINVAL, ctx.wait());
-}
-
-TEST_F(TestMockImageSyncSnapshotCopyRequest, SnapCreateCancel) {
-  ASSERT_EQ(0, create_snap(m_remote_image_ctx, "snap1"));
-
-  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-  MockSnapshotCreateRequest mock_snapshot_create_request;
-  journal::MockJournaler mock_journaler;
-
-  librbd::MockExclusiveLock mock_exclusive_lock;
-  mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
-
-  uint64_t remote_snap_id1 = m_remote_image_ctx->snap_ids[
-    {cls::rbd::UserSnapshotNamespace(), "snap1"}];
-  expect_get_snap_namespace(mock_remote_image_ctx, remote_snap_id1);
-
-  C_SaferCond ctx;
-  MockSnapshotCopyRequest *request = create_request(mock_remote_image_ctx,
-                                                    mock_local_image_ctx,
-                                                    mock_journaler, &ctx);
-  InSequence seq;
-  expect_start_op(mock_exclusive_lock);
-  EXPECT_CALL(mock_snapshot_create_request, send())
-    .WillOnce(DoAll(InvokeWithoutArgs([request]() {
-           request->cancel();
-         }),
-       Invoke([this, &mock_snapshot_create_request]() {
-           m_threads->work_queue->queue(mock_snapshot_create_request.on_finish, 0);
-         })));
-
-  request->send();
-  ASSERT_EQ(-ECANCELED, ctx.wait());
-}
-
-TEST_F(TestMockImageSyncSnapshotCopyRequest, SnapRemoveAndCreate) {
-  ASSERT_EQ(0, create_snap(m_remote_image_ctx, "snap1"));
-  ASSERT_EQ(0, create_snap(m_local_image_ctx, "snap1"));
-
-  uint64_t remote_snap_id1 = m_remote_image_ctx->snap_ids[
-    {cls::rbd::UserSnapshotNamespace(), "snap1"}];
-  uint64_t local_snap_id1 = m_local_image_ctx->snap_ids[
-    {cls::rbd::UserSnapshotNamespace(), "snap1"}];
-
-  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-  MockSnapshotCreateRequest mock_snapshot_create_request;
-  journal::MockJournaler mock_journaler;
-
-  librbd::MockExclusiveLock mock_exclusive_lock;
-  mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
-
-  InSequence seq;
-  expect_snap_is_unprotected(mock_local_image_ctx,
-                             m_local_image_ctx->snap_ids[
-                               {cls::rbd::UserSnapshotNamespace(), "snap1"}],
-                             true, 0);
-  expect_get_snap_namespace(mock_local_image_ctx, local_snap_id1);
-  expect_start_op(mock_exclusive_lock);
-  expect_snap_remove(mock_local_image_ctx, "snap1", 0);
-  expect_get_snap_namespace(mock_remote_image_ctx, remote_snap_id1);
-  expect_start_op(mock_exclusive_lock);
-  expect_snap_create(mock_local_image_ctx, mock_snapshot_create_request, "snap1", 12, 0);
-  expect_snap_is_protected(mock_remote_image_ctx, remote_snap_id1, false, 0);
-  expect_update_client(mock_journaler, 0);
-
-  C_SaferCond ctx;
-  MockSnapshotCopyRequest *request = create_request(mock_remote_image_ctx,
-                                                    mock_local_image_ctx,
-                                                    mock_journaler, &ctx);
-  request->send();
-  ASSERT_EQ(0, ctx.wait());
-
-  validate_snap_map({{remote_snap_id1, {12}}});
-  validate_snap_seqs({{remote_snap_id1, 12}});
-}
-
-TEST_F(TestMockImageSyncSnapshotCopyRequest, SnapRemoveError) {
-  ASSERT_EQ(0, create_snap(m_local_image_ctx, "snap1"));
-
-  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-  journal::MockJournaler mock_journaler;
-
-  librbd::MockExclusiveLock mock_exclusive_lock;
-  mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
-
-  uint64_t local_snap_id1 = m_local_image_ctx->snap_ids[
-    {cls::rbd::UserSnapshotNamespace(), "snap1"}];
-  InSequence seq;
-  expect_snap_is_unprotected(mock_local_image_ctx,
-                             m_local_image_ctx->snap_ids[
-                               {cls::rbd::UserSnapshotNamespace(), "snap1"}],
-                             true, 0);
-  expect_get_snap_namespace(mock_local_image_ctx, local_snap_id1);
-  expect_start_op(mock_exclusive_lock);
-  expect_snap_remove(mock_local_image_ctx, "snap1", -EINVAL);
-
-  C_SaferCond ctx;
-  MockSnapshotCopyRequest *request = create_request(mock_remote_image_ctx,
-                                                    mock_local_image_ctx,
-                                                    mock_journaler, &ctx);
-  request->send();
-  ASSERT_EQ(-EINVAL, ctx.wait());
-}
-
-TEST_F(TestMockImageSyncSnapshotCopyRequest, SnapUnprotect) {
-  ASSERT_EQ(0, create_snap(m_remote_image_ctx, "snap1", true));
-  ASSERT_EQ(0, create_snap(m_local_image_ctx, "snap1", true));
-
-  uint64_t remote_snap_id1 = m_remote_image_ctx->snap_ids[
-    {cls::rbd::UserSnapshotNamespace(), "snap1"}];
-  uint64_t local_snap_id1 = m_local_image_ctx->snap_ids[
-    {cls::rbd::UserSnapshotNamespace(), "snap1"}];
-  m_client_meta.snap_seqs[remote_snap_id1] = local_snap_id1;
-
-  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-  journal::MockJournaler mock_journaler;
-
-  librbd::MockExclusiveLock mock_exclusive_lock;
-  mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
-
-  InSequence seq;
-  expect_snap_is_unprotected(mock_local_image_ctx, local_snap_id1, false, 0);
-  expect_snap_is_unprotected(mock_remote_image_ctx, remote_snap_id1, true, 0);
-  expect_start_op(mock_exclusive_lock);
-  expect_snap_unprotect(mock_local_image_ctx, "snap1", 0);
-  expect_get_snap_namespace(mock_local_image_ctx, local_snap_id1);
-  expect_get_snap_namespace(mock_remote_image_ctx, remote_snap_id1);
-  expect_snap_is_protected(mock_remote_image_ctx, remote_snap_id1, false, 0);
-  expect_update_client(mock_journaler, 0);
-
-  C_SaferCond ctx;
-  MockSnapshotCopyRequest *request = create_request(mock_remote_image_ctx,
-                                                    mock_local_image_ctx,
-                                                    mock_journaler, &ctx);
-  request->send();
-  ASSERT_EQ(0, ctx.wait());
-
-  validate_snap_map({{remote_snap_id1, {local_snap_id1}}});
-  validate_snap_seqs({{remote_snap_id1, local_snap_id1}});
-}
-
-TEST_F(TestMockImageSyncSnapshotCopyRequest, SnapUnprotectError) {
-  ASSERT_EQ(0, create_snap(m_remote_image_ctx, "snap1", true));
-  ASSERT_EQ(0, create_snap(m_local_image_ctx, "snap1", true));
-
-  uint64_t remote_snap_id1 = m_remote_image_ctx->snap_ids[
-    {cls::rbd::UserSnapshotNamespace(), "snap1"}];
-  uint64_t local_snap_id1 = m_local_image_ctx->snap_ids[
-    {cls::rbd::UserSnapshotNamespace(), "snap1"}];
-  m_client_meta.snap_seqs[remote_snap_id1] = local_snap_id1;
-
-  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-  journal::MockJournaler mock_journaler;
-
-  librbd::MockExclusiveLock mock_exclusive_lock;
-  mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
-
-  InSequence seq;
-  expect_snap_is_unprotected(mock_local_image_ctx, local_snap_id1, false, 0);
-  expect_snap_is_unprotected(mock_remote_image_ctx, remote_snap_id1, true, 0);
-  expect_start_op(mock_exclusive_lock);
-  expect_snap_unprotect(mock_local_image_ctx, "snap1", -EBUSY);
-
-  C_SaferCond ctx;
-  MockSnapshotCopyRequest *request = create_request(mock_remote_image_ctx,
-                                                    mock_local_image_ctx,
-                                                    mock_journaler, &ctx);
-  request->send();
-  ASSERT_EQ(-EBUSY, ctx.wait());
-}
-
-TEST_F(TestMockImageSyncSnapshotCopyRequest, SnapUnprotectCancel) {
-  ASSERT_EQ(0, create_snap(m_remote_image_ctx, "snap1", true));
-  ASSERT_EQ(0, create_snap(m_local_image_ctx, "snap1", true));
-
-  uint64_t remote_snap_id1 = m_remote_image_ctx->snap_ids[
-    {cls::rbd::UserSnapshotNamespace(), "snap1"}];
-  uint64_t local_snap_id1 = m_local_image_ctx->snap_ids[
-    {cls::rbd::UserSnapshotNamespace(), "snap1"}];
-  m_client_meta.snap_seqs[remote_snap_id1] = local_snap_id1;
-
-  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-  journal::MockJournaler mock_journaler;
-
-  librbd::MockExclusiveLock mock_exclusive_lock;
-  mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
-
-  C_SaferCond ctx;
-  MockSnapshotCopyRequest *request = create_request(mock_remote_image_ctx,
-                                                    mock_local_image_ctx,
-                                                    mock_journaler, &ctx);
-  InSequence seq;
-  expect_snap_is_unprotected(mock_local_image_ctx, local_snap_id1, false, 0);
-  expect_snap_is_unprotected(mock_remote_image_ctx, remote_snap_id1, true, 0);
-  expect_start_op(mock_exclusive_lock);
-  EXPECT_CALL(*mock_local_image_ctx.operations,
-             execute_snap_unprotect(_, StrEq("snap1"), _))
-    .WillOnce(DoAll(InvokeWithoutArgs([request]() {
-           request->cancel();
-         }),
-       WithArg<2>(Invoke([this](Context *ctx) {
-           m_threads->work_queue->queue(ctx, 0);
-           }))));
-
-  request->send();
-  ASSERT_EQ(-ECANCELED, ctx.wait());
-}
-
-TEST_F(TestMockImageSyncSnapshotCopyRequest, SnapUnprotectRemove) {
-  ASSERT_EQ(0, create_snap(m_remote_image_ctx, "snap1", true));
-  ASSERT_EQ(0, create_snap(m_local_image_ctx, "snap1", true));
-
-  uint64_t remote_snap_id1 = m_remote_image_ctx->snap_ids[
-    {cls::rbd::UserSnapshotNamespace(), "snap1"}];
-  uint64_t local_snap_id1 = m_local_image_ctx->snap_ids[
-    {cls::rbd::UserSnapshotNamespace(), "snap1"}];
-
-  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-  MockSnapshotCreateRequest mock_snapshot_create_request;
-  journal::MockJournaler mock_journaler;
-
-  librbd::MockExclusiveLock mock_exclusive_lock;
-  mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
-
-  InSequence seq;
-  expect_snap_is_unprotected(mock_local_image_ctx,
-                             m_local_image_ctx->snap_ids[
-                               {cls::rbd::UserSnapshotNamespace(), "snap1"}],
-                             false, 0);
-  expect_start_op(mock_exclusive_lock);
-  expect_snap_unprotect(mock_local_image_ctx, "snap1", 0);
-  expect_get_snap_namespace(mock_local_image_ctx, local_snap_id1);
-  expect_start_op(mock_exclusive_lock);
-  expect_snap_remove(mock_local_image_ctx, "snap1", 0);
-  expect_get_snap_namespace(mock_remote_image_ctx, remote_snap_id1);
-  expect_start_op(mock_exclusive_lock);
-  expect_snap_create(mock_local_image_ctx, mock_snapshot_create_request, "snap1", 12, 0);
-  expect_snap_is_protected(mock_remote_image_ctx, remote_snap_id1, false, 0);
-  expect_update_client(mock_journaler, 0);
-
-  C_SaferCond ctx;
-  MockSnapshotCopyRequest *request = create_request(mock_remote_image_ctx,
-                                                    mock_local_image_ctx,
-                                                    mock_journaler, &ctx);
-  request->send();
-  ASSERT_EQ(0, ctx.wait());
-
-  validate_snap_map({{remote_snap_id1, {12}}});
-  validate_snap_seqs({{remote_snap_id1, 12}});
-}
-
-TEST_F(TestMockImageSyncSnapshotCopyRequest, SnapCreateProtect) {
-  ASSERT_EQ(0, create_snap(m_remote_image_ctx, "snap1", true));
-
-  uint64_t remote_snap_id1 = m_remote_image_ctx->snap_ids[
-    {cls::rbd::UserSnapshotNamespace(), "snap1"}];
-
-  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-  MockSnapshotCreateRequest mock_snapshot_create_request;
-  journal::MockJournaler mock_journaler;
-
-  librbd::MockExclusiveLock mock_exclusive_lock;
-  mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
-
-  InSequence seq;
-  expect_get_snap_namespace(mock_remote_image_ctx, remote_snap_id1);
-  expect_start_op(mock_exclusive_lock);
-  expect_snap_create(mock_local_image_ctx, mock_snapshot_create_request, "snap1", 12, 0);
-  expect_snap_is_protected(mock_remote_image_ctx, remote_snap_id1, true, 0);
-  expect_snap_is_protected(mock_local_image_ctx, 12, false, 0);
-  expect_start_op(mock_exclusive_lock);
-  expect_snap_protect(mock_local_image_ctx, "snap1", 0);
-  expect_update_client(mock_journaler, 0);
-
-  C_SaferCond ctx;
-  MockSnapshotCopyRequest *request = create_request(mock_remote_image_ctx,
-                                                    mock_local_image_ctx,
-                                                    mock_journaler, &ctx);
-  request->send();
-  ASSERT_EQ(0, ctx.wait());
-
-  validate_snap_map({{remote_snap_id1, {12}}});
-  validate_snap_seqs({{remote_snap_id1, 12}});
-}
-
-TEST_F(TestMockImageSyncSnapshotCopyRequest, SnapProtect) {
-  ASSERT_EQ(0, create_snap(m_remote_image_ctx, "snap1", true));
-  ASSERT_EQ(0, create_snap(m_local_image_ctx, "snap1", true));
-
-  uint64_t remote_snap_id1 = m_remote_image_ctx->snap_ids[
-    {cls::rbd::UserSnapshotNamespace(), "snap1"}];
-  uint64_t local_snap_id1 = m_local_image_ctx->snap_ids[
-    {cls::rbd::UserSnapshotNamespace(), "snap1"}];
-  m_client_meta.snap_seqs[remote_snap_id1] = local_snap_id1;
-
-  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-  journal::MockJournaler mock_journaler;
-
-  librbd::MockExclusiveLock mock_exclusive_lock;
-  mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
-
-  InSequence seq;
-  expect_snap_is_unprotected(mock_local_image_ctx, local_snap_id1, true, 0);
-  expect_get_snap_namespace(mock_local_image_ctx, local_snap_id1);
-  expect_get_snap_namespace(mock_remote_image_ctx, remote_snap_id1);
-  expect_snap_is_protected(mock_remote_image_ctx, remote_snap_id1, true, 0);
-  expect_snap_is_protected(mock_local_image_ctx, local_snap_id1, false, 0);
-  expect_start_op(mock_exclusive_lock);
-  expect_snap_protect(mock_local_image_ctx, "snap1", 0);
-  expect_update_client(mock_journaler, 0);
-
-  C_SaferCond ctx;
-  MockSnapshotCopyRequest *request = create_request(mock_remote_image_ctx,
-                                                    mock_local_image_ctx,
-                                                    mock_journaler, &ctx);
-  request->send();
-  ASSERT_EQ(0, ctx.wait());
-
-  validate_snap_map({{remote_snap_id1, {local_snap_id1}}});
-  validate_snap_seqs({{remote_snap_id1, local_snap_id1}});
-}
-
-TEST_F(TestMockImageSyncSnapshotCopyRequest, SnapProtectError) {
-  ASSERT_EQ(0, create_snap(m_remote_image_ctx, "snap1", true));
-  ASSERT_EQ(0, create_snap(m_local_image_ctx, "snap1", true));
-
-  uint64_t remote_snap_id1 = m_remote_image_ctx->snap_ids[
-    {cls::rbd::UserSnapshotNamespace(), "snap1"}];
-  uint64_t local_snap_id1 = m_local_image_ctx->snap_ids[
-    {cls::rbd::UserSnapshotNamespace(), "snap1"}];
-  m_client_meta.snap_seqs[remote_snap_id1] = local_snap_id1;
-
-  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-  journal::MockJournaler mock_journaler;
-
-  librbd::MockExclusiveLock mock_exclusive_lock;
-  mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
-
-  InSequence seq;
-  expect_snap_is_unprotected(mock_local_image_ctx, local_snap_id1, true, 0);
-  expect_get_snap_namespace(mock_local_image_ctx, local_snap_id1);
-  expect_get_snap_namespace(mock_remote_image_ctx, remote_snap_id1);
-  expect_snap_is_protected(mock_remote_image_ctx, remote_snap_id1, true, 0);
-  expect_snap_is_protected(mock_local_image_ctx, local_snap_id1, false, 0);
-  expect_start_op(mock_exclusive_lock);
-  expect_snap_protect(mock_local_image_ctx, "snap1", -EINVAL);
-
-  C_SaferCond ctx;
-  MockSnapshotCopyRequest *request = create_request(mock_remote_image_ctx,
-                                                    mock_local_image_ctx,
-                                                    mock_journaler, &ctx);
-  request->send();
-  ASSERT_EQ(-EINVAL, ctx.wait());
-}
-
-TEST_F(TestMockImageSyncSnapshotCopyRequest, SnapProtectCancel) {
-  ASSERT_EQ(0, create_snap(m_remote_image_ctx, "snap1", true));
-  ASSERT_EQ(0, create_snap(m_local_image_ctx, "snap1", true));
-
-  uint64_t remote_snap_id1 = m_remote_image_ctx->snap_ids[
-    {cls::rbd::UserSnapshotNamespace(), "snap1"}];
-  uint64_t local_snap_id1 = m_local_image_ctx->snap_ids[
-    {cls::rbd::UserSnapshotNamespace(), "snap1"}];
-  m_client_meta.snap_seqs[remote_snap_id1] = local_snap_id1;
-
-  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-  journal::MockJournaler mock_journaler;
-
-  librbd::MockExclusiveLock mock_exclusive_lock;
-  mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
-
-  C_SaferCond ctx;
-  MockSnapshotCopyRequest *request = create_request(mock_remote_image_ctx,
-                                                    mock_local_image_ctx,
-                                                    mock_journaler, &ctx);
-  InSequence seq;
-  expect_snap_is_unprotected(mock_local_image_ctx, local_snap_id1, true, 0);
-  expect_get_snap_namespace(mock_local_image_ctx, local_snap_id1);
-  expect_get_snap_namespace(mock_remote_image_ctx, remote_snap_id1);
-  expect_snap_is_protected(mock_remote_image_ctx, remote_snap_id1, true, 0);
-  expect_snap_is_protected(mock_local_image_ctx, local_snap_id1, false, 0);
-  expect_start_op(mock_exclusive_lock);
-  EXPECT_CALL(*mock_local_image_ctx.operations,
-             execute_snap_protect(_, StrEq("snap1"), _))
-    .WillOnce(DoAll(InvokeWithoutArgs([request]() {
-           request->cancel();
-         }),
-       WithArg<2>(Invoke([this](Context *ctx) {
-             m_threads->work_queue->queue(ctx, 0);
-           }))));
-
-  request->send();
-  ASSERT_EQ(-ECANCELED, ctx.wait());
-}
-
-} // namespace image_sync
-} // namespace mirror
-} // namespace rbd
diff --git a/src/test/rbd_mirror/image_sync/test_mock_SnapshotCreateRequest.cc b/src/test/rbd_mirror/image_sync/test_mock_SnapshotCreateRequest.cc
deleted file mode 100644 (file)
index 4a8ab1f..0000000
+++ /dev/null
@@ -1,393 +0,0 @@
-// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
-// vim: ts=8 sw=2 smarttab
-
-#include "test/rbd_mirror/test_mock_fixture.h"
-#include "test/librados_test_stub/LibradosTestStub.h"
-#include "include/rbd/librbd.hpp"
-#include "librbd/ImageCtx.h"
-#include "librbd/ImageState.h"
-#include "librbd/Operations.h"
-#include "osdc/Striper.h"
-#include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
-#include "test/librbd/mock/MockImageCtx.h"
-#include "tools/rbd_mirror/image_sync/SnapshotCreateRequest.h"
-#include "tools/rbd_mirror/Threads.h"
-
-namespace librbd {
-namespace {
-
-struct MockTestImageCtx : public librbd::MockImageCtx {
-  MockTestImageCtx(librbd::ImageCtx &image_ctx)
-    : librbd::MockImageCtx(image_ctx) {
-  }
-};
-
-} // anonymous namespace
-} // namespace librbd
-
-// template definitions
-#include "tools/rbd_mirror/image_sync/SnapshotCreateRequest.cc"
-template class rbd::mirror::image_sync::SnapshotCreateRequest<librbd::MockTestImageCtx>;
-
-namespace rbd {
-namespace mirror {
-namespace image_sync {
-
-using ::testing::_;
-using ::testing::DoAll;
-using ::testing::InSequence;
-using ::testing::Invoke;
-using ::testing::InvokeWithoutArgs;
-using ::testing::Return;
-using ::testing::ReturnNew;
-using ::testing::StrEq;
-using ::testing::WithArg;
-
-class TestMockImageSyncSnapshotCreateRequest : public TestMockFixture {
-public:
-  typedef SnapshotCreateRequest<librbd::MockTestImageCtx> MockSnapshotCreateRequest;
-
-  void SetUp() override {
-    TestMockFixture::SetUp();
-
-    librbd::RBD rbd;
-    ASSERT_EQ(0, create_image(rbd, m_local_io_ctx, m_image_name, m_image_size));
-    ASSERT_EQ(0, open_image(m_local_io_ctx, m_image_name, &m_local_image_ctx));
-  }
-
-  void expect_start_op(librbd::MockExclusiveLock &mock_exclusive_lock) {
-    EXPECT_CALL(mock_exclusive_lock, start_op()).WillOnce(
-      ReturnNew<FunctionContext>([](int) {}));
-  }
-
-  void expect_test_features(librbd::MockTestImageCtx &mock_image_ctx,
-                            uint64_t features, bool enabled) {
-    EXPECT_CALL(mock_image_ctx, test_features(features))
-                  .WillOnce(Return(enabled));
-  }
-
-  void expect_set_size(librbd::MockTestImageCtx &mock_image_ctx, int r) {
-    EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
-                exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("set_size"), _, _, _))
-                  .WillOnce(Return(r));
-  }
-
-  void expect_remove_parent(librbd::MockTestImageCtx &mock_image_ctx, int r) {
-    EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
-                exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("remove_parent"), _, _, _))
-                  .WillOnce(Return(r));
-  }
-
-  void expect_set_parent(librbd::MockTestImageCtx &mock_image_ctx, int r) {
-    EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
-                exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("set_parent"), _, _, _))
-                  .WillOnce(Return(r));
-  }
-
-  void expect_snap_create(librbd::MockTestImageCtx &mock_image_ctx,
-                          const std::string &snap_name, uint64_t snap_id, int r) {
-    EXPECT_CALL(*mock_image_ctx.operations, execute_snap_create(_, StrEq(snap_name), _, 0, true))
-                  .WillOnce(DoAll(InvokeWithoutArgs([&mock_image_ctx, snap_id, snap_name]() {
-                                    inject_snap(mock_image_ctx, snap_id, snap_name);
-                                  }),
-                                  WithArg<2>(Invoke([this, r](Context *ctx) {
-                                    m_threads->work_queue->queue(ctx, r);
-                                  }))));
-  }
-
-  void expect_object_map_resize(librbd::MockTestImageCtx &mock_image_ctx,
-                                librados::snap_t snap_id, int r) {
-    std::string oid(librbd::ObjectMap<>::object_map_name(mock_image_ctx.id,
-                                                         snap_id));
-    EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
-                exec(oid, _, StrEq("rbd"), StrEq("object_map_resize"), _, _, _))
-                  .WillOnce(Return(r));
-  }
-
-  static void inject_snap(librbd::MockTestImageCtx &mock_image_ctx,
-                   uint64_t snap_id, const std::string &snap_name) {
-    mock_image_ctx.snap_ids[{cls::rbd::UserSnapshotNamespace(),
-                            snap_name}] = snap_id;
-  }
-
-  MockSnapshotCreateRequest *create_request(librbd::MockTestImageCtx &mock_local_image_ctx,
-                                            const std::string &snap_name,
-                                           const cls::rbd::SnapshotNamespace &snap_namespace,
-                                            uint64_t size,
-                                            const librbd::ParentSpec &spec,
-                                            uint64_t parent_overlap,
-                                            Context *on_finish) {
-    return new MockSnapshotCreateRequest(&mock_local_image_ctx, snap_name, snap_namespace, size,
-                                         spec, parent_overlap, on_finish);
-  }
-
-  librbd::ImageCtx *m_local_image_ctx;
-};
-
-TEST_F(TestMockImageSyncSnapshotCreateRequest, Resize) {
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-  librbd::MockExclusiveLock mock_exclusive_lock;
-  mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
-
-  InSequence seq;
-  expect_start_op(mock_exclusive_lock);
-  expect_set_size(mock_local_image_ctx, 0);
-  expect_start_op(mock_exclusive_lock);
-  expect_snap_create(mock_local_image_ctx, "snap1", 10, 0);
-  expect_test_features(mock_local_image_ctx, RBD_FEATURE_OBJECT_MAP, false);
-
-  C_SaferCond ctx;
-  MockSnapshotCreateRequest *request = create_request(mock_local_image_ctx,
-                                                      "snap1",
-                                                     cls::rbd::UserSnapshotNamespace(),
-                                                     123, {}, 0,
-                                                      &ctx);
-  request->send();
-  ASSERT_EQ(0, ctx.wait());
-}
-
-TEST_F(TestMockImageSyncSnapshotCreateRequest, ResizeError) {
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-  librbd::MockExclusiveLock mock_exclusive_lock;
-  mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
-
-  InSequence seq;
-  expect_start_op(mock_exclusive_lock);
-  expect_set_size(mock_local_image_ctx, -EINVAL);
-
-  C_SaferCond ctx;
-  MockSnapshotCreateRequest *request = create_request(mock_local_image_ctx,
-                                                      "snap1",
-                                                     cls::rbd::UserSnapshotNamespace(),
-                                                     123, {}, 0,
-                                                      &ctx);
-  request->send();
-  ASSERT_EQ(-EINVAL, ctx.wait());
-}
-
-TEST_F(TestMockImageSyncSnapshotCreateRequest, RemoveParent) {
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-  librbd::MockExclusiveLock mock_exclusive_lock;
-  mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
-
-  mock_local_image_ctx.parent_md.spec.pool_id = 213;
-
-  InSequence seq;
-  expect_start_op(mock_exclusive_lock);
-  expect_remove_parent(mock_local_image_ctx, 0);
-  expect_start_op(mock_exclusive_lock);
-  expect_snap_create(mock_local_image_ctx, "snap1", 10, 0);
-  expect_test_features(mock_local_image_ctx, RBD_FEATURE_OBJECT_MAP, false);
-
-  C_SaferCond ctx;
-  MockSnapshotCreateRequest *request = create_request(mock_local_image_ctx,
-                                                      "snap1",
-                                                     cls::rbd::UserSnapshotNamespace(),
-                                                      m_local_image_ctx->size,
-                                                      {}, 0, &ctx);
-  request->send();
-  ASSERT_EQ(0, ctx.wait());
-}
-
-TEST_F(TestMockImageSyncSnapshotCreateRequest, RemoveParentError) {
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-  librbd::MockExclusiveLock mock_exclusive_lock;
-  mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
-
-  mock_local_image_ctx.parent_md.spec.pool_id = 213;
-
-  InSequence seq;
-  expect_start_op(mock_exclusive_lock);
-  expect_remove_parent(mock_local_image_ctx, -EINVAL);
-
-  C_SaferCond ctx;
-  MockSnapshotCreateRequest *request = create_request(mock_local_image_ctx,
-                                                      "snap1",
-                                                     cls::rbd::UserSnapshotNamespace(),
-                                                      m_local_image_ctx->size,
-                                                      {}, 0, &ctx);
-  request->send();
-  ASSERT_EQ(-EINVAL, ctx.wait());
-}
-
-TEST_F(TestMockImageSyncSnapshotCreateRequest, RemoveSetParent) {
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-  librbd::MockExclusiveLock mock_exclusive_lock;
-  mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
-
-  mock_local_image_ctx.parent_md.spec.pool_id = 213;
-
-  InSequence seq;
-  expect_start_op(mock_exclusive_lock);
-  expect_remove_parent(mock_local_image_ctx, 0);
-  expect_start_op(mock_exclusive_lock);
-  expect_set_parent(mock_local_image_ctx, 0);
-  expect_start_op(mock_exclusive_lock);
-  expect_snap_create(mock_local_image_ctx, "snap1", 10, 0);
-  expect_test_features(mock_local_image_ctx, RBD_FEATURE_OBJECT_MAP, false);
-
-  C_SaferCond ctx;
-  MockSnapshotCreateRequest *request = create_request(mock_local_image_ctx,
-                                                      "snap1",
-                                                     cls::rbd::UserSnapshotNamespace(),
-                                                      m_local_image_ctx->size,
-                                                      {123, "test", 0}, 0,
-                                                      &ctx);
-  request->send();
-  ASSERT_EQ(0, ctx.wait());
-}
-
-TEST_F(TestMockImageSyncSnapshotCreateRequest, SetParentSpec) {
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-  librbd::MockExclusiveLock mock_exclusive_lock;
-  mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
-
-  InSequence seq;
-  expect_start_op(mock_exclusive_lock);
-  expect_set_parent(mock_local_image_ctx, 0);
-  expect_start_op(mock_exclusive_lock);
-  expect_snap_create(mock_local_image_ctx, "snap1", 10, 0);
-  expect_test_features(mock_local_image_ctx, RBD_FEATURE_OBJECT_MAP, false);
-
-  C_SaferCond ctx;
-  MockSnapshotCreateRequest *request = create_request(mock_local_image_ctx,
-                                                      "snap1",
-                                                     cls::rbd::UserSnapshotNamespace(),
-                                                      m_local_image_ctx->size,
-                                                      {123, "test", 0}, 0,
-                                                      &ctx);
-  request->send();
-  ASSERT_EQ(0, ctx.wait());
-}
-
-TEST_F(TestMockImageSyncSnapshotCreateRequest, SetParentOverlap) {
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-  librbd::MockExclusiveLock mock_exclusive_lock;
-  mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
-
-  mock_local_image_ctx.parent_md.spec = {123, "test", 0};
-
-  InSequence seq;
-  expect_start_op(mock_exclusive_lock);
-  expect_set_parent(mock_local_image_ctx, 0);
-  expect_start_op(mock_exclusive_lock);
-  expect_snap_create(mock_local_image_ctx, "snap1", 10, 0);
-  expect_test_features(mock_local_image_ctx, RBD_FEATURE_OBJECT_MAP, false);
-
-  C_SaferCond ctx;
-  MockSnapshotCreateRequest *request = create_request(mock_local_image_ctx,
-                                                      "snap1",
-                                                     cls::rbd::UserSnapshotNamespace(),
-                                                      m_local_image_ctx->size,
-                                                      mock_local_image_ctx.parent_md.spec,
-                                                      123, &ctx);
-  request->send();
-  ASSERT_EQ(0, ctx.wait());
-}
-
-TEST_F(TestMockImageSyncSnapshotCreateRequest, SetParentError) {
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-  librbd::MockExclusiveLock mock_exclusive_lock;
-  mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
-
-  InSequence seq;
-  expect_start_op(mock_exclusive_lock);
-  expect_set_parent(mock_local_image_ctx, -ESTALE);
-
-  C_SaferCond ctx;
-  MockSnapshotCreateRequest *request = create_request(mock_local_image_ctx,
-                                                      "snap1",
-                                                     cls::rbd::UserSnapshotNamespace(),
-                                                      m_local_image_ctx->size,
-                                                      {123, "test", 0}, 0,
-                                                      &ctx);
-  request->send();
-  ASSERT_EQ(-ESTALE, ctx.wait());
-}
-
-TEST_F(TestMockImageSyncSnapshotCreateRequest, SnapCreate) {
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-  librbd::MockExclusiveLock mock_exclusive_lock;
-  mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
-
-  InSequence seq;
-  expect_start_op(mock_exclusive_lock);
-  expect_snap_create(mock_local_image_ctx, "snap1", 10, 0);
-  expect_test_features(mock_local_image_ctx, RBD_FEATURE_OBJECT_MAP, false);
-
-  C_SaferCond ctx;
-  MockSnapshotCreateRequest *request = create_request(mock_local_image_ctx,
-                                                      "snap1",
-                                                     cls::rbd::UserSnapshotNamespace(),
-                                                      m_local_image_ctx->size,
-                                                      {}, 0, &ctx);
-  request->send();
-  ASSERT_EQ(0, ctx.wait());
-}
-
-TEST_F(TestMockImageSyncSnapshotCreateRequest, SnapCreateError) {
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-  librbd::MockExclusiveLock mock_exclusive_lock;
-  mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
-
-  InSequence seq;
-  expect_start_op(mock_exclusive_lock);
-  expect_snap_create(mock_local_image_ctx, "snap1", 10, -EINVAL);
-
-  C_SaferCond ctx;
-  MockSnapshotCreateRequest *request = create_request(mock_local_image_ctx,
-                                                      "snap1",
-                                                     cls::rbd::UserSnapshotNamespace(),
-                                                      m_local_image_ctx->size,
-                                                      {}, 0, &ctx);
-  request->send();
-  ASSERT_EQ(-EINVAL, ctx.wait());
-}
-
-TEST_F(TestMockImageSyncSnapshotCreateRequest, ResizeObjectMap) {
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-  librbd::MockExclusiveLock mock_exclusive_lock;
-  mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
-
-  InSequence seq;
-  expect_start_op(mock_exclusive_lock);
-  expect_snap_create(mock_local_image_ctx, "snap1", 10, 0);
-  expect_test_features(mock_local_image_ctx, RBD_FEATURE_OBJECT_MAP, true);
-  expect_start_op(mock_exclusive_lock);
-  expect_object_map_resize(mock_local_image_ctx, 10, 0);
-
-  C_SaferCond ctx;
-  MockSnapshotCreateRequest *request = create_request(mock_local_image_ctx,
-                                                      "snap1",
-                                                     cls::rbd::UserSnapshotNamespace(),
-                                                      m_local_image_ctx->size,
-                                                      {}, 0, &ctx);
-  request->send();
-  ASSERT_EQ(0, ctx.wait());
-}
-
-TEST_F(TestMockImageSyncSnapshotCreateRequest, ResizeObjectMapError) {
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-  librbd::MockExclusiveLock mock_exclusive_lock;
-  mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
-
-  InSequence seq;
-  expect_start_op(mock_exclusive_lock);
-  expect_snap_create(mock_local_image_ctx, "snap1", 10, 0);
-  expect_test_features(mock_local_image_ctx, RBD_FEATURE_OBJECT_MAP, true);
-  expect_start_op(mock_exclusive_lock);
-  expect_object_map_resize(mock_local_image_ctx, 10, -EINVAL);
-
-  C_SaferCond ctx;
-  MockSnapshotCreateRequest *request = create_request(mock_local_image_ctx,
-                                                      "snap1",
-                                                     cls::rbd::UserSnapshotNamespace(),
-                                                      m_local_image_ctx->size,
-                                                      {}, 0, &ctx);
-  request->send();
-  ASSERT_EQ(-EINVAL, ctx.wait());
-}
-
-} // namespace image_sync
-} // namespace mirror
-} // namespace rbd
index 4b9e95acc4376ac89a8ece51b2ed89f13ca30d9e..aed32bbfb48b7c403f64ce670d55680dfb923572 100644 (file)
@@ -3,17 +3,14 @@
 
 #include "test/rbd_mirror/test_mock_fixture.h"
 #include "include/rbd/librbd.hpp"
+#include "librbd/DeepCopyRequest.h"
 #include "librbd/journal/Types.h"
 #include "librbd/journal/TypeTraits.h"
 #include "test/journal/mock/MockJournaler.h"
 #include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
 #include "test/librbd/mock/MockImageCtx.h"
-#include "test/librbd/mock/MockObjectMap.h"
 #include "tools/rbd_mirror/ImageSync.h"
 #include "tools/rbd_mirror/Threads.h"
-#include "tools/rbd_mirror/image_sync/ImageCopyRequest.h"
-#include "tools/rbd_mirror/image_sync/MetadataCopyRequest.h"
-#include "tools/rbd_mirror/image_sync/SnapshotCopyRequest.h"
 #include "tools/rbd_mirror/image_sync/SyncPointCreateRequest.h"
 #include "tools/rbd_mirror/image_sync/SyncPointPruneRequest.h"
 
@@ -37,44 +34,26 @@ struct TypeTraits<librbd::MockTestImageCtx> {
 };
 
 } // namespace journal
-} // namespace librbd
-
-// template definitions
-template class rbd::mirror::ImageSync<librbd::MockTestImageCtx>;
-#include "tools/rbd_mirror/ImageSync.cc"
-
-namespace rbd {
-namespace mirror {
-
-template<>
-struct InstanceWatcher<librbd::MockTestImageCtx> {
-  MOCK_METHOD2(notify_sync_request, void(const std::string, Context *));
-  MOCK_METHOD1(cancel_sync_request, bool(const std::string &));
-  MOCK_METHOD1(notify_sync_complete, void(const std::string &));
-};
-
-namespace image_sync {
 
 template <>
-class ImageCopyRequest<librbd::MockTestImageCtx> {
+class DeepCopyRequest<librbd::MockTestImageCtx> {
 public:
-  static ImageCopyRequest* s_instance;
+  static DeepCopyRequest* s_instance;
   Context *on_finish;
 
-  static ImageCopyRequest* create(librbd::MockTestImageCtx *local_image_ctx,
-                                  librbd::MockTestImageCtx *remote_image_ctx,
-                                  SafeTimer *timer, Mutex *timer_lock,
-                                  journal::MockJournaler *journaler,
-                                  librbd::journal::MirrorPeerClientMeta *client_meta,
-                                  librbd::journal::MirrorPeerSyncPoint *sync_point,
-                                  Context *on_finish,
-                                  rbd::mirror::ProgressContext *progress_ctx = nullptr) {
+  static DeepCopyRequest* create(
+      librbd::MockTestImageCtx *src_image_ctx,
+      librbd::MockTestImageCtx *dst_image_ctx,
+      librados::snap_t snap_id_start, librados::snap_t snap_id_end,
+      const librbd::deep_copy::ObjectNumber &object_number,
+      ContextWQ *work_queue, SnapSeqs *snap_seqs, ProgressContext *prog_ctx,
+      Context *on_finish) {
     assert(s_instance != nullptr);
     s_instance->on_finish = on_finish;
     return s_instance;
   }
 
-  ImageCopyRequest() {
+  DeepCopyRequest() {
     s_instance = this;
   }
 
@@ -88,59 +67,26 @@ public:
   MOCK_METHOD0(send, void());
 };
 
-template <>
-class MetadataCopyRequest<librbd::MockTestImageCtx> {
-public:
-  static MetadataCopyRequest* s_instance;
-  Context *on_finish{nullptr};
-
-  static MetadataCopyRequest* create(librbd::MockTestImageCtx *local_image_ctx,
-                                     librbd::MockTestImageCtx *remote_image_ctx,
-                                     Context *on_finish) {
-    assert(s_instance != nullptr);
-    s_instance->on_finish = on_finish;
-    return s_instance;
-  }
-
-  MetadataCopyRequest() {
-    s_instance = this;
-  }
+DeepCopyRequest<librbd::MockTestImageCtx>* DeepCopyRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
 
-  MOCK_METHOD0(send, void());
-};
-
-template <>
-class SnapshotCopyRequest<librbd::MockTestImageCtx> {
-public:
-  static SnapshotCopyRequest* s_instance;
-  Context *on_finish;
-
-  static SnapshotCopyRequest* create(librbd::MockTestImageCtx *local_image_ctx,
-                                     librbd::MockTestImageCtx *remote_image_ctx,
-                                     SnapshotCopyRequest<librbd::ImageCtx>::SnapMap *snap_map,
-                                     journal::MockJournaler *journaler,
-                                     librbd::journal::MirrorPeerClientMeta *client_meta,
-                                     ContextWQ *work_queue,
-                                     Context *on_finish) {
-    assert(s_instance != nullptr);
-    s_instance->on_finish = on_finish;
-    return s_instance;
-  }
-
-  SnapshotCopyRequest() {
-    s_instance = this;
-  }
+} // namespace librbd
 
-  void put() {
-  }
+// template definitions
+template class rbd::mirror::ImageSync<librbd::MockTestImageCtx>;
+#include "tools/rbd_mirror/ImageSync.cc"
 
-  void get() {
-  }
+namespace rbd {
+namespace mirror {
 
-  MOCK_METHOD0(send, void());
-  MOCK_METHOD0(cancel, void());
+template<>
+struct InstanceWatcher<librbd::MockTestImageCtx> {
+  MOCK_METHOD2(notify_sync_request, void(const std::string, Context *));
+  MOCK_METHOD1(cancel_sync_request, bool(const std::string &));
+  MOCK_METHOD1(notify_sync_complete, void(const std::string &));
 };
 
+namespace image_sync {
+
 template <>
 class SyncPointCreateRequest<librbd::MockTestImageCtx> {
 public:
@@ -187,9 +133,6 @@ public:
   MOCK_METHOD0(send, void());
 };
 
-ImageCopyRequest<librbd::MockTestImageCtx>* ImageCopyRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
-MetadataCopyRequest<librbd::MockTestImageCtx>* MetadataCopyRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
-SnapshotCopyRequest<librbd::MockTestImageCtx>* SnapshotCopyRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
 SyncPointCreateRequest<librbd::MockTestImageCtx>* SyncPointCreateRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
 SyncPointPruneRequest<librbd::MockTestImageCtx>* SyncPointPruneRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
 
@@ -199,7 +142,7 @@ using ::testing::_;
 using ::testing::InSequence;
 using ::testing::Invoke;
 using ::testing::Return;
-using ::testing::ReturnNew;
+using ::testing::StrEq;
 using ::testing::WithArg;
 using ::testing::InvokeWithoutArgs;
 
@@ -207,11 +150,9 @@ class TestMockImageSync : public TestMockFixture {
 public:
   typedef ImageSync<librbd::MockTestImageCtx> MockImageSync;
   typedef InstanceWatcher<librbd::MockTestImageCtx> MockInstanceWatcher;
-  typedef image_sync::ImageCopyRequest<librbd::MockTestImageCtx> MockImageCopyRequest;
-  typedef image_sync::MetadataCopyRequest<librbd::MockTestImageCtx> MockMetadataCopyRequest;
-  typedef image_sync::SnapshotCopyRequest<librbd::MockTestImageCtx> MockSnapshotCopyRequest;
   typedef image_sync::SyncPointCreateRequest<librbd::MockTestImageCtx> MockSyncPointCreateRequest;
   typedef image_sync::SyncPointPruneRequest<librbd::MockTestImageCtx> MockSyncPointPruneRequest;
+  typedef librbd::DeepCopyRequest<librbd::MockTestImageCtx> MockImageCopyRequest;
 
   void SetUp() override {
     TestMockFixture::SetUp();
@@ -224,9 +165,17 @@ public:
     ASSERT_EQ(0, open_image(m_local_io_ctx, m_image_name, &m_local_image_ctx));
   }
 
-  void expect_start_op(librbd::MockExclusiveLock &mock_exclusive_lock) {
-    EXPECT_CALL(mock_exclusive_lock, start_op()).WillOnce(
-      ReturnNew<FunctionContext>([](int) {}));
+  void expect_get_snap_id(librbd::MockTestImageCtx &mock_image_ctx) {
+    EXPECT_CALL(mock_image_ctx, get_snap_id(_, _))
+      .WillOnce(Return(123));
+  }
+
+  void expect_snap_set(librbd::MockTestImageCtx &mock_image_ctx,
+                       const std::string &snap_name, int r) {
+    EXPECT_CALL(*mock_image_ctx.state, snap_set(_, StrEq(snap_name), _))
+      .WillOnce(WithArg<2>(Invoke([this, r](Context *on_finish) {
+          m_threads->work_queue->queue(on_finish, r);
+        })));
   }
 
   void expect_notify_sync_request(MockInstanceWatcher &mock_instance_watcher,
@@ -264,13 +213,6 @@ public:
         }));
   }
 
-  void expect_copy_snapshots(MockSnapshotCopyRequest &mock_snapshot_copy_request, int r) {
-    EXPECT_CALL(mock_snapshot_copy_request, send())
-      .WillOnce(Invoke([this, &mock_snapshot_copy_request, r]() {
-          m_threads->work_queue->queue(mock_snapshot_copy_request.on_finish, r);
-        }));
-  }
-
   void expect_copy_image(MockImageCopyRequest &mock_image_copy_request, int r) {
     EXPECT_CALL(mock_image_copy_request, send())
       .WillOnce(Invoke([this, &mock_image_copy_request, r]() {
@@ -278,35 +220,9 @@ public:
         }));
   }
 
-  void expect_copy_metadata(MockMetadataCopyRequest &mock_metadata_copy_request,
-                            int r) {
-    EXPECT_CALL(mock_metadata_copy_request, send())
-      .WillOnce(Invoke([this, &mock_metadata_copy_request, r]() {
-          m_threads->work_queue->queue(mock_metadata_copy_request.on_finish, r);
-        }));
-  }
-
-  void expect_rollback_object_map(librbd::MockObjectMap &mock_object_map, int r) {
-    if ((m_local_image_ctx->features & RBD_FEATURE_OBJECT_MAP) != 0) {
-      EXPECT_CALL(mock_object_map, rollback(_, _))
-        .WillOnce(WithArg<1>(Invoke([this, r](Context *ctx) {
-            m_threads->work_queue->queue(ctx, r);
-          })));
-    }
-  }
-
-  void expect_create_object_map(librbd::MockTestImageCtx &mock_image_ctx,
-                                librbd::MockObjectMap *mock_object_map) {
-    EXPECT_CALL(mock_image_ctx, create_object_map(CEPH_NOSNAP))
-      .WillOnce(Return(mock_object_map));
-  }
-
-  void expect_open_object_map(librbd::MockTestImageCtx &mock_image_ctx,
-                              librbd::MockObjectMap &mock_object_map) {
-    EXPECT_CALL(mock_object_map, open(_))
-      .WillOnce(Invoke([this](Context *ctx) {
-          m_threads->work_queue->queue(ctx, 0);
-        }));
+  void expect_flush_sync_point(journal::MockJournaler &mock_journaler, int r) {
+    EXPECT_CALL(mock_journaler, update_client(_, _))
+      .WillOnce(WithArg<1>(CompleteContext(r)));
   }
 
   void expect_prune_sync_point(MockSyncPointPruneRequest &mock_sync_point_prune_request,
@@ -350,29 +266,16 @@ TEST_F(TestMockImageSync, SimpleSync) {
   journal::MockJournaler mock_journaler;
   MockInstanceWatcher mock_instance_watcher;
   MockImageCopyRequest mock_image_copy_request;
-  MockSnapshotCopyRequest mock_snapshot_copy_request;
   MockSyncPointCreateRequest mock_sync_point_create_request;
   MockSyncPointPruneRequest mock_sync_point_prune_request;
-  MockMetadataCopyRequest mock_metadata_copy_request;
-
-  librbd::MockExclusiveLock mock_exclusive_lock;
-  mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
-
-  librbd::MockObjectMap *mock_object_map = new librbd::MockObjectMap();
-  mock_local_image_ctx.object_map = mock_object_map;
-  expect_test_features(mock_local_image_ctx);
 
   InSequence seq;
   expect_notify_sync_request(mock_instance_watcher, mock_local_image_ctx.id, 0);
   expect_create_sync_point(mock_local_image_ctx, mock_sync_point_create_request, 0);
-  expect_copy_snapshots(mock_snapshot_copy_request, 0);
+  expect_get_snap_id(mock_remote_image_ctx);
   expect_copy_image(mock_image_copy_request, 0);
-  expect_start_op(mock_exclusive_lock);
-  expect_rollback_object_map(*mock_object_map, 0);
-  expect_create_object_map(mock_local_image_ctx, mock_object_map);
-  expect_open_object_map(mock_local_image_ctx, *mock_object_map);
+  expect_flush_sync_point(mock_journaler, 0);
   expect_prune_sync_point(mock_sync_point_prune_request, true, 0);
-  expect_copy_metadata(mock_metadata_copy_request, 0);
   expect_notify_sync_complete(mock_instance_watcher, mock_local_image_ctx.id);
 
   C_SaferCond ctx;
@@ -389,34 +292,23 @@ TEST_F(TestMockImageSync, RestartSync) {
   journal::MockJournaler mock_journaler;
   MockInstanceWatcher mock_instance_watcher;
   MockImageCopyRequest mock_image_copy_request;
-  MockSnapshotCopyRequest mock_snapshot_copy_request;
   MockSyncPointCreateRequest mock_sync_point_create_request;
   MockSyncPointPruneRequest mock_sync_point_prune_request;
-  MockMetadataCopyRequest mock_metadata_copy_request;
 
   m_client_meta.sync_points = {{cls::rbd::UserSnapshotNamespace(), "snap1", boost::none},
                                {cls::rbd::UserSnapshotNamespace(), "snap2", "snap1", boost::none}};
   mock_local_image_ctx.snap_ids[{cls::rbd::UserSnapshotNamespace(), "snap1"}] = 123;
   mock_local_image_ctx.snap_ids[{cls::rbd::UserSnapshotNamespace(), "snap2"}] = 234;
 
-  librbd::MockExclusiveLock mock_exclusive_lock;
-  mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
-
-  librbd::MockObjectMap *mock_object_map = new librbd::MockObjectMap();
-  mock_local_image_ctx.object_map = mock_object_map;
   expect_test_features(mock_local_image_ctx);
 
   InSequence seq;
   expect_notify_sync_request(mock_instance_watcher, mock_local_image_ctx.id, 0);
   expect_prune_sync_point(mock_sync_point_prune_request, false, 0);
-  expect_copy_snapshots(mock_snapshot_copy_request, 0);
+  expect_get_snap_id(mock_remote_image_ctx);
   expect_copy_image(mock_image_copy_request, 0);
-  expect_start_op(mock_exclusive_lock);
-  expect_rollback_object_map(*mock_object_map, 0);
-  expect_create_object_map(mock_local_image_ctx, mock_object_map);
-  expect_open_object_map(mock_local_image_ctx, *mock_object_map);
+  expect_flush_sync_point(mock_journaler, 0);
   expect_prune_sync_point(mock_sync_point_prune_request, true, 0);
-  expect_copy_metadata(mock_metadata_copy_request, 0);
   expect_notify_sync_complete(mock_instance_watcher, mock_local_image_ctx.id);
 
   C_SaferCond ctx;
@@ -472,19 +364,15 @@ TEST_F(TestMockImageSync, CancelImageCopy) {
   journal::MockJournaler mock_journaler;
   MockInstanceWatcher mock_instance_watcher;
   MockImageCopyRequest mock_image_copy_request;
-  MockSnapshotCopyRequest mock_snapshot_copy_request;
   MockSyncPointCreateRequest mock_sync_point_create_request;
   MockSyncPointPruneRequest mock_sync_point_prune_request;
 
-  librbd::MockExclusiveLock mock_exclusive_lock;
-  mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
-
   m_client_meta.sync_points = {{cls::rbd::UserSnapshotNamespace(), "snap1", boost::none}};
 
   InSequence seq;
   expect_notify_sync_request(mock_instance_watcher, mock_local_image_ctx.id, 0);
   expect_prune_sync_point(mock_sync_point_prune_request, false, 0);
-  expect_copy_snapshots(mock_snapshot_copy_request, 0);
+  expect_get_snap_id(mock_remote_image_ctx);
 
   C_SaferCond image_copy_ctx;
   EXPECT_CALL(mock_image_copy_request, send())
@@ -512,61 +400,15 @@ TEST_F(TestMockImageSync, CancelImageCopy) {
   ASSERT_EQ(-ECANCELED, ctx.wait());
 }
 
-TEST_F(TestMockImageSync, CancelAfterCopySnapshots) {
-  librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
-  librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
-  journal::MockJournaler mock_journaler;
-  MockInstanceWatcher mock_instance_watcher;
-  MockSnapshotCopyRequest mock_snapshot_copy_request;
-  MockSyncPointCreateRequest mock_sync_point_create_request;
-
-  librbd::MockExclusiveLock mock_exclusive_lock;
-  mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
-
-  librbd::MockObjectMap *mock_object_map = new librbd::MockObjectMap();
-  mock_local_image_ctx.object_map = mock_object_map;
-  expect_test_features(mock_local_image_ctx);
-
-  C_SaferCond ctx;
-  MockImageSync *request = create_request(mock_remote_image_ctx,
-                                          mock_local_image_ctx, mock_journaler,
-                                          mock_instance_watcher, &ctx);
-  InSequence seq;
-  expect_notify_sync_request(mock_instance_watcher, mock_local_image_ctx.id, 0);
-  expect_create_sync_point(mock_local_image_ctx, mock_sync_point_create_request, 0);
-  EXPECT_CALL(mock_snapshot_copy_request, send())
-    .WillOnce((DoAll(InvokeWithoutArgs([request]() {
-             request->cancel();
-           }),
-         Invoke([this, &mock_snapshot_copy_request]() {
-             m_threads->work_queue->queue(mock_snapshot_copy_request.on_finish, 0);
-           }))));
-  expect_cancel_sync_request(mock_instance_watcher, mock_local_image_ctx.id,
-                             false);
-  EXPECT_CALL(mock_snapshot_copy_request, cancel());
-  expect_notify_sync_complete(mock_instance_watcher, mock_local_image_ctx.id);
-
-  request->send();
-  ASSERT_EQ(-ECANCELED, ctx.wait());
-}
-
 TEST_F(TestMockImageSync, CancelAfterCopyImage) {
   librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
   librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
   journal::MockJournaler mock_journaler;
   MockInstanceWatcher mock_instance_watcher;
   MockImageCopyRequest mock_image_copy_request;
-  MockSnapshotCopyRequest mock_snapshot_copy_request;
   MockSyncPointCreateRequest mock_sync_point_create_request;
   MockSyncPointPruneRequest mock_sync_point_prune_request;
 
-  librbd::MockExclusiveLock mock_exclusive_lock;
-  mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
-
-  librbd::MockObjectMap *mock_object_map = new librbd::MockObjectMap();
-  mock_local_image_ctx.object_map = mock_object_map;
-  expect_test_features(mock_local_image_ctx);
-
   C_SaferCond ctx;
   MockImageSync *request = create_request(mock_remote_image_ctx,
                                           mock_local_image_ctx, mock_journaler,
@@ -574,7 +416,7 @@ TEST_F(TestMockImageSync, CancelAfterCopyImage) {
   InSequence seq;
   expect_notify_sync_request(mock_instance_watcher, mock_local_image_ctx.id, 0);
   expect_create_sync_point(mock_local_image_ctx, mock_sync_point_create_request, 0);
-  expect_copy_snapshots(mock_snapshot_copy_request, 0);
+  expect_get_snap_id(mock_remote_image_ctx);
   EXPECT_CALL(mock_image_copy_request, send())
     .WillOnce((DoAll(InvokeWithoutArgs([request]() {
              request->cancel();
index 78a6e330d94a112a1d6c1909a2efb0235872f162..103969d892531eed794d26ed5684e2f2c27b7d7b 100644 (file)
@@ -32,11 +32,6 @@ set(rbd_mirror_internal
   image_replayer/PrepareLocalImageRequest.cc
   image_replayer/PrepareRemoteImageRequest.cc
   image_replayer/ReplayStatusFormatter.cc
-  image_sync/ImageCopyRequest.cc
-  image_sync/MetadataCopyRequest.cc
-  image_sync/ObjectCopyRequest.cc
-  image_sync/SnapshotCopyRequest.cc
-  image_sync/SnapshotCreateRequest.cc
   image_sync/SyncPointCreateRequest.cc
   image_sync/SyncPointPruneRequest.cc
   pool_watcher/RefreshImagesRequest.cc
index 94df5a8aac62247b17f53c5cc674a73fc57d02ab..5c50b5fc79e5e87a9e1a08383682bbb912fd77f2 100644 (file)
@@ -4,16 +4,15 @@
 #include "ImageSync.h"
 #include "InstanceWatcher.h"
 #include "ProgressContext.h"
+#include "common/Timer.h"
 #include "common/errno.h"
 #include "journal/Journaler.h"
-#include "librbd/ExclusiveLock.h"
+#include "librbd/DeepCopyRequest.h"
 #include "librbd/ImageCtx.h"
-#include "librbd/ObjectMap.h"
+#include "librbd/ImageState.h"
 #include "librbd/Utils.h"
+#include "librbd/internal.h"
 #include "librbd/journal/Types.h"
-#include "tools/rbd_mirror/image_sync/ImageCopyRequest.h"
-#include "tools/rbd_mirror/image_sync/MetadataCopyRequest.h"
-#include "tools/rbd_mirror/image_sync/SnapshotCopyRequest.h"
 #include "tools/rbd_mirror/image_sync/SyncPointCreateRequest.h"
 #include "tools/rbd_mirror/image_sync/SyncPointPruneRequest.h"
 
@@ -30,6 +29,20 @@ using namespace image_sync;
 using librbd::util::create_context_callback;
 using librbd::util::unique_lock_name;
 
+template <typename I>
+class ImageSync<I>::ImageCopyProgressContext : public librbd::ProgressContext {
+public:
+  ImageCopyProgressContext(ImageSync *image_sync) : image_sync(image_sync) {
+  }
+
+  int update_progress(uint64_t object_no, uint64_t object_count) override {
+    image_sync->handle_copy_image_update_progress(object_no, object_count);
+    return 0;
+  }
+
+  ImageSync *image_sync;
+};
+
 template <typename I>
 ImageSync<I>::ImageSync(I *local_image_ctx, I *remote_image_ctx,
                         SafeTimer *timer, Mutex *timer_lock,
@@ -44,13 +57,16 @@ ImageSync<I>::ImageSync(I *local_image_ctx, I *remote_image_ctx,
     m_journaler(journaler), m_client_meta(client_meta),
     m_work_queue(work_queue), m_instance_watcher(instance_watcher),
     m_progress_ctx(progress_ctx),
-    m_lock(unique_lock_name("ImageSync::m_lock", this)) {
+    m_lock(unique_lock_name("ImageSync::m_lock", this)),
+    m_update_sync_point_interval(m_local_image_ctx->cct->_conf->template get_val<double>(
+        "rbd_mirror_sync_point_update_age")), m_client_meta_copy(*client_meta) {
 }
 
 template <typename I>
 ImageSync<I>::~ImageSync() {
-  assert(m_snapshot_copy_request == nullptr);
   assert(m_image_copy_request == nullptr);
+  assert(m_image_copy_prog_ctx == nullptr);
+  assert(m_update_sync_ctx == nullptr);
 }
 
 template <typename I>
@@ -70,10 +86,6 @@ void ImageSync<I>::cancel() {
     return;
   }
 
-  if (m_snapshot_copy_request != nullptr) {
-    m_snapshot_copy_request->cancel();
-  }
-
   if (m_image_copy_request != nullptr) {
     m_image_copy_request->cancel();
   }
@@ -144,7 +156,7 @@ void ImageSync<I>::send_create_sync_point() {
   // TODO: when support for disconnecting laggy clients is added,
   //       re-connect and create catch-up sync point
   if (m_client_meta->sync_points.size() > 0) {
-    send_copy_snapshots();
+    send_copy_image();
     return;
   }
 
@@ -168,61 +180,40 @@ void ImageSync<I>::handle_create_sync_point(int r) {
     return;
   }
 
-  send_copy_snapshots();
-}
-
-template <typename I>
-void ImageSync<I>::send_copy_snapshots() {
-  m_lock.Lock();
-  if (m_canceled) {
-    m_lock.Unlock();
-    finish(-ECANCELED);
-    return;
-  }
-
-  dout(20) << dendl;
-
-  Context *ctx = create_context_callback<
-    ImageSync<I>, &ImageSync<I>::handle_copy_snapshots>(this);
-  m_snapshot_copy_request = SnapshotCopyRequest<I>::create(
-    m_local_image_ctx, m_remote_image_ctx, &m_snap_map, m_journaler,
-    m_client_meta, m_work_queue, ctx);
-  m_snapshot_copy_request->get();
-  m_lock.Unlock();
-
-  update_progress("COPY_SNAPSHOTS");
-
-  m_snapshot_copy_request->send();
+  send_copy_image();
 }
 
 template <typename I>
-void ImageSync<I>::handle_copy_snapshots(int r) {
-  dout(20) << ": r=" << r << dendl;
-
+void ImageSync<I>::send_copy_image() {
+  librados::snap_t snap_id_start = 0;
+  librados::snap_t snap_id_end;
+  librbd::deep_copy::ObjectNumber object_number;
+  int r = 0;
   {
-    Mutex::Locker locker(m_lock);
-    m_snapshot_copy_request->put();
-    m_snapshot_copy_request = nullptr;
-    if (r == 0 && m_canceled) {
-      r = -ECANCELED;
+    RWLock::RLocker snap_locker(m_remote_image_ctx->snap_lock);
+    assert(!m_client_meta->sync_points.empty());
+    auto &sync_point = m_client_meta->sync_points.front();
+    snap_id_end = m_remote_image_ctx->get_snap_id(
+       cls::rbd::UserSnapshotNamespace(), sync_point.snap_name);
+    if (snap_id_end == CEPH_NOSNAP) {
+      derr << ": failed to locate snapshot: " << sync_point.snap_name << dendl;
+      r = -ENOENT;
+    } else if (!sync_point.from_snap_name.empty()) {
+      snap_id_start = m_remote_image_ctx->get_snap_id(
+        cls::rbd::UserSnapshotNamespace(), sync_point.from_snap_name);
+      if (snap_id_start == CEPH_NOSNAP) {
+        derr << ": failed to locate from snapshot: "
+             << sync_point.from_snap_name << dendl;
+        r = -ENOENT;
+      }
     }
+    object_number = sync_point.object_number;
   }
-
-  if (r == -ECANCELED) {
-    dout(10) << ": snapshot copy canceled" << dendl;
-    finish(r);
-    return;
-  } else if (r < 0) {
-    derr << ": failed to copy snapshot metadata: " << cpp_strerror(r) << dendl;
+  if (r < 0) {
     finish(r);
     return;
   }
 
-  send_copy_image();
-}
-
-template <typename I>
-void ImageSync<I>::send_copy_image() {
   m_lock.Lock();
   if (m_canceled) {
     m_lock.Unlock();
@@ -234,10 +225,11 @@ void ImageSync<I>::send_copy_image() {
 
   Context *ctx = create_context_callback<
     ImageSync<I>, &ImageSync<I>::handle_copy_image>(this);
-  m_image_copy_request = ImageCopyRequest<I>::create(
-    m_local_image_ctx, m_remote_image_ctx, m_timer, m_timer_lock,
-    m_journaler, m_client_meta, &m_client_meta->sync_points.front(),
-    ctx, m_progress_ctx);
+  m_image_copy_prog_ctx = new ImageCopyProgressContext(this);
+  m_image_copy_request = librbd::DeepCopyRequest<I>::create(
+      m_remote_image_ctx, m_local_image_ctx, snap_id_start, snap_id_end,
+      object_number, m_work_queue, &m_client_meta->snap_seqs,
+      m_image_copy_prog_ctx, ctx);
   m_image_copy_request->get();
   m_lock.Unlock();
 
@@ -251,12 +243,25 @@ void ImageSync<I>::handle_copy_image(int r) {
   dout(20) << ": r=" << r << dendl;
 
   {
+    Mutex::Locker timer_locker(*m_timer_lock);
     Mutex::Locker locker(m_lock);
     m_image_copy_request->put();
     m_image_copy_request = nullptr;
+    delete m_image_copy_prog_ctx;
+    m_image_copy_prog_ctx = nullptr;
     if (r == 0 && m_canceled) {
       r = -ECANCELED;
     }
+
+    if (m_update_sync_ctx != nullptr) {
+      m_timer->cancel_event(m_update_sync_ctx);
+      m_update_sync_ctx = nullptr;
+    }
+
+    if (m_updating_sync_point) {
+      m_ret_val = r;
+      return;
+    }
   }
 
   if (r == -ECANCELED) {
@@ -269,89 +274,136 @@ void ImageSync<I>::handle_copy_image(int r) {
     return;
   }
 
-  send_copy_object_map();
+  send_flush_sync_point();
 }
 
 template <typename I>
-void ImageSync<I>::send_copy_object_map() {
-  update_progress("COPY_OBJECT_MAP");
-
-  m_local_image_ctx->owner_lock.get_read();
-  m_local_image_ctx->snap_lock.get_read();
-  if (!m_local_image_ctx->test_features(RBD_FEATURE_OBJECT_MAP,
-                                        m_local_image_ctx->snap_lock)) {
-    m_local_image_ctx->snap_lock.put_read();
-    m_local_image_ctx->owner_lock.put_read();
-    send_prune_sync_points();
-    return;
-  }
+void ImageSync<I>::handle_copy_image_update_progress(uint64_t object_no,
+                                                     uint64_t object_count) {
+  int percent = 100 * object_no / object_count;
+  update_progress("COPY_IMAGE " + stringify(percent) + "%");
 
-  assert(m_local_image_ctx->object_map != nullptr);
+  Mutex::Locker locker(m_lock);
+  m_image_copy_object_no = object_no;
+  m_image_copy_object_count = object_count;
+
+  if (m_update_sync_ctx == nullptr && !m_updating_sync_point) {
+    send_update_sync_point();
+  }
+}
 
-  assert(!m_client_meta->sync_points.empty());
-  librbd::journal::MirrorPeerSyncPoint &sync_point =
-    m_client_meta->sync_points.front();
-  auto snap_id_it = m_local_image_ctx->snap_ids.find(
-    {cls::rbd::UserSnapshotNamespace(), sync_point.snap_name});
-  assert(snap_id_it != m_local_image_ctx->snap_ids.end());
-  librados::snap_t snap_id = snap_id_it->second;
+template <typename I>
+void ImageSync<I>::send_update_sync_point() {
+  assert(m_lock.is_locked());
 
-  dout(20) << ": snap_id=" << snap_id << ", "
-           << "snap_name=" << sync_point.snap_name << dendl;
+  m_update_sync_ctx = nullptr;
 
-  Context *finish_op_ctx = nullptr;
-  if (m_local_image_ctx->exclusive_lock != nullptr) {
-    finish_op_ctx = m_local_image_ctx->exclusive_lock->start_op();
+  if (m_canceled) {
+    return;
   }
-  if (finish_op_ctx == nullptr) {
-    derr << ": lost exclusive lock" << dendl;
-    m_local_image_ctx->snap_lock.put_read();
-    m_local_image_ctx->owner_lock.put_read();
-    finish(-EROFS);
+
+  auto sync_point = &m_client_meta->sync_points.front();
+
+  if (m_client_meta->sync_object_count == m_image_copy_object_count &&
+      sync_point->object_number &&
+      (m_image_copy_object_no - 1) == sync_point->object_number.get()) {
+    // update sync point did not progress since last sync
     return;
   }
 
-  // rollback the object map (copy snapshot object map to HEAD)
-  RWLock::WLocker object_map_locker(m_local_image_ctx->object_map_lock);
-  auto ctx = new FunctionContext([this, finish_op_ctx](int r) {
-      handle_copy_object_map(r);
-      finish_op_ctx->complete(0);
-    });
-  m_local_image_ctx->object_map->rollback(snap_id, ctx);
-  m_local_image_ctx->snap_lock.put_read();
-  m_local_image_ctx->owner_lock.put_read();
+  m_updating_sync_point = true;
+
+  m_client_meta_copy = *m_client_meta;
+  m_client_meta->sync_object_count = m_image_copy_object_count;
+  if (m_image_copy_object_no > 0) {
+    sync_point->object_number = m_image_copy_object_no - 1;
+  }
+
+  CephContext *cct = m_local_image_ctx->cct;
+  ldout(cct, 20) << ": sync_point=" << *sync_point << dendl;
+
+  bufferlist client_data_bl;
+  librbd::journal::ClientData client_data(*m_client_meta);
+  ::encode(client_data, client_data_bl);
+
+  Context *ctx = create_context_callback<
+    ImageSync<I>, &ImageSync<I>::handle_update_sync_point>(
+      this);
+  m_journaler->update_client(client_data_bl, ctx);
 }
 
 template <typename I>
-void ImageSync<I>::handle_copy_object_map(int r) {
-  dout(20) << dendl;
+void ImageSync<I>::handle_update_sync_point(int r) {
+  CephContext *cct = m_local_image_ctx->cct;
+  ldout(cct, 20) << ": r=" << r << dendl;
 
-  assert(r == 0);
-  send_refresh_object_map();
+  if (r < 0) {
+    *m_client_meta = m_client_meta_copy;
+    lderr(cct) << ": failed to update client data: " << cpp_strerror(r)
+               << dendl;
+  }
+
+  {
+    Mutex::Locker timer_locker(*m_timer_lock);
+    Mutex::Locker locker(m_lock);
+    m_updating_sync_point = false;
+
+    if (m_image_copy_request != nullptr) {
+      m_update_sync_ctx = new FunctionContext(
+        [this](int r) {
+          this->send_update_sync_point();
+        });
+      m_timer->add_event_after(m_update_sync_point_interval,
+                               m_update_sync_ctx);
+      return;
+    }
+  }
+
+  send_flush_sync_point();
 }
 
 template <typename I>
-void ImageSync<I>::send_refresh_object_map() {
-  dout(20) << dendl;
+void ImageSync<I>::send_flush_sync_point() {
+  if (m_ret_val < 0) {
+    finish(m_ret_val);
+    return;
+  }
+
+  update_progress("FLUSH_SYNC_POINT");
+
+  m_client_meta_copy = *m_client_meta;
+  m_client_meta->sync_object_count = m_image_copy_object_count;
+  auto sync_point = &m_client_meta->sync_points.front();
+  if (m_image_copy_object_no > 0) {
+    sync_point->object_number = m_image_copy_object_no - 1;
+  } else {
+    sync_point->object_number = boost::none;
+  }
+
+  dout(20) << ": sync_point=" << *sync_point << dendl;
 
-  update_progress("REFRESH_OBJECT_MAP");
+  bufferlist client_data_bl;
+  librbd::journal::ClientData client_data(*m_client_meta);
+  ::encode(client_data, client_data_bl);
 
   Context *ctx = create_context_callback<
-    ImageSync<I>, &ImageSync<I>::handle_refresh_object_map>(this);
-  m_object_map = m_local_image_ctx->create_object_map(CEPH_NOSNAP);
-  m_object_map->open(ctx);
+    ImageSync<I>, &ImageSync<I>::handle_flush_sync_point>(
+      this);
+  m_journaler->update_client(client_data_bl, ctx);
 }
 
 template <typename I>
-void ImageSync<I>::handle_refresh_object_map(int r) {
-  dout(20) << dendl;
+void ImageSync<I>::handle_flush_sync_point(int r) {
+  dout(20) << ": r=" << r << dendl;
 
-  assert(r == 0);
-  {
-    RWLock::WLocker snap_locker(m_local_image_ctx->snap_lock);
-    std::swap(m_local_image_ctx->object_map, m_object_map);
+  if (r < 0) {
+    *m_client_meta = m_client_meta_copy;
+
+    derr << ": failed to update client data: " << cpp_strerror(r)
+         << dendl;
+    finish(r);
+    return;
   }
-  delete m_object_map;
 
   send_prune_sync_points();
 }
@@ -385,30 +437,6 @@ void ImageSync<I>::handle_prune_sync_points(int r) {
     return;
   }
 
-  send_copy_metadata();
-}
-
-template <typename I>
-void ImageSync<I>::send_copy_metadata() {
-  dout(20) << dendl;
-  update_progress("COPY_METADATA");
-
-  Context *ctx = create_context_callback<
-    ImageSync<I>, &ImageSync<I>::handle_copy_metadata>(this);
-  auto request = MetadataCopyRequest<I>::create(
-    m_local_image_ctx, m_remote_image_ctx, ctx);
-  request->send();
-}
-
-template <typename I>
-void ImageSync<I>::handle_copy_metadata(int r) {
-  dout(20) << ": r=" << r << dendl;
-  if (r < 0) {
-    derr << ": failed to copy metadata: " << cpp_strerror(r) << dendl;
-    finish(r);
-    return;
-  }
-
   finish(0);
 }
 
index 7e836b716f71664e2c26a6abe25a0f5c486bff9a..9e00c1290cf58895d438c168a246110786c2b408 100644 (file)
@@ -7,6 +7,7 @@
 #include "include/int_types.h"
 #include "librbd/ImageCtx.h"
 #include "librbd/journal/TypeTraits.h"
+#include "librbd/journal/Types.h"
 #include "common/Mutex.h"
 #include "tools/rbd_mirror/BaseRequest.h"
 #include <map>
@@ -14,9 +15,9 @@
 
 class Context;
 class ContextWQ;
-class Mutex;
-class SafeTimer;
 namespace journal { class Journaler; }
+namespace librbd { class ProgressContext; }
+namespace librbd { template <typename> class DeepCopyRequest; }
 namespace librbd { namespace journal { struct MirrorPeerClientMeta; } }
 
 namespace rbd {
@@ -26,9 +27,6 @@ class ProgressContext;
 
 template <typename> class InstanceWatcher;
 
-namespace image_sync { template <typename> class ImageCopyRequest; }
-namespace image_sync { template <typename> class SnapshotCopyRequest; }
-
 template <typename ImageCtxT = librbd::ImageCtx>
 class ImageSync : public BaseRequest {
 public:
@@ -37,8 +35,9 @@ public:
   typedef librbd::journal::MirrorPeerClientMeta MirrorPeerClientMeta;
 
   static ImageSync* create(ImageCtxT *local_image_ctx,
-                           ImageCtxT *remote_image_ctx, SafeTimer *timer,
-                           Mutex *timer_lock, const std::string &mirror_uuid,
+                           ImageCtxT *remote_image_ctx,
+                           SafeTimer *timer, Mutex *timer_lock,
+                           const std::string &mirror_uuid,
                            Journaler *journaler,
                            MirrorPeerClientMeta *client_meta,
                            ContextWQ *work_queue,
@@ -79,22 +78,13 @@ private:
    * CREATE_SYNC_POINT (skip if already exists and
    *    |               not disconnected)
    *    v
-   * COPY_SNAPSHOTS
-   *    |
-   *    v
    * COPY_IMAGE . . . . . . . . . . . . . .
    *    |                                 .
    *    v                                 .
-   * COPY_OBJECT_MAP (skip if object      .
-   *    |             map disabled)       .
-   *    v                                 .
-   * REFRESH_OBJECT_MAP (skip if object   .
-   *    |                map disabled)    .
-   *    v                                 .
-   * PRUNE_SYNC_POINTS                    . (image sync canceled)
-   *    |                                 .
+   * FLUSH_SYNC_POINT                     .
+   *    |                                 . (image sync canceled)
    *    v                                 .
-   * COPY_METADATA                        .
+   * PRUNE_SYNC_POINTS                    .
    *    |                                 .
    *    v                                 .
    * <finish> < . . . . . . . . . . . . . .
@@ -104,6 +94,7 @@ private:
 
   typedef std::vector<librados::snap_t> SnapIds;
   typedef std::map<librados::snap_t, SnapIds> SnapMap;
+  class ImageCopyProgressContext;
 
   ImageCtxT *m_local_image_ctx;
   ImageCtxT *m_remote_image_ctx;
@@ -121,9 +112,17 @@ private:
   Mutex m_lock;
   bool m_canceled = false;
 
-  image_sync::SnapshotCopyRequest<ImageCtxT> *m_snapshot_copy_request = nullptr;
-  image_sync::ImageCopyRequest<ImageCtxT> *m_image_copy_request = nullptr;
-  decltype(ImageCtxT::object_map) m_object_map = nullptr;
+  librbd::DeepCopyRequest<ImageCtxT> *m_image_copy_request = nullptr;
+  librbd::ProgressContext *m_image_copy_prog_ctx = nullptr;
+
+  bool m_updating_sync_point = false;
+  Context *m_update_sync_ctx = nullptr;
+  double m_update_sync_point_interval;
+  uint64_t m_image_copy_object_no = 0;
+  uint64_t m_image_copy_object_count = 0;
+  MirrorPeerClientMeta m_client_meta_copy;
+
+  int m_ret_val = 0;
 
   void send_notify_sync_request();
   void handle_notify_sync_request(int r);
@@ -134,24 +133,22 @@ private:
   void send_create_sync_point();
   void handle_create_sync_point(int r);
 
-  void send_copy_snapshots();
-  void handle_copy_snapshots(int r);
+  void send_update_max_object_count();
+  void handle_update_max_object_count(int r);
 
   void send_copy_image();
   void handle_copy_image(int r);
+  void handle_copy_image_update_progress(uint64_t object_no,
+                                         uint64_t object_count);
+  void send_update_sync_point();
+  void handle_update_sync_point(int r);
 
-  void send_copy_object_map();
-  void handle_copy_object_map(int r);
-
-  void send_refresh_object_map();
-  void handle_refresh_object_map(int r);
+  void send_flush_sync_point();
+  void handle_flush_sync_point(int r);
 
   void send_prune_sync_points();
   void handle_prune_sync_points(int r);
 
-  void send_copy_metadata();
-  void handle_copy_metadata(int r);
-
   void update_progress(const std::string &description);
 };
 
diff --git a/src/tools/rbd_mirror/image_sync/ImageCopyRequest.cc b/src/tools/rbd_mirror/image_sync/ImageCopyRequest.cc
deleted file mode 100644 (file)
index 6768caa..0000000
+++ /dev/null
@@ -1,423 +0,0 @@
-// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
-// vim: ts=8 sw=2 smarttab
-
-#include "ImageCopyRequest.h"
-#include "ObjectCopyRequest.h"
-#include "include/stringify.h"
-#include "common/errno.h"
-#include "common/Timer.h"
-#include "journal/Journaler.h"
-#include "librbd/Utils.h"
-#include "tools/rbd_mirror/ProgressContext.h"
-
-#define dout_context g_ceph_context
-#define dout_subsys ceph_subsys_rbd_mirror
-#undef dout_prefix
-#define dout_prefix *_dout << "rbd::mirror::image_sync::ImageCopyRequest: " \
-                           << this << " " << __func__
-
-namespace rbd {
-namespace mirror {
-namespace image_sync {
-
-using librbd::util::create_context_callback;
-using librbd::util::unique_lock_name;
-
-template <typename I>
-ImageCopyRequest<I>::ImageCopyRequest(I *local_image_ctx, I *remote_image_ctx,
-                                      SafeTimer *timer, Mutex *timer_lock,
-                                      Journaler *journaler,
-                                      MirrorPeerClientMeta *client_meta,
-                                      MirrorPeerSyncPoint *sync_point,
-                                      Context *on_finish,
-                                     ProgressContext *progress_ctx)
-  : BaseRequest("rbd::mirror::image_sync::ImageCopyRequest",
-               local_image_ctx->cct, on_finish),
-    m_local_image_ctx(local_image_ctx), m_remote_image_ctx(remote_image_ctx),
-    m_timer(timer), m_timer_lock(timer_lock), m_journaler(journaler),
-    m_client_meta(client_meta), m_sync_point(sync_point),
-    m_progress_ctx(progress_ctx),
-    m_lock(unique_lock_name("ImageCopyRequest::m_lock", this)),
-    m_updating_sync_point(false), m_update_sync_ctx(nullptr),
-    m_update_sync_point_interval(m_local_image_ctx->cct->_conf->template get_val<double>(
-      "rbd_mirror_sync_point_update_age")),
-    m_client_meta_copy(*client_meta) {
-  assert(!m_client_meta_copy.sync_points.empty());
-}
-
-template <typename I>
-void ImageCopyRequest<I>::send() {
-  int r = compute_snap_map();
-  if (r < 0) {
-    finish(r);
-    return;
-  }
-
-  send_update_max_object_count();
-}
-
-template <typename I>
-void ImageCopyRequest<I>::cancel() {
-  Mutex::Locker locker(m_lock);
-
-  dout(20) << dendl;
-  m_canceled = true;
-}
-
-template <typename I>
-void ImageCopyRequest<I>::send_update_max_object_count() {
-  uint64_t max_objects = m_client_meta->sync_object_count;
-  {
-    RWLock::RLocker snap_locker(m_remote_image_ctx->snap_lock);
-    max_objects = std::max(max_objects,
-                           m_remote_image_ctx->get_object_count(CEPH_NOSNAP));
-    for (auto snap_id : m_remote_image_ctx->snaps) {
-      max_objects = std::max(max_objects,
-                             m_remote_image_ctx->get_object_count(snap_id));
-    }
-  }
-
-  if (max_objects <= m_client_meta->sync_object_count) {
-    send_object_copies();
-    return;
-  }
-
-  update_progress("UPDATE_MAX_OBJECT_COUNT");
-
-  dout(20) << ": sync_object_count=" << max_objects << dendl;
-
-  m_client_meta_copy = *m_client_meta;
-  m_client_meta_copy.sync_object_count = max_objects;
-
-  bufferlist client_data_bl;
-  librbd::journal::ClientData client_data(m_client_meta_copy);
-  ::encode(client_data, client_data_bl);
-
-  Context *ctx = create_context_callback<
-    ImageCopyRequest<I>, &ImageCopyRequest<I>::handle_update_max_object_count>(
-      this);
-  m_journaler->update_client(client_data_bl, ctx);
-}
-
-template <typename I>
-void ImageCopyRequest<I>::handle_update_max_object_count(int r) {
-  dout(20) << ": r=" << r << dendl;
-
-  if (r == 0) {
-    Mutex::Locker locker(m_lock);
-    if (m_canceled) {
-      dout(10) << ": image copy canceled" << dendl;
-      r = -ECANCELED;
-    }
-  }
-
-  if (r < 0) {
-    if (r != -ECANCELED) {
-      derr << ": failed to update client data: " << cpp_strerror(r) << dendl;
-    }
-    finish(r);
-    return;
-  }
-
-  // update provided meta structure to reflect reality
-  m_client_meta->sync_object_count = m_client_meta_copy.sync_object_count;
-
-  send_object_copies();
-}
-
-template <typename I>
-void ImageCopyRequest<I>::send_object_copies() {
-  CephContext *cct = m_local_image_ctx->cct;
-
-  m_object_no = 0;
-  if (m_sync_point->object_number) {
-    m_object_no = *m_sync_point->object_number + 1;
-  }
-  m_end_object_no = m_client_meta->sync_object_count;
-
-  dout(20) << ": start_object=" << m_object_no << ", "
-           << "end_object=" << m_end_object_no << dendl;
-
-  update_progress("COPY_OBJECT");
-
-  bool complete;
-  {
-    Mutex::Locker locker(m_lock);
-    for (int i = 0; i < cct->_conf->get_val<int64_t>("rbd_concurrent_management_ops"); ++i) {
-      send_next_object_copy();
-      if (m_ret_val < 0 && m_current_ops == 0) {
-        break;
-      }
-    }
-    complete = (m_current_ops == 0);
-
-    if (!complete) {
-      m_update_sync_ctx = new FunctionContext([this](int r) {
-          this->send_update_sync_point();
-      });
-    }
-  }
-
-  {
-    Mutex::Locker timer_locker(*m_timer_lock);
-    if (m_update_sync_ctx) {
-      m_update_sync_ctx = m_timer->add_event_after(
-        m_update_sync_point_interval,
-       m_update_sync_ctx);
-    }
-  }
-
-  if (complete) {
-    send_flush_sync_point();
-  }
-}
-
-template <typename I>
-void ImageCopyRequest<I>::send_next_object_copy() {
-  assert(m_lock.is_locked());
-
-  if (m_canceled && m_ret_val == 0) {
-    dout(10) << ": image copy canceled" << dendl;
-    m_ret_val = -ECANCELED;
-  }
-
-  if (m_ret_val < 0 || m_object_no >= m_end_object_no) {
-    return;
-  }
-
-  uint64_t ono = m_object_no++;
-
-  dout(20) << ": object_num=" << ono << dendl;
-
-  ++m_current_ops;
-
-  Context *ctx = create_context_callback<
-    ImageCopyRequest<I>, &ImageCopyRequest<I>::handle_object_copy>(this);
-  ObjectCopyRequest<I> *req = ObjectCopyRequest<I>::create(
-    m_local_image_ctx, m_remote_image_ctx, &m_snap_map, ono, ctx);
-  req->send();
-}
-
-template <typename I>
-void ImageCopyRequest<I>::handle_object_copy(int r) {
-  dout(20) << ": r=" << r << dendl;
-
-  int percent;
-  bool complete;
-  {
-    Mutex::Locker locker(m_lock);
-    assert(m_current_ops > 0);
-    --m_current_ops;
-
-    percent = 100 * m_object_no / m_end_object_no;
-
-    if (r < 0) {
-      derr << ": object copy failed: " << cpp_strerror(r) << dendl;
-      if (m_ret_val == 0) {
-        m_ret_val = r;
-      }
-    }
-
-    send_next_object_copy();
-    complete = (m_current_ops == 0);
-  }
-
-  update_progress("COPY_OBJECT " + stringify(percent) + "%", false);
-
-  if (complete) {
-    bool do_flush = true;
-    {
-      Mutex::Locker timer_locker(*m_timer_lock);
-      Mutex::Locker locker(m_lock);
-      if (!m_updating_sync_point) {
-        if (m_update_sync_ctx != nullptr) {
-          m_timer->cancel_event(m_update_sync_ctx);
-          m_update_sync_ctx = nullptr;
-        }
-      } else {
-        do_flush = false;
-      }
-    }
-
-    if (do_flush) {
-      send_flush_sync_point();
-    }
-  }
-}
-
-template <typename I>
-void ImageCopyRequest<I>::send_update_sync_point() {
-  Mutex::Locker l(m_lock);
-
-  m_update_sync_ctx = nullptr;
-
-  if (m_canceled || m_ret_val < 0 || m_current_ops == 0) {
-    return;
-  }
-
-  if (m_sync_point->object_number &&
-      (m_object_no-1) == m_sync_point->object_number.get()) {
-    // update sync point did not progress since last sync
-    return;
-  }
-
-  m_updating_sync_point = true;
-
-  m_client_meta_copy = *m_client_meta;
-  m_sync_point->object_number = m_object_no - 1;
-
-  CephContext *cct = m_local_image_ctx->cct;
-  ldout(cct, 20) << ": sync_point=" << *m_sync_point << dendl;
-
-  bufferlist client_data_bl;
-  librbd::journal::ClientData client_data(*m_client_meta);
-  ::encode(client_data, client_data_bl);
-
-  Context *ctx = create_context_callback<
-    ImageCopyRequest<I>, &ImageCopyRequest<I>::handle_update_sync_point>(
-      this);
-  m_journaler->update_client(client_data_bl, ctx);
-}
-
-template <typename I>
-void ImageCopyRequest<I>::handle_update_sync_point(int r) {
-  CephContext *cct = m_local_image_ctx->cct;
-  ldout(cct, 20) << ": r=" << r << dendl;
-
-  if (r < 0) {
-    *m_client_meta = m_client_meta_copy;
-    lderr(cct) << ": failed to update client data: " << cpp_strerror(r)
-               << dendl;
-  }
-
-  bool complete;
-  {
-    Mutex::Locker l(m_lock);
-    m_updating_sync_point = false;
-
-    complete = m_current_ops == 0 || m_canceled || m_ret_val < 0;
-
-    if (!complete) {
-      m_update_sync_ctx = new FunctionContext([this](int r) {
-          this->send_update_sync_point();
-      });
-    }
-  }
-
-  if (!complete) {
-    Mutex::Locker timer_lock(*m_timer_lock);
-    if (m_update_sync_ctx) {
-      m_timer->add_event_after(m_update_sync_point_interval,
-                               m_update_sync_ctx);
-    }
-  } else {
-    send_flush_sync_point();
-  }
-}
-
-template <typename I>
-void ImageCopyRequest<I>::send_flush_sync_point() {
-  if (m_ret_val < 0) {
-    finish(m_ret_val);
-    return;
-  }
-
-  update_progress("FLUSH_SYNC_POINT");
-
-  m_client_meta_copy = *m_client_meta;
-  if (m_object_no > 0) {
-    m_sync_point->object_number = m_object_no - 1;
-  } else {
-    m_sync_point->object_number = boost::none;
-  }
-
-  dout(20) << ": sync_point=" << *m_sync_point << dendl;
-
-  bufferlist client_data_bl;
-  librbd::journal::ClientData client_data(m_client_meta_copy);
-  ::encode(client_data, client_data_bl);
-
-  Context *ctx = create_context_callback<
-    ImageCopyRequest<I>, &ImageCopyRequest<I>::handle_flush_sync_point>(
-      this);
-  m_journaler->update_client(client_data_bl, ctx);
-}
-
-template <typename I>
-void ImageCopyRequest<I>::handle_flush_sync_point(int r) {
-  dout(20) << ": r=" << r << dendl;
-
-  if (r < 0) {
-    *m_client_meta = m_client_meta_copy;
-
-    derr << ": failed to update client data: " << cpp_strerror(r)
-         << dendl;
-    finish(r);
-    return;
-  }
-
-  finish(0);
-}
-
-template <typename I>
-int ImageCopyRequest<I>::compute_snap_map() {
-
-  librados::snap_t snap_id_start = 0;
-  librados::snap_t snap_id_end;
-  {
-    RWLock::RLocker snap_locker(m_remote_image_ctx->snap_lock);
-    snap_id_end = m_remote_image_ctx->get_snap_id(
-       cls::rbd::UserSnapshotNamespace(), m_sync_point->snap_name);
-    if (snap_id_end == CEPH_NOSNAP) {
-      derr << ": failed to locate snapshot: "
-           << m_sync_point->snap_name << dendl;
-      return -ENOENT;
-    }
-
-    if (!m_sync_point->from_snap_name.empty()) {
-      snap_id_start = m_remote_image_ctx->get_snap_id(
-        cls::rbd::UserSnapshotNamespace(), m_sync_point->from_snap_name);
-      if (snap_id_start == CEPH_NOSNAP) {
-        derr << ": failed to locate from snapshot: "
-             << m_sync_point->from_snap_name << dendl;
-        return -ENOENT;
-      }
-    }
-  }
-
-  SnapIds snap_ids;
-  for (auto it = m_client_meta->snap_seqs.begin();
-       it != m_client_meta->snap_seqs.end(); ++it) {
-    snap_ids.insert(snap_ids.begin(), it->second);
-    if (it->first < snap_id_start) {
-      continue;
-    } else if (it->first > snap_id_end) {
-      break;
-    }
-
-    m_snap_map[it->first] = snap_ids;
-  }
-
-  if (m_snap_map.empty()) {
-    derr << ": failed to map snapshots within boundary" << dendl;
-    return -EINVAL;
-  }
-
-  return 0;
-}
-
-template <typename I>
-void ImageCopyRequest<I>::update_progress(const std::string &description,
-                                         bool flush) {
-  dout(20) << ": " << description << dendl;
-
-  if (m_progress_ctx) {
-    m_progress_ctx->update_progress("IMAGE_COPY/" + description, flush);
-  }
-}
-
-} // namespace image_sync
-} // namespace mirror
-} // namespace rbd
-
-template class rbd::mirror::image_sync::ImageCopyRequest<librbd::ImageCtx>;
diff --git a/src/tools/rbd_mirror/image_sync/ImageCopyRequest.h b/src/tools/rbd_mirror/image_sync/ImageCopyRequest.h
deleted file mode 100644 (file)
index 4be826a..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
-// vim: ts=8 sw=2 smarttab
-
-#ifndef RBD_MIRROR_IMAGE_SYNC_IMAGE_COPY_REQUEST_H
-#define RBD_MIRROR_IMAGE_SYNC_IMAGE_COPY_REQUEST_H
-
-#include "include/int_types.h"
-#include "include/rados/librados.hpp"
-#include "common/Mutex.h"
-#include "librbd/journal/Types.h"
-#include "librbd/journal/TypeTraits.h"
-#include "tools/rbd_mirror/BaseRequest.h"
-#include <map>
-#include <vector>
-
-class Context;
-class SafeTimer;
-namespace journal { class Journaler; }
-namespace librbd { struct ImageCtx; }
-
-namespace rbd {
-namespace mirror {
-
-class ProgressContext;
-
-namespace image_sync {
-
-template <typename ImageCtxT = librbd::ImageCtx>
-class ImageCopyRequest : public BaseRequest {
-public:
-  typedef std::vector<librados::snap_t> SnapIds;
-  typedef std::map<librados::snap_t, SnapIds> SnapMap;
-  typedef librbd::journal::TypeTraits<ImageCtxT> TypeTraits;
-  typedef typename TypeTraits::Journaler Journaler;
-  typedef librbd::journal::MirrorPeerSyncPoint MirrorPeerSyncPoint;
-  typedef librbd::journal::MirrorPeerClientMeta MirrorPeerClientMeta;
-  typedef rbd::mirror::ProgressContext ProgressContext;
-
-  static ImageCopyRequest* create(ImageCtxT *local_image_ctx,
-                                  ImageCtxT *remote_image_ctx,
-                                  SafeTimer *timer, Mutex *timer_lock,
-                                  Journaler *journaler,
-                                  MirrorPeerClientMeta *client_meta,
-                                  MirrorPeerSyncPoint *sync_point,
-                                  Context *on_finish,
-                                 ProgressContext *progress_ctx = nullptr) {
-    return new ImageCopyRequest(local_image_ctx, remote_image_ctx, timer,
-                                timer_lock, journaler, client_meta, sync_point,
-                                on_finish, progress_ctx);
-  }
-
-  ImageCopyRequest(ImageCtxT *local_image_ctx, ImageCtxT *remote_image_ctx,
-                   SafeTimer *timer, Mutex *timer_lock, Journaler *journaler,
-                   MirrorPeerClientMeta *client_meta,
-                   MirrorPeerSyncPoint *sync_point, Context *on_finish,
-                  ProgressContext *progress_ctx = nullptr);
-
-  void send() override;
-  void cancel() override;
-
-private:
-  /**
-   * @verbatim
-   *
-   * <start>
-   *    |
-   *    v
-   * UPDATE_MAX_OBJECT_COUNT
-   *    |
-   *    |   . . . . .
-   *    |   .       .  (parallel execution of
-   *    v   v       .   multiple objects at once)
-   * COPY_OBJECT  . .
-   *    |
-   *    v
-   * FLUSH_SYNC_POINT
-   *    |
-   *    v
-   * <finish>
-   *
-   * @endverbatim
-   */
-
-  ImageCtxT *m_local_image_ctx;
-  ImageCtxT *m_remote_image_ctx;
-  SafeTimer *m_timer;
-  Mutex *m_timer_lock;
-  Journaler *m_journaler;
-  MirrorPeerClientMeta *m_client_meta;
-  MirrorPeerSyncPoint *m_sync_point;
-  ProgressContext *m_progress_ctx;
-
-  SnapMap m_snap_map;
-
-  Mutex m_lock;
-  bool m_canceled = false;
-
-  uint64_t m_object_no = 0;
-  uint64_t m_end_object_no;
-  uint64_t m_current_ops = 0;
-  int m_ret_val = 0;
-
-  bool m_updating_sync_point;
-  Context *m_update_sync_ctx;
-  double m_update_sync_point_interval;
-
-  MirrorPeerClientMeta m_client_meta_copy;
-
-  void send_update_max_object_count();
-  void handle_update_max_object_count(int r);
-
-  void send_object_copies();
-  void send_next_object_copy();
-  void handle_object_copy(int r);
-
-  void send_update_sync_point();
-  void handle_update_sync_point(int r);
-
-  void send_flush_sync_point();
-  void handle_flush_sync_point(int r);
-
-  int compute_snap_map();
-
-  void update_progress(const std::string &description, bool flush = true);
-};
-
-} // namespace image_sync
-} // namespace mirror
-} // namespace rbd
-
-extern template class rbd::mirror::image_sync::ImageCopyRequest<librbd::ImageCtx>;
-
-#endif // RBD_MIRROR_IMAGE_SYNC_IMAGE_COPY_REQUEST_H
diff --git a/src/tools/rbd_mirror/image_sync/MetadataCopyRequest.cc b/src/tools/rbd_mirror/image_sync/MetadataCopyRequest.cc
deleted file mode 100644 (file)
index b9311dc..0000000
+++ /dev/null
@@ -1,119 +0,0 @@
-// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
-// vim: ts=8 sw=2 smarttab
-
-#include "tools/rbd_mirror/image_sync/MetadataCopyRequest.h"
-#include "common/dout.h"
-#include "common/errno.h"
-#include "cls/rbd/cls_rbd_client.h"
-#include "librbd/Utils.h"
-
-#define dout_context g_ceph_context
-#define dout_subsys ceph_subsys_rbd_mirror
-#undef dout_prefix
-#define dout_prefix *_dout << "rbd::mirror::image_sync::MetadataCopyRequest: " \
-                           << this << " " << __func__ << ": "
-
-namespace rbd {
-namespace mirror {
-namespace image_sync {
-
-namespace {
-
-const uint64_t MAX_METADATA_ITEMS = 128;
-
-} // anonymous namespace
-
-using librbd::util::create_rados_callback;
-
-template <typename I>
-void MetadataCopyRequest<I>::send() {
-  list_remote_metadata();
-}
-
-template <typename I>
-void MetadataCopyRequest<I>::list_remote_metadata() {
-  dout(20) << "start_key=" << m_last_metadata_key << dendl;
-
-  librados::ObjectReadOperation op;
-  librbd::cls_client::metadata_list_start(&op, m_last_metadata_key, MAX_METADATA_ITEMS);
-
-  librados::AioCompletion *aio_comp = create_rados_callback<
-    MetadataCopyRequest<I>,
-    &MetadataCopyRequest<I>::handle_list_remote_data>(this);
-  m_out_bl.clear();
-  m_remote_image_ctx->md_ctx.aio_operate(m_remote_image_ctx->header_oid,
-                                         aio_comp, &op, &m_out_bl);
-  aio_comp->release();
-}
-
-template <typename I>
-void MetadataCopyRequest<I>::handle_list_remote_data(int r) {
-  dout(20) << "r=" << r << dendl;
-
-  Metadata metadata;
-  if (r == 0) {
-    bufferlist::iterator it = m_out_bl.begin();
-    r = librbd::cls_client::metadata_list_finish(&it, &metadata);
-  }
-
-  if (r < 0) {
-    derr << "failed to retrieve metadata: " << cpp_strerror(r) << dendl;
-    finish(r);
-    return;
-  }
-
-  if (metadata.empty()) {
-    finish(0);
-    return;
-  }
-
-  m_last_metadata_key = metadata.rbegin()->first;
-  m_more_metadata = (metadata.size() >= MAX_METADATA_ITEMS);
-  set_local_metadata(metadata);
-}
-
-template <typename I>
-void MetadataCopyRequest<I>::set_local_metadata(const Metadata& metadata) {
-  dout(20) << "count=" << metadata.size() << dendl;
-
-  librados::ObjectWriteOperation op;
-  librbd::cls_client::metadata_set(&op, metadata);
-
-  librados::AioCompletion *aio_comp = create_rados_callback<
-    MetadataCopyRequest<I>,
-    &MetadataCopyRequest<I>::handle_set_local_metadata>(this);
-  m_local_image_ctx->md_ctx.aio_operate(m_local_image_ctx->header_oid, aio_comp,
-                                        &op);
-  aio_comp->release();
-}
-
-template <typename I>
-void MetadataCopyRequest<I>::handle_set_local_metadata(int r) {
-  dout(20) << "r=" << r << dendl;
-
-  if (r < 0) {
-    derr << "failed to set metadata: " << cpp_strerror(r) << dendl;
-    finish(r);
-    return;
-  }
-
-  if (m_more_metadata) {
-    list_remote_metadata();
-    return;
-  }
-
-  finish(0);
-}
-
-template <typename I>
-void MetadataCopyRequest<I>::finish(int r) {
-  dout(20) << "r=" << r << dendl;
-  m_on_finish->complete(r);
-  delete this;
-}
-
-} // namespace image_sync
-} // namespace mirror
-} // namespace rbd
-
-template class rbd::mirror::image_sync::MetadataCopyRequest<librbd::ImageCtx>;
diff --git a/src/tools/rbd_mirror/image_sync/MetadataCopyRequest.h b/src/tools/rbd_mirror/image_sync/MetadataCopyRequest.h
deleted file mode 100644 (file)
index 967b640..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
-// vim: ts=8 sw=2 smarttab
-
-#ifndef RBD_MIRROR_IMAGE_SYNC_METADATA_COPY_REQUEST_H
-#define RBD_MIRROR_IMAGE_SYNC_METADATA_COPY_REQUEST_H
-
-#include "include/int_types.h"
-#include "include/buffer.h"
-#include "include/rados/librados.hpp"
-#include "librbd/ImageCtx.h"
-#include <map>
-#include <string>
-
-class Context;
-
-namespace rbd {
-namespace mirror {
-namespace image_sync {
-
-template <typename ImageCtxT = librbd::ImageCtx>
-class MetadataCopyRequest {
-public:
-  static MetadataCopyRequest* create(ImageCtxT *local_image_ctx,
-                                     ImageCtxT *remote_image_ctx,
-                                     Context *on_finish) {
-    return new MetadataCopyRequest(local_image_ctx, remote_image_ctx,
-                                   on_finish);
-  }
-
-  MetadataCopyRequest(ImageCtxT *local_image_ctx, ImageCtxT *remote_image_ctx,
-                      Context *on_finish)
-    : m_local_image_ctx(local_image_ctx), m_remote_image_ctx(remote_image_ctx),
-      m_on_finish(on_finish) {
-  }
-
-  void send();
-
-private:
-  /**
-   * @verbatim
-   *
-   * <start>
-   *    |
-   *    v
-   * LIST_REMOTE_METADATA <-----\
-   *    |                       | (repeat if additional
-   *    v                       |  metadata)
-   * SET_LOCAL_METADATA --------/
-   *    |
-   *    v
-   * <finish>
-   *
-   * @endverbatim
-   */
-  typedef std::map<std::string, bufferlist> Metadata;
-
-  ImageCtxT *m_local_image_ctx;
-  ImageCtxT *m_remote_image_ctx;
-  Context *m_on_finish;
-
-  bufferlist m_out_bl;
-
-  std::string m_last_metadata_key;
-  bool m_more_metadata = false;
-
-  void list_remote_metadata();
-  void handle_list_remote_data(int r);
-
-  void set_local_metadata(const Metadata& metadata);
-  void handle_set_local_metadata(int r);
-
-  void finish(int r);
-
-};
-
-} // namespace image_sync
-} // namespace mirror
-} // namespace rbd
-
-extern template class rbd::mirror::image_sync::MetadataCopyRequest<librbd::ImageCtx>;
-
-#endif // RBD_MIRROR_IMAGE_SYNC_METADATA_COPY_REQUEST_H
diff --git a/src/tools/rbd_mirror/image_sync/ObjectCopyRequest.cc b/src/tools/rbd_mirror/image_sync/ObjectCopyRequest.cc
deleted file mode 100644 (file)
index ab9dd8d..0000000
+++ /dev/null
@@ -1,506 +0,0 @@
-// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
-// vim: ts=8 sw=2 smarttab
-
-#include "ObjectCopyRequest.h"
-#include "librados/snap_set_diff.h"
-#include "librbd/ExclusiveLock.h"
-#include "librbd/ObjectMap.h"
-#include "librbd/Utils.h"
-#include "common/errno.h"
-
-#define dout_context g_ceph_context
-#define dout_subsys ceph_subsys_rbd_mirror
-#undef dout_prefix
-#define dout_prefix *_dout << "rbd::mirror::image_sync::ObjectCopyRequest: " \
-                           << this << " " << __func__
-
-namespace librados {
-
-bool operator==(const clone_info_t& rhs, const clone_info_t& lhs) {
-  return (rhs.cloneid == lhs.cloneid &&
-          rhs.snaps == lhs.snaps &&
-          rhs.overlap == lhs.overlap &&
-          rhs.size == lhs.size);
-}
-
-bool operator==(const snap_set_t& rhs, const snap_set_t& lhs) {
-  return (rhs.clones == lhs.clones &&
-          rhs.seq == lhs.seq);
-}
-
-} // namespace librados
-
-namespace rbd {
-namespace mirror {
-namespace image_sync {
-
-using librbd::util::create_context_callback;
-using librbd::util::create_rados_callback;
-
-template <typename I>
-ObjectCopyRequest<I>::ObjectCopyRequest(I *local_image_ctx, I *remote_image_ctx,
-                                        const SnapMap *snap_map,
-                                        uint64_t object_number,
-                                        Context *on_finish)
-  : m_local_image_ctx(local_image_ctx), m_remote_image_ctx(remote_image_ctx),
-    m_snap_map(snap_map), m_object_number(object_number),
-    m_on_finish(on_finish) {
-  assert(!snap_map->empty());
-
-  m_local_io_ctx.dup(m_local_image_ctx->data_ctx);
-  m_local_oid = m_local_image_ctx->get_object_name(object_number);
-
-  m_remote_io_ctx.dup(m_remote_image_ctx->data_ctx);
-  m_remote_oid = m_remote_image_ctx->get_object_name(object_number);
-
-  dout(20) << ": "
-           << "remote_oid=" << m_remote_oid << ", "
-           << "local_oid=" << m_local_oid << dendl;
-}
-
-template <typename I>
-void ObjectCopyRequest<I>::send() {
-  send_list_snaps();
-}
-
-template <typename I>
-void ObjectCopyRequest<I>::send_list_snaps() {
-  dout(20) << dendl;
-
-  librados::AioCompletion *rados_completion = create_rados_callback<
-    ObjectCopyRequest<I>, &ObjectCopyRequest<I>::handle_list_snaps>(this);
-
-  librados::ObjectReadOperation op;
-  m_snap_set = {};
-  m_snap_ret = 0;
-  op.list_snaps(&m_snap_set, &m_snap_ret);
-
-  m_remote_io_ctx.snap_set_read(CEPH_SNAPDIR);
-  int r = m_remote_io_ctx.aio_operate(m_remote_oid, rados_completion, &op,
-                                      nullptr);
-  assert(r == 0);
-  rados_completion->release();
-}
-
-template <typename I>
-void ObjectCopyRequest<I>::handle_list_snaps(int r) {
-  if (r == 0 && m_snap_ret < 0) {
-    r = m_snap_ret;
-  }
-
-  dout(20) << ": r=" << r << dendl;
-
-  if (r == -ENOENT) {
-    finish(0);
-    return;
-  }
-
-  if (r < 0) {
-    derr << ": failed to list snaps: " << cpp_strerror(r) << dendl;
-    finish(r);
-    return;
-  }
-
-  if (m_retry_missing_read) {
-    if (m_snap_set == m_retry_snap_set) {
-      derr << ": read encountered missing object using up-to-date snap set"
-           << dendl;
-      finish(-ENOENT);
-      return;
-    }
-
-    dout(20) << ": retrying using updated snap set" << dendl;
-    m_retry_missing_read = false;
-    m_retry_snap_set = {};
-  }
-
-  compute_diffs();
-  send_read_object();
-}
-
-template <typename I>
-void ObjectCopyRequest<I>::send_read_object() {
-  if (m_snap_sync_ops.empty()) {
-    // no more snapshot diffs to read from remote
-    finish(0);
-    return;
-  }
-
-  // build the read request
-  auto &sync_ops = m_snap_sync_ops.begin()->second;
-  assert(!sync_ops.empty());
-
-  bool read_required = false;
-  librados::ObjectReadOperation op;
-  for (auto &sync_op : sync_ops) {
-    switch (sync_op.type) {
-    case SYNC_OP_TYPE_WRITE:
-      if (!read_required) {
-        // map the sync op start snap id back to the necessary read snap id
-        librados::snap_t remote_snap_seq =
-          m_snap_sync_ops.begin()->first.second;
-        m_remote_io_ctx.snap_set_read(remote_snap_seq);
-
-        dout(20) << ": remote_snap_seq=" << remote_snap_seq << dendl;
-        read_required = true;
-      }
-      dout(20) << ": read op: " << sync_op.offset << "~" << sync_op.length
-               << dendl;
-      op.sparse_read(sync_op.offset, sync_op.length, &sync_op.extent_map,
-                     &sync_op.out_bl, nullptr);
-      op.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_SEQUENTIAL |
-                       LIBRADOS_OP_FLAG_FADVISE_NOCACHE);
-      break;
-    default:
-      break;
-    }
-  }
-
-  if (!read_required) {
-    // nothing written to this object for this snapshot (must be trunc/remove)
-    send_write_object();
-    return;
-  }
-
-  librados::AioCompletion *comp = create_rados_callback<
-    ObjectCopyRequest<I>, &ObjectCopyRequest<I>::handle_read_object>(this);
-  int r = m_remote_io_ctx.aio_operate(m_remote_oid, comp, &op, nullptr);
-  assert(r == 0);
-  comp->release();
-}
-
-template <typename I>
-void ObjectCopyRequest<I>::handle_read_object(int r) {
-  dout(20) << ": r=" << r << dendl;
-
-  if (r == -ENOENT) {
-    m_retry_snap_set = m_snap_set;
-    m_retry_missing_read = true;
-
-    dout(5) << ": object missing potentially due to removed snapshot" << dendl;
-    send_list_snaps();
-    return;
-  }
-
-  if (r < 0) {
-    derr << ": failed to read from remote object: " << cpp_strerror(r)
-         << dendl;
-    finish(r);
-    return;
-  }
-
-  send_write_object();
-}
-
-template <typename I>
-void ObjectCopyRequest<I>::send_write_object() {
-  // retrieve the local snap context for the op
-  SnapIds local_snap_ids;
-  librados::snap_t local_snap_seq = 0;
-  librados::snap_t remote_snap_seq = m_snap_sync_ops.begin()->first.first;
-  if (remote_snap_seq != 0) {
-    auto snap_map_it = m_snap_map->find(remote_snap_seq);
-    assert(snap_map_it != m_snap_map->end());
-
-    // write snapshot context should be before actual snapshot
-    if (snap_map_it != m_snap_map->begin()) {
-      --snap_map_it;
-      assert(!snap_map_it->second.empty());
-      local_snap_seq = snap_map_it->second.front();
-      local_snap_ids = snap_map_it->second;
-    }
-  }
-
-  Context *finish_op_ctx;
-  {
-    RWLock::RLocker owner_locker(m_local_image_ctx->owner_lock);
-    finish_op_ctx = start_local_op(m_local_image_ctx->owner_lock);
-  }
-  if (finish_op_ctx == nullptr) {
-    derr << ": lost exclusive lock" << dendl;
-    finish(-EROFS);
-    return;
-  }
-
-  dout(20) << ": "
-           << "local_snap_seq=" << local_snap_seq << ", "
-           << "local_snaps=" << local_snap_ids << dendl;
-
-  auto &sync_ops = m_snap_sync_ops.begin()->second;
-  assert(!sync_ops.empty());
-  uint64_t object_offset;
-  uint64_t buffer_offset;
-  librados::ObjectWriteOperation op;
-  for (auto &sync_op : sync_ops) {
-    switch (sync_op.type) {
-    case SYNC_OP_TYPE_WRITE:
-      object_offset = sync_op.offset;
-      buffer_offset = 0;
-      for (auto it : sync_op.extent_map) {
-        if (object_offset < it.first) {
-          dout(20) << ": zero op: " << object_offset << "~"
-                   << it.first - object_offset << dendl;
-          op.zero(object_offset, it.first - object_offset);
-        }
-        dout(20) << ": write op: " << it.first << "~" << it.second << dendl;
-        bufferlist tmpbl;
-        tmpbl.substr_of(sync_op.out_bl, buffer_offset, it.second);
-        op.write(it.first, tmpbl);
-        op.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_SEQUENTIAL |
-                         LIBRADOS_OP_FLAG_FADVISE_NOCACHE);
-        buffer_offset += it.second;
-        object_offset = it.first + it.second;
-      }
-      if (object_offset < sync_op.offset + sync_op.length) {
-        uint64_t sync_op_end = sync_op.offset + sync_op.length;
-        assert(sync_op_end <= m_snap_object_sizes[remote_snap_seq]);
-        if (sync_op_end == m_snap_object_sizes[remote_snap_seq]) {
-          dout(20) << ": trunc op: " << object_offset << dendl;
-          op.truncate(object_offset);
-          m_snap_object_sizes[remote_snap_seq] = object_offset;
-        } else {
-          dout(20) << ": zero op: " << object_offset << "~"
-                   << sync_op_end - object_offset << dendl;
-          op.zero(object_offset, sync_op_end - object_offset);
-        }
-      }
-      break;
-    case SYNC_OP_TYPE_TRUNC:
-      if (sync_op.offset > m_snap_object_sizes[remote_snap_seq]) {
-        // skip (must have been updated in WRITE op case issuing trunc op)
-        break;
-      }
-      dout(20) << ": trunc op: " << sync_op.offset << dendl;
-      op.truncate(sync_op.offset);
-      break;
-    case SYNC_OP_TYPE_REMOVE:
-      dout(20) << ": remove op" << dendl;
-      op.remove();
-      break;
-    default:
-      ceph_abort();
-    }
-  }
-
-  auto ctx = new FunctionContext([this, finish_op_ctx](int r) {
-      handle_write_object(r);
-      finish_op_ctx->complete(0);
-    });
-  librados::AioCompletion *comp = create_rados_callback(ctx);
-  int r = m_local_io_ctx.aio_operate(m_local_oid, comp, &op, local_snap_seq,
-                                     local_snap_ids);
-  assert(r == 0);
-  comp->release();
-}
-
-template <typename I>
-void ObjectCopyRequest<I>::handle_write_object(int r) {
-  dout(20) << ": r=" << r << dendl;
-
-  if (r == -ENOENT) {
-    r = 0;
-  }
-  if (r < 0) {
-    derr << ": failed to write to local object: " << cpp_strerror(r)
-         << dendl;
-    finish(r);
-    return;
-  }
-
-  m_snap_sync_ops.erase(m_snap_sync_ops.begin());
-  if (!m_snap_sync_ops.empty()) {
-    send_read_object();
-    return;
-  }
-
-  send_update_object_map();
-}
-
-template <typename I>
-void ObjectCopyRequest<I>::send_update_object_map() {
-  m_local_image_ctx->owner_lock.get_read();
-  m_local_image_ctx->snap_lock.get_read();
-  if (!m_local_image_ctx->test_features(RBD_FEATURE_OBJECT_MAP,
-                                        m_local_image_ctx->snap_lock) ||
-      m_snap_object_states.empty()) {
-    m_local_image_ctx->snap_lock.put_read();
-    m_local_image_ctx->owner_lock.put_read();
-    finish(0);
-    return;
-  } else if (m_local_image_ctx->object_map == nullptr) {
-    // possible that exclusive lock was lost in background
-    derr << ": object map is not initialized" << dendl;
-
-    m_local_image_ctx->snap_lock.put_read();
-    m_local_image_ctx->owner_lock.put_read();
-    finish(-EINVAL);
-    return;
-  }
-
-  assert(m_local_image_ctx->object_map != nullptr);
-
-  auto snap_object_state = *m_snap_object_states.begin();
-  m_snap_object_states.erase(m_snap_object_states.begin());
-
-  dout(20) << ": "
-           << "local_snap_id=" << snap_object_state.first << ", "
-           << "object_state=" << static_cast<uint32_t>(snap_object_state.second)
-           << dendl;
-
-  auto finish_op_ctx = start_local_op(m_local_image_ctx->owner_lock);
-  if (finish_op_ctx == nullptr) {
-    derr << ": lost exclusive lock" << dendl;
-    m_local_image_ctx->snap_lock.put_read();
-    m_local_image_ctx->owner_lock.put_read();
-    finish(-EROFS);
-    return;
-  }
-
-  auto ctx = new FunctionContext([this, finish_op_ctx](int r) {
-      handle_update_object_map(r);
-      finish_op_ctx->complete(0);
-    });
-
-  RWLock::WLocker object_map_locker(m_local_image_ctx->object_map_lock);
-  bool sent = m_local_image_ctx->object_map->template aio_update<
-    Context, &Context::complete>(
-      snap_object_state.first, m_object_number, snap_object_state.second, {},
-      {}, ctx);
-  assert(sent);
-  m_local_image_ctx->snap_lock.put_read();
-  m_local_image_ctx->owner_lock.put_read();
-}
-
-template <typename I>
-void ObjectCopyRequest<I>::handle_update_object_map(int r) {
-  dout(20) << ": r=" << r << dendl;
-
-  assert(r == 0);
-  if (!m_snap_object_states.empty()) {
-    send_update_object_map();
-    return;
-  }
-  finish(0);
-}
-
-template <typename I>
-Context *ObjectCopyRequest<I>::start_local_op(RWLock &owner_lock) {
-  assert(m_local_image_ctx->owner_lock.is_locked());
-  if (m_local_image_ctx->exclusive_lock == nullptr) {
-    return nullptr;
-  }
-  return m_local_image_ctx->exclusive_lock->start_op();
-}
-
-template <typename I>
-void ObjectCopyRequest<I>::compute_diffs() {
-  CephContext *cct = m_local_image_ctx->cct;
-
-  m_snap_sync_ops = {};
-  m_snap_object_states = {};
-  m_snap_object_sizes = {};
-
-  librados::snap_t remote_sync_pont_snap_id = m_snap_map->rbegin()->first;
-  uint64_t prev_end_size = 0;
-  bool prev_exists = false;
-  librados::snap_t start_remote_snap_id = 0;
-  for (auto &pair : *m_snap_map) {
-    assert(!pair.second.empty());
-    librados::snap_t end_remote_snap_id = pair.first;
-    librados::snap_t end_local_snap_id = pair.second.front();
-
-    interval_set<uint64_t> diff;
-    uint64_t end_size;
-    bool exists;
-    librados::snap_t clone_end_snap_id;
-    calc_snap_set_diff(cct, m_snap_set, start_remote_snap_id,
-                       end_remote_snap_id, &diff, &end_size, &exists,
-                       &clone_end_snap_id);
-
-    dout(20) << ": "
-             << "start_remote_snap=" << start_remote_snap_id << ", "
-             << "end_remote_snap_id=" << end_remote_snap_id << ", "
-             << "clone_end_snap_id=" << clone_end_snap_id << ", "
-             << "end_local_snap_id=" << end_local_snap_id << ", "
-             << "diff=" << diff << ", "
-             << "end_size=" << end_size << ", "
-             << "exists=" << exists << dendl;
-    if (exists) {
-      // clip diff to size of object (in case it was truncated)
-      if (end_size < prev_end_size) {
-        interval_set<uint64_t> trunc;
-        trunc.insert(end_size, prev_end_size);
-        trunc.intersection_of(diff);
-        diff.subtract(trunc);
-        dout(20) << ": clearing truncate diff: " << trunc << dendl;
-      }
-
-      // prepare the object map state
-      {
-        RWLock::RLocker snap_locker(m_local_image_ctx->snap_lock);
-        uint8_t object_state = OBJECT_EXISTS;
-        if (m_local_image_ctx->test_features(RBD_FEATURE_FAST_DIFF,
-                                             m_local_image_ctx->snap_lock) &&
-            prev_exists && diff.empty() && end_size == prev_end_size) {
-          object_state = OBJECT_EXISTS_CLEAN;
-        }
-        m_snap_object_states[end_local_snap_id] = object_state;
-      }
-
-      // reads should be issued against the newest (existing) snapshot within
-      // the associated snapshot object clone. writes should be issued
-      // against the oldest snapshot in the snap_map.
-      assert(clone_end_snap_id >= end_remote_snap_id);
-      if (clone_end_snap_id > remote_sync_pont_snap_id) {
-        // do not read past the sync point snapshot
-        clone_end_snap_id = remote_sync_pont_snap_id;
-      }
-
-      // object write/zero, or truncate
-      // NOTE: a single snapshot clone might represent multiple snapshots, but
-      // the write/zero and truncate ops will only be associated with the first
-      // snapshot encountered within the clone since the diff will be empty for
-      // subsequent snapshots and the size will remain constant for a clone.
-      for (auto it = diff.begin(); it != diff.end(); ++it) {
-        dout(20) << ": read/write op: " << it.get_start() << "~"
-                 << it.get_len() << dendl;
-        m_snap_sync_ops[{end_remote_snap_id, clone_end_snap_id}].emplace_back(
-          SYNC_OP_TYPE_WRITE, it.get_start(), it.get_len());
-      }
-      if (end_size < prev_end_size) {
-        dout(20) << ": trunc op: " << end_size << dendl;
-        m_snap_sync_ops[{end_remote_snap_id, clone_end_snap_id}].emplace_back(
-          SYNC_OP_TYPE_TRUNC, end_size, 0U);
-      }
-      m_snap_object_sizes[end_remote_snap_id] = end_size;
-    } else {
-      if (prev_exists) {
-        // object remove
-        dout(20) << ": remove op" << dendl;
-        m_snap_sync_ops[{end_remote_snap_id, end_remote_snap_id}].emplace_back(
-          SYNC_OP_TYPE_REMOVE, 0U, 0U);
-      }
-    }
-
-    prev_end_size = end_size;
-    prev_exists = exists;
-    start_remote_snap_id = end_remote_snap_id;
-  }
-}
-
-template <typename I>
-void ObjectCopyRequest<I>::finish(int r) {
-  dout(20) << ": r=" << r << dendl;
-
-  // ensure IoCtxs are closed prior to proceeding
-  auto on_finish = m_on_finish;
-  delete this;
-
-  on_finish->complete(r);
-}
-
-} // namespace image_sync
-} // namespace mirror
-} // namespace rbd
-
-template class rbd::mirror::image_sync::ObjectCopyRequest<librbd::ImageCtx>;
diff --git a/src/tools/rbd_mirror/image_sync/ObjectCopyRequest.h b/src/tools/rbd_mirror/image_sync/ObjectCopyRequest.h
deleted file mode 100644 (file)
index 57963c2..0000000
+++ /dev/null
@@ -1,153 +0,0 @@
-// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
-// vim: ts=8 sw=2 smarttab
-
-#ifndef RBD_MIRROR_IMAGE_SYNC_OBJECT_COPY_REQUEST_H
-#define RBD_MIRROR_IMAGE_SYNC_OBJECT_COPY_REQUEST_H
-
-#include "include/int_types.h"
-#include "include/rados/librados.hpp"
-#include "common/snap_types.h"
-#include "librbd/ImageCtx.h"
-#include <list>
-#include <map>
-#include <string>
-#include <vector>
-
-class Context;
-class RWLock;
-
-namespace rbd {
-namespace mirror {
-namespace image_sync {
-
-template <typename ImageCtxT = librbd::ImageCtx>
-class ObjectCopyRequest {
-public:
-  typedef std::vector<librados::snap_t> SnapIds;
-  typedef std::map<librados::snap_t, SnapIds> SnapMap;
-
-  static ObjectCopyRequest* create(ImageCtxT *local_image_ctx,
-                                   ImageCtxT *remote_image_ctx,
-                                   const SnapMap *snap_map,
-                                   uint64_t object_number, Context *on_finish) {
-    return new ObjectCopyRequest(local_image_ctx, remote_image_ctx, snap_map,
-                                 object_number, on_finish);
-  }
-
-  ObjectCopyRequest(ImageCtxT *local_image_ctx, ImageCtxT *remote_image_ctx,
-                    const SnapMap *snap_map, uint64_t object_number,
-                    Context *on_finish);
-
-  void send();
-
-  // testing support
-  inline librados::IoCtx &get_local_io_ctx() {
-    return m_local_io_ctx;
-  }
-  inline librados::IoCtx &get_remote_io_ctx() {
-    return m_remote_io_ctx;
-  }
-
-private:
-  /**
-   * @verbatim
-   *
-   * <start>
-   *    |
-   *    v
-   * LIST_SNAPS < * * *
-   *    |             * (-ENOENT and snap set stale)
-   *    |   * * * * * *
-   *    |   *
-   *    v   *
-   * READ_OBJECT <--------\
-   *    |                 | (repeat for each snapshot)
-   *    v                 |
-   * WRITE_OBJECT --------/
-   *    |
-   *    |     /-----------\
-   *    |     |           | (repeat for each snapshot)
-   *    v     v           |
-   * UPDATE_OBJECT_MAP ---/ (skip if object
-   *    |                    map disabled)
-   *    |
-   *    v
-   * <finish>
-   *
-   * @endverbatim
-   */
-
-  enum SyncOpType {
-    SYNC_OP_TYPE_WRITE,
-    SYNC_OP_TYPE_TRUNC,
-    SYNC_OP_TYPE_REMOVE
-  };
-
-  typedef std::map<uint64_t, uint64_t> ExtentMap;
-
-  struct SyncOp {
-    SyncOp(SyncOpType type, uint64_t offset, uint64_t length)
-      : type(type), offset(offset), length(length) {
-    }
-
-    SyncOpType type;
-    uint64_t offset;
-    uint64_t length;
-
-    ExtentMap extent_map;
-    bufferlist out_bl;
-  };
-
-  typedef std::list<SyncOp> SyncOps;
-  typedef std::pair<librados::snap_t, librados::snap_t> WriteReadSnapIds;
-  typedef std::map<WriteReadSnapIds, SyncOps> SnapSyncOps;
-  typedef std::map<librados::snap_t, uint8_t> SnapObjectStates;
-  typedef std::map<librados::snap_t, uint64_t> SnapObjectSizes;
-
-  ImageCtxT *m_local_image_ctx;
-  ImageCtxT *m_remote_image_ctx;
-  const SnapMap *m_snap_map;
-  uint64_t m_object_number;
-  Context *m_on_finish;
-
-  decltype(m_local_image_ctx->data_ctx) m_local_io_ctx;
-  decltype(m_remote_image_ctx->data_ctx) m_remote_io_ctx;
-  std::string m_local_oid;
-  std::string m_remote_oid;
-
-  librados::snap_set_t m_snap_set;
-  int m_snap_ret = 0;
-
-  bool m_retry_missing_read = false;
-  librados::snap_set_t m_retry_snap_set;
-
-  SnapSyncOps m_snap_sync_ops;
-  SnapObjectStates m_snap_object_states;
-  SnapObjectSizes m_snap_object_sizes;
-
-  void send_list_snaps();
-  void handle_list_snaps(int r);
-
-  void send_read_object();
-  void handle_read_object(int r);
-
-  void send_write_object();
-  void handle_write_object(int r);
-
-  void send_update_object_map();
-  void handle_update_object_map(int r);
-
-  Context *start_local_op(RWLock &owner_lock);
-
-  void compute_diffs();
-  void finish(int r);
-
-};
-
-} // namespace image_sync
-} // namespace mirror
-} // namespace rbd
-
-extern template class rbd::mirror::image_sync::ObjectCopyRequest<librbd::ImageCtx>;
-
-#endif // RBD_MIRROR_IMAGE_SYNC_OBJECT_COPY_REQUEST_H
diff --git a/src/tools/rbd_mirror/image_sync/SnapshotCopyRequest.cc b/src/tools/rbd_mirror/image_sync/SnapshotCopyRequest.cc
deleted file mode 100644 (file)
index f5f0701..0000000
+++ /dev/null
@@ -1,614 +0,0 @@
-// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
-// vim: ts=8 sw=2 smarttab
-
-#include "SnapshotCopyRequest.h"
-#include "SnapshotCreateRequest.h"
-#include "common/errno.h"
-#include "common/WorkQueue.h"
-#include "journal/Journaler.h"
-#include "librbd/ExclusiveLock.h"
-#include "librbd/Operations.h"
-#include "librbd/Utils.h"
-#include "librbd/journal/Types.h"
-
-#define dout_context g_ceph_context
-#define dout_subsys ceph_subsys_rbd_mirror
-#undef dout_prefix
-#define dout_prefix *_dout << "rbd::mirror::image_sync::SnapshotCopyRequest: " \
-                           << this << " " << __func__
-
-namespace rbd {
-namespace mirror {
-namespace image_sync {
-
-namespace {
-
-template <typename I>
-const std::string &get_snapshot_name(I *image_ctx, librados::snap_t snap_id) {
-  auto snap_it = std::find_if(image_ctx->snap_ids.begin(),
-                              image_ctx->snap_ids.end(),
-                              [snap_id](
-                               const std::pair<
-                                         std::pair<cls::rbd::SnapshotNamespace,
-                                                   std::string>,
-                                         librados::snap_t> &pair) {
-    return pair.second == snap_id;
-  });
-  assert(snap_it != image_ctx->snap_ids.end());
-  return snap_it->first.second;
-}
-
-} // anonymous namespace
-
-using librbd::util::create_context_callback;
-using librbd::util::unique_lock_name;
-
-template <typename I>
-SnapshotCopyRequest<I>::SnapshotCopyRequest(I *local_image_ctx,
-                                            I *remote_image_ctx,
-                                            SnapMap *snap_map,
-                                            Journaler *journaler,
-                                            librbd::journal::MirrorPeerClientMeta *meta,
-                                            ContextWQ *work_queue,
-                                            Context *on_finish)
-  : BaseRequest("rbd::mirror::image_sync::SnapshotCopyRequest",
-               local_image_ctx->cct, on_finish),
-    m_local_image_ctx(local_image_ctx), m_remote_image_ctx(remote_image_ctx),
-    m_snap_map(snap_map), m_journaler(journaler), m_client_meta(meta),
-    m_work_queue(work_queue), m_snap_seqs(meta->snap_seqs),
-    m_lock(unique_lock_name("SnapshotCopyRequest::m_lock", this)) {
-  m_snap_map->clear();
-
-  // snap ids ordered from oldest to newest
-  m_remote_snap_ids.insert(remote_image_ctx->snaps.begin(),
-                           remote_image_ctx->snaps.end());
-  m_local_snap_ids.insert(local_image_ctx->snaps.begin(),
-                          local_image_ctx->snaps.end());
-}
-
-template <typename I>
-void SnapshotCopyRequest<I>::send() {
-  librbd::ParentSpec remote_parent_spec;
-  int r = validate_parent(m_remote_image_ctx, &remote_parent_spec);
-  if (r < 0) {
-    derr << ": remote image parent spec mismatch" << dendl;
-    error(r);
-    return;
-  }
-
-  r = validate_parent(m_local_image_ctx, &m_local_parent_spec);
-  if (r < 0) {
-    derr << ": local image parent spec mismatch" << dendl;
-    error(r);
-    return;
-  }
-
-  send_snap_unprotect();
-}
-
-template <typename I>
-void SnapshotCopyRequest<I>::cancel() {
-  Mutex::Locker locker(m_lock);
-
-  dout(20) << dendl;
-  m_canceled = true;
-}
-
-template <typename I>
-void SnapshotCopyRequest<I>::send_snap_unprotect() {
-
-  SnapIdSet::iterator snap_id_it = m_local_snap_ids.begin();
-  if (m_prev_snap_id != CEPH_NOSNAP) {
-    snap_id_it = m_local_snap_ids.upper_bound(m_prev_snap_id);
-  }
-
-  for (; snap_id_it != m_local_snap_ids.end(); ++snap_id_it) {
-    librados::snap_t local_snap_id = *snap_id_it;
-
-    m_local_image_ctx->snap_lock.get_read();
-
-    bool local_unprotected;
-    int r = m_local_image_ctx->is_snap_unprotected(local_snap_id,
-                                                   &local_unprotected);
-    if (r < 0) {
-      derr << ": failed to retrieve local snap unprotect status: "
-           << cpp_strerror(r) << dendl;
-      m_local_image_ctx->snap_lock.put_read();
-      finish(r);
-      return;
-    }
-    m_local_image_ctx->snap_lock.put_read();
-
-    if (local_unprotected) {
-      // snap is already unprotected -- check next snap
-      continue;
-    }
-
-    // if local snapshot is protected and (1) it isn't in our mapping
-    // table, or (2) the remote snapshot isn't protected, unprotect it
-    auto snap_seq_it = std::find_if(
-      m_snap_seqs.begin(), m_snap_seqs.end(),
-      [local_snap_id](const SnapSeqs::value_type& pair) {
-        return pair.second == local_snap_id;
-      });
-
-    if (snap_seq_it != m_snap_seqs.end()) {
-      m_remote_image_ctx->snap_lock.get_read();
-      bool remote_unprotected;
-      r = m_remote_image_ctx->is_snap_unprotected(snap_seq_it->first,
-                                                  &remote_unprotected);
-      if (r < 0) {
-        derr << ": failed to retrieve remote snap unprotect status: "
-             << cpp_strerror(r) << dendl;
-        m_remote_image_ctx->snap_lock.put_read();
-        finish(r);
-        return;
-      }
-      m_remote_image_ctx->snap_lock.put_read();
-
-      if (remote_unprotected) {
-        // remote is unprotected -- unprotect local snap
-        break;
-      }
-    } else {
-      // remote snapshot doesn't exist -- unprotect local snap
-      break;
-    }
-  }
-
-  if (snap_id_it == m_local_snap_ids.end()) {
-    // no local snapshots to unprotect
-    m_prev_snap_id = CEPH_NOSNAP;
-    send_snap_remove();
-    return;
-  }
-
-  m_prev_snap_id = *snap_id_it;
-  m_snap_name = get_snapshot_name(m_local_image_ctx, m_prev_snap_id);
-
-  dout(20) << ": "
-           << "snap_name=" << m_snap_name << ", "
-           << "snap_id=" << m_prev_snap_id << dendl;
-
-  auto finish_op_ctx = start_local_op();
-  if (finish_op_ctx == nullptr) {
-    derr << ": lost exclusive lock" << dendl;
-    finish(-EROFS);
-    return;
-  }
-
-  auto ctx = new FunctionContext([this, finish_op_ctx](int r) {
-      handle_snap_unprotect(r);
-      finish_op_ctx->complete(0);
-    });
-  RWLock::RLocker owner_locker(m_local_image_ctx->owner_lock);
-  m_local_image_ctx->operations->execute_snap_unprotect(
-    cls::rbd::UserSnapshotNamespace(), m_snap_name.c_str(), ctx);
-}
-
-template <typename I>
-void SnapshotCopyRequest<I>::handle_snap_unprotect(int r) {
-  dout(20) << ": r=" << r << dendl;
-
-  if (r < 0) {
-    derr << ": failed to unprotect snapshot '" << m_snap_name << "': "
-         << cpp_strerror(r) << dendl;
-    finish(r);
-    return;
-  }
-  if (handle_cancellation())
-  {
-    return;
-  }
-
-  send_snap_unprotect();
-}
-
-template <typename I>
-void SnapshotCopyRequest<I>::send_snap_remove() {
-  SnapIdSet::iterator snap_id_it = m_local_snap_ids.begin();
-  if (m_prev_snap_id != CEPH_NOSNAP) {
-    snap_id_it = m_local_snap_ids.upper_bound(m_prev_snap_id);
-  }
-
-  for (; snap_id_it != m_local_snap_ids.end(); ++snap_id_it) {
-    librados::snap_t local_snap_id = *snap_id_it;
-
-    cls::rbd::SnapshotNamespace snap_namespace;
-    m_local_image_ctx->snap_lock.get_read();
-    int r = m_local_image_ctx->get_snap_namespace(local_snap_id,
-                                                  &snap_namespace);
-    m_local_image_ctx->snap_lock.put_read();
-    if (r < 0) {
-      derr << ": failed to retrieve local snap namespace: " << m_snap_name
-          << dendl;
-      finish(r);
-      return;
-    }
-
-    if (boost::get<cls::rbd::UserSnapshotNamespace>(&snap_namespace) ==
-          nullptr) {
-      continue;
-    }
-
-    // if the local snapshot isn't in our mapping table, remove it
-    auto snap_seq_it = std::find_if(
-      m_snap_seqs.begin(), m_snap_seqs.end(),
-      [local_snap_id](const SnapSeqs::value_type& pair) {
-        return pair.second == local_snap_id;
-      });
-
-    if (snap_seq_it == m_snap_seqs.end()) {
-      break;
-    }
-  }
-
-  if (snap_id_it == m_local_snap_ids.end()) {
-    // no local snapshots to delete
-    m_prev_snap_id = CEPH_NOSNAP;
-    send_snap_create();
-    return;
-  }
-
-  m_prev_snap_id = *snap_id_it;
-  m_snap_name = get_snapshot_name(m_local_image_ctx, m_prev_snap_id);
-
-  dout(20) << ": "
-           << "snap_name=" << m_snap_name << ", "
-           << "snap_id=" << m_prev_snap_id << dendl;
-
-  auto finish_op_ctx = start_local_op();
-  if (finish_op_ctx == nullptr) {
-    derr << ": lost exclusive lock" << dendl;
-    finish(-EROFS);
-    return;
-  }
-
-  auto ctx = new FunctionContext([this, finish_op_ctx](int r) {
-      handle_snap_remove(r);
-      finish_op_ctx->complete(0);
-    });
-  RWLock::RLocker owner_locker(m_local_image_ctx->owner_lock);
-  m_local_image_ctx->operations->execute_snap_remove(
-    cls::rbd::UserSnapshotNamespace(), m_snap_name.c_str(), ctx);
-}
-
-template <typename I>
-void SnapshotCopyRequest<I>::handle_snap_remove(int r) {
-  dout(20) << ": r=" << r << dendl;
-
-  if (r < 0) {
-    derr << ": failed to remove snapshot '" << m_snap_name << "': "
-         << cpp_strerror(r) << dendl;
-    finish(r);
-    return;
-  }
-  if (handle_cancellation())
-  {
-    return;
-  }
-
-  send_snap_remove();
-}
-
-template <typename I>
-void SnapshotCopyRequest<I>::send_snap_create() {
-  SnapIdSet::iterator snap_id_it = m_remote_snap_ids.begin();
-  if (m_prev_snap_id != CEPH_NOSNAP) {
-    snap_id_it = m_remote_snap_ids.upper_bound(m_prev_snap_id);
-  }
-
-  for (; snap_id_it != m_remote_snap_ids.end(); ++snap_id_it) {
-    librados::snap_t remote_snap_id = *snap_id_it;
-
-    cls::rbd::SnapshotNamespace snap_namespace;
-    m_remote_image_ctx->snap_lock.get_read();
-    int r = m_remote_image_ctx->get_snap_namespace(remote_snap_id, &snap_namespace);
-    m_remote_image_ctx->snap_lock.put_read();
-    if (r < 0) {
-      derr << ": failed to retrieve remote snap namespace: " << m_snap_name
-          << dendl;
-      finish(r);
-      return;
-    }
-
-    // if the remote snapshot isn't in our mapping table, create it
-    if (m_snap_seqs.find(remote_snap_id) == m_snap_seqs.end() &&
-       boost::get<cls::rbd::UserSnapshotNamespace>(&snap_namespace) != nullptr) {
-      break;
-    }
-  }
-
-  if (snap_id_it == m_remote_snap_ids.end()) {
-    // no remote snapshots to create
-    m_prev_snap_id = CEPH_NOSNAP;
-    send_snap_protect();
-    return;
-  }
-
-  m_prev_snap_id = *snap_id_it;
-  m_snap_name = get_snapshot_name(m_remote_image_ctx, m_prev_snap_id);
-
-  m_remote_image_ctx->snap_lock.get_read();
-  auto snap_info_it = m_remote_image_ctx->snap_info.find(m_prev_snap_id);
-  if (snap_info_it == m_remote_image_ctx->snap_info.end()) {
-    m_remote_image_ctx->snap_lock.put_read();
-    derr << ": failed to retrieve remote snap info: " << m_snap_name
-         << dendl;
-    finish(-ENOENT);
-    return;
-  }
-
-  uint64_t size = snap_info_it->second.size;
-  m_snap_namespace = snap_info_it->second.snap_namespace;
-  librbd::ParentSpec parent_spec;
-  uint64_t parent_overlap = 0;
-  if (snap_info_it->second.parent.spec.pool_id != -1) {
-    parent_spec = m_local_parent_spec;
-    parent_overlap = snap_info_it->second.parent.overlap;
-  }
-  m_remote_image_ctx->snap_lock.put_read();
-
-
-  dout(20) << ": "
-           << "snap_name=" << m_snap_name << ", "
-           << "snap_id=" << m_prev_snap_id << ", "
-           << "size=" << size << ", "
-           << "parent_info=["
-           << "pool_id=" << parent_spec.pool_id << ", "
-           << "image_id=" << parent_spec.image_id << ", "
-           << "snap_id=" << parent_spec.snap_id << ", "
-           << "overlap=" << parent_overlap << "]" << dendl;
-
-  Context *finish_op_ctx = start_local_op();
-  if (finish_op_ctx == nullptr) {
-    derr << ": lost exclusive lock" << dendl;
-    finish(-EROFS);
-    return;
-  }
-
-  auto ctx = new FunctionContext([this, finish_op_ctx](int r) {
-      handle_snap_create(r);
-      finish_op_ctx->complete(0);
-    });
-  SnapshotCreateRequest<I> *req = SnapshotCreateRequest<I>::create(
-    m_local_image_ctx, m_snap_name, m_snap_namespace, size, parent_spec,
-    parent_overlap, ctx);
-  req->send();
-}
-
-template <typename I>
-void SnapshotCopyRequest<I>::handle_snap_create(int r) {
-  dout(20) << ": r=" << r << dendl;
-
-  if (r < 0) {
-    derr << ": failed to create snapshot '" << m_snap_name << "': "
-         << cpp_strerror(r) << dendl;
-    finish(r);
-    return;
-  }
-  if (handle_cancellation())
-  {
-    return;
-  }
-
-  assert(m_prev_snap_id != CEPH_NOSNAP);
-
-  auto snap_it = m_local_image_ctx->snap_ids.find({cls::rbd::UserSnapshotNamespace(),
-                                                  m_snap_name});
-  assert(snap_it != m_local_image_ctx->snap_ids.end());
-  librados::snap_t local_snap_id = snap_it->second;
-
-  dout(20) << ": mapping remote snap id " << m_prev_snap_id << " to "
-           << local_snap_id << dendl;
-  m_snap_seqs[m_prev_snap_id] = local_snap_id;
-
-  send_snap_create();
-}
-
-template <typename I>
-void SnapshotCopyRequest<I>::send_snap_protect() {
-  SnapIdSet::iterator snap_id_it = m_remote_snap_ids.begin();
-  if (m_prev_snap_id != CEPH_NOSNAP) {
-    snap_id_it = m_remote_snap_ids.upper_bound(m_prev_snap_id);
-  }
-
-  for (; snap_id_it != m_remote_snap_ids.end(); ++snap_id_it) {
-    librados::snap_t remote_snap_id = *snap_id_it;
-
-    m_remote_image_ctx->snap_lock.get_read();
-
-    bool remote_protected;
-    int r = m_remote_image_ctx->is_snap_protected(remote_snap_id,
-                                                  &remote_protected);
-    if (r < 0) {
-      derr << ": failed to retrieve remote snap protect status: "
-           << cpp_strerror(r) << dendl;
-      m_remote_image_ctx->snap_lock.put_read();
-      finish(r);
-      return;
-    }
-    m_remote_image_ctx->snap_lock.put_read();
-
-    if (!remote_protected) {
-      // snap is not protected -- check next snap
-      continue;
-    }
-
-    // if local snapshot is not protected, protect it
-    auto snap_seq_it = m_snap_seqs.find(remote_snap_id);
-    assert(snap_seq_it != m_snap_seqs.end());
-
-    m_local_image_ctx->snap_lock.get_read();
-    bool local_protected;
-    r = m_local_image_ctx->is_snap_protected(snap_seq_it->second,
-                                             &local_protected);
-    if (r < 0) {
-      derr << ": failed to retrieve local snap protect status: "
-           << cpp_strerror(r) << dendl;
-      m_local_image_ctx->snap_lock.put_read();
-      finish(r);
-      return;
-    }
-    m_local_image_ctx->snap_lock.put_read();
-
-    if (!local_protected) {
-      break;
-    }
-  }
-
-  if (snap_id_it == m_remote_snap_ids.end()) {
-    // no local snapshots to protect
-    m_prev_snap_id = CEPH_NOSNAP;
-    send_update_client();
-    return;
-  }
-
-  m_prev_snap_id = *snap_id_it;
-  m_snap_name = get_snapshot_name(m_remote_image_ctx, m_prev_snap_id);
-
-  dout(20) << ": "
-           << "snap_name=" << m_snap_name << ", "
-           << "snap_id=" << m_prev_snap_id << dendl;
-
-  auto finish_op_ctx = start_local_op();
-  if (finish_op_ctx == nullptr) {
-    derr << ": lost exclusive lock" << dendl;
-    finish(-EROFS);
-    return;
-  }
-
-  auto ctx = new FunctionContext([this, finish_op_ctx](int r) {
-      handle_snap_protect(r);
-      finish_op_ctx->complete(0);
-    });
-  RWLock::RLocker owner_locker(m_local_image_ctx->owner_lock);
-  m_local_image_ctx->operations->execute_snap_protect(
-    cls::rbd::UserSnapshotNamespace(), m_snap_name.c_str(), ctx);
-}
-
-template <typename I>
-void SnapshotCopyRequest<I>::handle_snap_protect(int r) {
-  dout(20) << ": r=" << r << dendl;
-
-  if (r < 0) {
-    derr << ": failed to protect snapshot '" << m_snap_name << "': "
-         << cpp_strerror(r) << dendl;
-    finish(r);
-    return;
-  }
-  if (handle_cancellation())
-  {
-    return;
-  }
-
-  send_snap_protect();
-}
-
-template <typename I>
-void SnapshotCopyRequest<I>::send_update_client() {
-  dout(20) << dendl;
-
-  compute_snap_map();
-
-  librbd::journal::MirrorPeerClientMeta client_meta(*m_client_meta);
-  client_meta.snap_seqs = m_snap_seqs;
-
-  librbd::journal::ClientData client_data(client_meta);
-  bufferlist data_bl;
-  ::encode(client_data, data_bl);
-
-  Context *ctx = create_context_callback<
-    SnapshotCopyRequest<I>, &SnapshotCopyRequest<I>::handle_update_client>(
-      this);
-  m_journaler->update_client(data_bl, ctx);
-}
-
-template <typename I>
-void SnapshotCopyRequest<I>::handle_update_client(int r) {
-  dout(20) << ": r=" << r << dendl;
-
-  if (r < 0) {
-    derr << ": failed to update client data: " << cpp_strerror(r)
-         << dendl;
-    finish(r);
-    return;
-  }
-  if (handle_cancellation())
-  {
-    return;
-  }
-
-  m_client_meta->snap_seqs = m_snap_seqs;
-
-  finish(0);
-}
-
-template <typename I>
-bool SnapshotCopyRequest<I>::handle_cancellation() {
-  {
-    Mutex::Locker locker(m_lock);
-    if (!m_canceled) {
-      return false;
-    }
-  }
-  dout(10) << ": snapshot copy canceled" << dendl;
-  finish(-ECANCELED);
-  return true;
-}
-
-template <typename I>
-void SnapshotCopyRequest<I>::error(int r) {
-  dout(20) << ": r=" << r << dendl;
-
-  m_work_queue->queue(new FunctionContext([this, r](int r1) { finish(r); }));
-}
-
-template <typename I>
-void SnapshotCopyRequest<I>::compute_snap_map() {
-  SnapIds local_snap_ids;
-  for (auto &pair : m_snap_seqs) {
-    local_snap_ids.reserve(1 + local_snap_ids.size());
-    local_snap_ids.insert(local_snap_ids.begin(), pair.second);
-    m_snap_map->insert(std::make_pair(pair.first, local_snap_ids));
-  }
-}
-
-template <typename I>
-int SnapshotCopyRequest<I>::validate_parent(I *image_ctx,
-                                            librbd::ParentSpec *spec) {
-  RWLock::RLocker owner_locker(image_ctx->owner_lock);
-  RWLock::RLocker snap_locker(image_ctx->snap_lock);
-
-  // ensure remote image's parent specs are still consistent
-  *spec = image_ctx->parent_md.spec;
-  for (auto &snap_info_pair : image_ctx->snap_info) {
-    auto &parent_spec = snap_info_pair.second.parent.spec;
-    if (parent_spec.pool_id == -1) {
-      continue;
-    } else if (spec->pool_id == -1) {
-      *spec = parent_spec;
-      continue;
-    }
-
-    if (*spec != parent_spec) {
-      return -EINVAL;
-    }
-  }
-  return 0;
-}
-
-template <typename I>
-Context *SnapshotCopyRequest<I>::start_local_op() {
-  RWLock::RLocker owner_locker(m_local_image_ctx->owner_lock);
-  if (m_local_image_ctx->exclusive_lock == nullptr) {
-    return nullptr;
-  }
-  return m_local_image_ctx->exclusive_lock->start_op();
-}
-
-} // namespace image_sync
-} // namespace mirror
-} // namespace rbd
-
-template class rbd::mirror::image_sync::SnapshotCopyRequest<librbd::ImageCtx>;
diff --git a/src/tools/rbd_mirror/image_sync/SnapshotCopyRequest.h b/src/tools/rbd_mirror/image_sync/SnapshotCopyRequest.h
deleted file mode 100644 (file)
index 85ae4d4..0000000
+++ /dev/null
@@ -1,147 +0,0 @@
-// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
-// vim: ts=8 sw=2 smarttab
-
-#ifndef RBD_MIRROR_IMAGE_SYNC_SNAPSHOT_COPY_REQUEST_H
-#define RBD_MIRROR_IMAGE_SYNC_SNAPSHOT_COPY_REQUEST_H
-
-#include "include/int_types.h"
-#include "include/rados/librados.hpp"
-#include "common/snap_types.h"
-#include "librbd/ImageCtx.h"
-#include "librbd/Types.h"
-#include "librbd/journal/TypeTraits.h"
-#include "tools/rbd_mirror/BaseRequest.h"
-#include <map>
-#include <set>
-#include <string>
-#include <tuple>
-
-class Context;
-class ContextWQ;
-namespace journal { class Journaler; }
-namespace librbd { namespace journal { struct MirrorPeerClientMeta; } }
-
-namespace rbd {
-namespace mirror {
-namespace image_sync {
-
-template <typename ImageCtxT = librbd::ImageCtx>
-class SnapshotCopyRequest : public BaseRequest {
-public:
-  typedef librbd::journal::TypeTraits<ImageCtxT> TypeTraits;
-  typedef typename TypeTraits::Journaler Journaler;
-
-  typedef std::vector<librados::snap_t> SnapIds;
-  typedef std::map<librados::snap_t, SnapIds> SnapMap;
-
-  static SnapshotCopyRequest* create(ImageCtxT *local_image_ctx,
-                                     ImageCtxT *remote_image_ctx,
-                                     SnapMap *snap_map, Journaler *journaler,
-                                     librbd::journal::MirrorPeerClientMeta *client_meta,
-                                     ContextWQ *work_queue,
-                                     Context *on_finish) {
-    return new SnapshotCopyRequest(local_image_ctx, remote_image_ctx,
-                                   snap_map, journaler, client_meta, work_queue,
-                                   on_finish);
-  }
-
-  SnapshotCopyRequest(ImageCtxT *local_image_ctx, ImageCtxT *remote_image_ctx,
-                      SnapMap *snap_map, Journaler *journaler,
-                      librbd::journal::MirrorPeerClientMeta *client_meta,
-                      ContextWQ *work_queue, Context *on_finish);
-
-  void send() override;
-  void cancel() override;
-
-private:
-  /**
-   * @verbatim
-   *
-   * <start>
-   *    |
-   *    |   /-----------\
-   *    |   |           |
-   *    v   v           | (repeat as needed)
-   * UNPROTECT_SNAP ----/
-   *    |
-   *    |   /-----------\
-   *    |   |           |
-   *    v   v           | (repeat as needed)
-   * REMOVE_SNAP -------/
-   *    |
-   *    |   /-----------\
-   *    |   |           |
-   *    v   v           | (repeat as needed)
-   * CREATE_SNAP -------/
-   *    |
-   *    |   /-----------\
-   *    |   |           |
-   *    v   v           | (repeat as needed)
-   * PROTECT_SNAP ------/
-   *    |
-   *    v
-   * UPDATE_CLIENT
-   *    |
-   *    v
-   * <finish>
-   *
-   * @endverbatim
-   */
-
-  typedef std::set<librados::snap_t> SnapIdSet;
-  typedef std::map<librados::snap_t, librados::snap_t> SnapSeqs;
-
-  ImageCtxT *m_local_image_ctx;
-  ImageCtxT *m_remote_image_ctx;
-  SnapMap *m_snap_map;
-  Journaler *m_journaler;
-  librbd::journal::MirrorPeerClientMeta *m_client_meta;
-  ContextWQ *m_work_queue;
-
-  SnapIdSet m_local_snap_ids;
-  SnapIdSet m_remote_snap_ids;
-  SnapSeqs m_snap_seqs;
-  librados::snap_t m_prev_snap_id = CEPH_NOSNAP;
-
-  std::string m_snap_name;
-  cls::rbd::SnapshotNamespace m_snap_namespace;
-
-  librbd::ParentSpec m_local_parent_spec;
-
-  Mutex m_lock;
-  bool m_canceled = false;
-
-  void send_snap_unprotect();
-  void handle_snap_unprotect(int r);
-
-  void send_snap_remove();
-  void handle_snap_remove(int r);
-
-  void send_snap_create();
-  void handle_snap_create(int r);
-
-  void send_snap_protect();
-  void handle_snap_protect(int r);
-
-  void send_update_client();
-  void handle_update_client(int r);
-
-  bool handle_cancellation();
-
-  void error(int r);
-
-  void compute_snap_map();
-
-  int validate_parent(ImageCtxT *image_ctx, librbd::ParentSpec *spec);
-
-  Context *start_local_op();
-
-};
-
-} // namespace image_sync
-} // namespace mirror
-} // namespace rbd
-
-extern template class rbd::mirror::image_sync::SnapshotCopyRequest<librbd::ImageCtx>;
-
-#endif // RBD_MIRROR_IMAGE_SYNC_SNAPSHOT_COPY_REQUEST_H
diff --git a/src/tools/rbd_mirror/image_sync/SnapshotCreateRequest.cc b/src/tools/rbd_mirror/image_sync/SnapshotCreateRequest.cc
deleted file mode 100644 (file)
index 2384179..0000000
+++ /dev/null
@@ -1,334 +0,0 @@
-// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
-// vim: ts=8 sw=2 smarttab
-
-#include "SnapshotCreateRequest.h"
-#include "common/errno.h"
-#include "cls/rbd/cls_rbd_client.h"
-#include "cls/rbd/cls_rbd_types.h"
-#include "librbd/ExclusiveLock.h"
-#include "librbd/ObjectMap.h"
-#include "librbd/Operations.h"
-#include "librbd/Utils.h"
-#include "osdc/Striper.h"
-
-#define dout_context g_ceph_context
-#define dout_subsys ceph_subsys_rbd_mirror
-#undef dout_prefix
-#define dout_prefix *_dout << "rbd::mirror::image_sync::SnapshotCreateRequest: " \
-                           << this << " " << __func__
-
-namespace rbd {
-namespace mirror {
-namespace image_sync {
-
-using librbd::util::create_context_callback;
-using librbd::util::create_rados_callback;
-
-template <typename I>
-SnapshotCreateRequest<I>::SnapshotCreateRequest(I *local_image_ctx,
-                                                const std::string &snap_name,
-                                               const cls::rbd::SnapshotNamespace &snap_namespace,
-                                                uint64_t size,
-                                                const librbd::ParentSpec &spec,
-                                                uint64_t parent_overlap,
-                                                Context *on_finish)
-  : m_local_image_ctx(local_image_ctx), m_snap_name(snap_name),
-    m_snap_namespace(snap_namespace), m_size(size),
-    m_parent_spec(spec), m_parent_overlap(parent_overlap),
-    m_on_finish(on_finish) {
-}
-
-template <typename I>
-void SnapshotCreateRequest<I>::send() {
-  send_set_size();
-}
-
-template <typename I>
-void SnapshotCreateRequest<I>::send_set_size() {
-  m_local_image_ctx->snap_lock.get_read();
-  if (m_local_image_ctx->size == m_size) {
-    m_local_image_ctx->snap_lock.put_read();
-    send_remove_parent();
-    return;
-  }
-  m_local_image_ctx->snap_lock.put_read();
-
-  dout(20) << dendl;
-
-  // Change the image size on disk so that the snapshot picks up
-  // the expected size.  We can do this because the last snapshot
-  // we process is the sync snapshot which was created to match the
-  // image size. We also don't need to worry about trimming because
-  // we track the highest possible object number within the sync record
-  librados::ObjectWriteOperation op;
-  librbd::cls_client::set_size(&op, m_size);
-
-  auto finish_op_ctx = start_local_op();
-  if (finish_op_ctx == nullptr) {
-    derr << ": lost exclusive lock" << dendl;
-    finish(-EROFS);
-    return;
-  }
-
-  auto ctx = new FunctionContext([this, finish_op_ctx](int r) {
-      handle_set_size(r);
-      finish_op_ctx->complete(0);
-    });
-  librados::AioCompletion *comp = create_rados_callback(ctx);
-  int r = m_local_image_ctx->md_ctx.aio_operate(m_local_image_ctx->header_oid,
-                                                comp, &op);
-  assert(r == 0);
-  comp->release();
-}
-
-template <typename I>
-void SnapshotCreateRequest<I>::handle_set_size(int r) {
-  dout(20) << ": r=" << r << dendl;
-
-  if (r < 0) {
-    derr << ": failed to update image size '" << m_snap_name << "': "
-         << cpp_strerror(r) << dendl;
-    finish(r);
-    return;
-  }
-
-  {
-    // adjust in-memory image size now that it's updated on disk
-    RWLock::WLocker snap_locker(m_local_image_ctx->snap_lock);
-    m_local_image_ctx->size = m_size;
-  }
-
-  send_remove_parent();
-}
-
-template <typename I>
-void SnapshotCreateRequest<I>::send_remove_parent() {
-  m_local_image_ctx->parent_lock.get_read();
-  if (m_local_image_ctx->parent_md.spec.pool_id == -1 ||
-      m_local_image_ctx->parent_md.spec == m_parent_spec) {
-    m_local_image_ctx->parent_lock.put_read();
-    send_set_parent();
-    return;
-  }
-  m_local_image_ctx->parent_lock.put_read();
-
-  dout(20) << dendl;
-
-  librados::ObjectWriteOperation op;
-  librbd::cls_client::remove_parent(&op);
-
-  auto finish_op_ctx = start_local_op();
-  if (finish_op_ctx == nullptr) {
-    derr << ": lost exclusive lock" << dendl;
-    finish(-EROFS);
-    return;
-  }
-
-  auto ctx = new FunctionContext([this, finish_op_ctx](int r) {
-      handle_remove_parent(r);
-      finish_op_ctx->complete(0);
-    });
-  librados::AioCompletion *comp = create_rados_callback(ctx);
-  int r = m_local_image_ctx->md_ctx.aio_operate(m_local_image_ctx->header_oid,
-                                                comp, &op);
-  assert(r == 0);
-  comp->release();
-}
-
-template <typename I>
-void SnapshotCreateRequest<I>::handle_remove_parent(int r) {
-  dout(20) << ": r=" << r << dendl;
-
-  if (r < 0) {
-    derr << ": failed to remove parent '" << m_snap_name << "': "
-         << cpp_strerror(r) << dendl;
-    finish(r);
-    return;
-  }
-
-  {
-    // adjust in-memory parent now that it's updated on disk
-    RWLock::WLocker parent_locker(m_local_image_ctx->parent_lock);
-    m_local_image_ctx->parent_md.spec = {};
-    m_local_image_ctx->parent_md.overlap = 0;
-  }
-
-  send_set_parent();
-}
-
-template <typename I>
-void SnapshotCreateRequest<I>::send_set_parent() {
-  m_local_image_ctx->parent_lock.get_read();
-  if (m_local_image_ctx->parent_md.spec == m_parent_spec &&
-      m_local_image_ctx->parent_md.overlap == m_parent_overlap) {
-    m_local_image_ctx->parent_lock.put_read();
-    send_snap_create();
-    return;
-  }
-  m_local_image_ctx->parent_lock.put_read();
-
-  dout(20) << dendl;
-
-  librados::ObjectWriteOperation op;
-  librbd::cls_client::set_parent(&op, m_parent_spec, m_parent_overlap);
-
-  auto finish_op_ctx = start_local_op();
-  if (finish_op_ctx == nullptr) {
-    derr << ": lost exclusive lock" << dendl;
-    finish(-EROFS);
-    return;
-  }
-
-  auto ctx = new FunctionContext([this, finish_op_ctx](int r) {
-      handle_set_parent(r);
-      finish_op_ctx->complete(0);
-    });
-  librados::AioCompletion *comp = create_rados_callback(ctx);
-  int r = m_local_image_ctx->md_ctx.aio_operate(m_local_image_ctx->header_oid,
-                                                comp, &op);
-  assert(r == 0);
-  comp->release();
-}
-
-template <typename I>
-void SnapshotCreateRequest<I>::handle_set_parent(int r) {
-  dout(20) << ": r=" << r << dendl;
-
-  if (r < 0) {
-    derr << ": failed to set parent '" << m_snap_name << "': "
-         << cpp_strerror(r) << dendl;
-    finish(r);
-    return;
-  }
-
-  {
-    // adjust in-memory parent now that it's updated on disk
-    RWLock::WLocker parent_locker(m_local_image_ctx->parent_lock);
-    m_local_image_ctx->parent_md.spec = m_parent_spec;
-    m_local_image_ctx->parent_md.overlap = m_parent_overlap;
-  }
-
-  send_snap_create();
-}
-
-template <typename I>
-void SnapshotCreateRequest<I>::send_snap_create() {
-  dout(20) << ": snap_name=" << m_snap_name << dendl;
-
-  auto finish_op_ctx = start_local_op();
-  if (finish_op_ctx == nullptr) {
-    derr << ": lost exclusive lock" << dendl;
-    finish(-EROFS);
-    return;
-  }
-
-  auto ctx = new FunctionContext([this, finish_op_ctx](int r) {
-      handle_snap_create(r);
-      finish_op_ctx->complete(0);
-    });
-  RWLock::RLocker owner_locker(m_local_image_ctx->owner_lock);
-  m_local_image_ctx->operations->execute_snap_create(m_snap_namespace,
-                                                    m_snap_name.c_str(),
-                                                    ctx,
-                                                     0U, true);
-}
-
-template <typename I>
-void SnapshotCreateRequest<I>::handle_snap_create(int r) {
-  dout(20) << ": r=" << r << dendl;
-
-  if (r < 0) {
-    derr << ": failed to create snapshot '" << m_snap_name << "': "
-         << cpp_strerror(r) << dendl;
-    finish(r);
-    return;
-  }
-
-  send_create_object_map();
-}
-template <typename I>
-void SnapshotCreateRequest<I>::send_create_object_map() {
-
-  if (!m_local_image_ctx->test_features(RBD_FEATURE_OBJECT_MAP)) {
-    finish(0);
-    return;
-  }
-
-  m_local_image_ctx->snap_lock.get_read();
-  auto snap_it = m_local_image_ctx->snap_ids.find(
-    {cls::rbd::UserSnapshotNamespace(), m_snap_name});
-  if (snap_it == m_local_image_ctx->snap_ids.end()) {
-    derr << ": failed to locate snap: " << m_snap_name << dendl;
-    m_local_image_ctx->snap_lock.put_read();
-    finish(-ENOENT);
-    return;
-  }
-  librados::snap_t local_snap_id = snap_it->second;
-  m_local_image_ctx->snap_lock.put_read();
-
-  std::string object_map_oid(librbd::ObjectMap<>::object_map_name(
-    m_local_image_ctx->id, local_snap_id));
-  uint64_t object_count = Striper::get_num_objects(m_local_image_ctx->layout,
-                                                   m_size);
-  dout(20) << ": "
-           << "object_map_oid=" << object_map_oid << ", "
-           << "object_count=" << object_count << dendl;
-
-  // initialize an empty object map of the correct size (object sync
-  // will populate the object map)
-  librados::ObjectWriteOperation op;
-  librbd::cls_client::object_map_resize(&op, object_count, OBJECT_NONEXISTENT);
-
-  auto finish_op_ctx = start_local_op();
-  if (finish_op_ctx == nullptr) {
-    derr << ": lost exclusive lock" << dendl;
-    finish(-EROFS);
-    return;
-  }
-
-  auto ctx = new FunctionContext([this, finish_op_ctx](int r) {
-      handle_create_object_map(r);
-      finish_op_ctx->complete(0);
-    });
-  librados::AioCompletion *comp = create_rados_callback(ctx);
-  int r = m_local_image_ctx->md_ctx.aio_operate(object_map_oid, comp, &op);
-  assert(r == 0);
-  comp->release();
-}
-
-template <typename I>
-void SnapshotCreateRequest<I>::handle_create_object_map(int r) {
-  dout(20) << ": r=" << r << dendl;
-
-  if (r < 0) {
-    derr << ": failed to create object map: " << cpp_strerror(r)
-         << dendl;
-    finish(r);
-    return;
-  }
-
-  finish(0);
-}
-
-template <typename I>
-Context *SnapshotCreateRequest<I>::start_local_op() {
-  RWLock::RLocker owner_locker(m_local_image_ctx->owner_lock);
-  if (m_local_image_ctx->exclusive_lock == nullptr) {
-    return nullptr;
-  }
-  return m_local_image_ctx->exclusive_lock->start_op();
-}
-
-template <typename I>
-void SnapshotCreateRequest<I>::finish(int r) {
-  dout(20) << ": r=" << r << dendl;
-
-  m_on_finish->complete(r);
-  delete this;
-}
-
-} // namespace image_sync
-} // namespace mirror
-} // namespace rbd
-
-template class rbd::mirror::image_sync::SnapshotCreateRequest<librbd::ImageCtx>;
diff --git a/src/tools/rbd_mirror/image_sync/SnapshotCreateRequest.h b/src/tools/rbd_mirror/image_sync/SnapshotCreateRequest.h
deleted file mode 100644 (file)
index 503a164..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
-// vim: ts=8 sw=2 smarttab
-
-#ifndef RBD_MIRROR_IMAGE_SYNC_SNAPSHOT_CREATE_REQUEST_H
-#define RBD_MIRROR_IMAGE_SYNC_SNAPSHOT_CREATE_REQUEST_H
-
-#include "include/int_types.h"
-#include "include/rados/librados.hpp"
-#include "common/snap_types.h"
-#include "librbd/ImageCtx.h"
-#include "librbd/Types.h"
-#include "librbd/journal/TypeTraits.h"
-#include <map>
-#include <set>
-#include <string>
-#include <tuple>
-
-class Context;
-
-namespace rbd {
-namespace mirror {
-namespace image_sync {
-
-template <typename ImageCtxT = librbd::ImageCtx>
-class SnapshotCreateRequest {
-public:
-  static SnapshotCreateRequest* create(ImageCtxT *local_image_ctx,
-                                       const std::string &snap_name,
-                                       const cls::rbd::SnapshotNamespace &snap_namespace,
-                                       uint64_t size,
-                                       const librbd::ParentSpec &parent_spec,
-                                       uint64_t parent_overlap,
-                                       Context *on_finish) {
-    return new SnapshotCreateRequest(local_image_ctx, snap_name, snap_namespace, size,
-                                     parent_spec, parent_overlap, on_finish);
-  }
-
-  SnapshotCreateRequest(ImageCtxT *local_image_ctx,
-                        const std::string &snap_name,
-                       const cls::rbd::SnapshotNamespace &snap_namespace,
-                       uint64_t size,
-                        const librbd::ParentSpec &parent_spec,
-                        uint64_t parent_overlap, Context *on_finish);
-
-  void send();
-
-private:
-  /**
-   * @verbatim
-   *
-   * <start>
-   *    |
-   *    v (skip if not needed)
-   * SET_SIZE
-   *    |
-   *    v (skip if not needed)
-   * REMOVE_PARENT
-   *    |
-   *    v (skip if not needed)
-   * SET_PARENT
-   *    |
-   *    v
-   * CREATE_SNAP
-   *    |
-   *    v (skip if not needed)
-   * CREATE_OBJECT_MAP
-   *    |
-   *    v
-   * <finish>
-   *
-   * @endverbatim
-   */
-
-  ImageCtxT *m_local_image_ctx;
-  std::string m_snap_name;
-  cls::rbd::SnapshotNamespace m_snap_namespace;
-  uint64_t m_size;
-  librbd::ParentSpec m_parent_spec;
-  uint64_t m_parent_overlap;
-  Context *m_on_finish;
-
-  void send_set_size();
-  void handle_set_size(int r);
-
-  void send_remove_parent();
-  void handle_remove_parent(int r);
-
-  void send_set_parent();
-  void handle_set_parent(int r);
-
-  void send_snap_create();
-  void handle_snap_create(int r);
-
-  void send_create_object_map();
-  void handle_create_object_map(int r);
-
-  Context *start_local_op();
-
-  void finish(int r);
-};
-
-} // namespace image_sync
-} // namespace mirror
-} // namespace rbd
-
-extern template class rbd::mirror::image_sync::SnapshotCreateRequest<librbd::ImageCtx>;
-
-#endif // RBD_MIRROR_IMAGE_SYNC_SNAPSHOT_CREATE_REQUEST_H