]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rbd-mirror: allocate empty object map during snapshot create
authorJason Dillaman <dillaman@redhat.com>
Wed, 4 May 2016 01:42:05 +0000 (21:42 -0400)
committerJason Dillaman <dillaman@redhat.com>
Tue, 10 May 2016 17:43:49 +0000 (13:43 -0400)
Signed-off-by: Jason Dillaman <dillaman@redhat.com>
(cherry picked from commit 57a7fe0f44c5542a72120d0beed8b38e9ccd66db)

src/test/rbd_mirror/image_sync/test_mock_SnapshotCreateRequest.cc
src/tools/rbd_mirror/image_sync/SnapshotCopyRequest.cc
src/tools/rbd_mirror/image_sync/SnapshotCreateRequest.cc

index 5d8d78d991f3996b595da78d26db20cbe5c71d10..dd8305de02499458321b4e373f9d21cfe58e9f96 100644 (file)
@@ -7,6 +7,7 @@
 #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"
@@ -41,6 +42,12 @@ public:
     ASSERT_EQ(0, open_image(m_local_io_ctx, m_image_name, &m_local_image_ctx));
   }
 
+  void expect_test_features(librbd::MockImageCtx &mock_image_ctx,
+                            uint64_t features, bool enabled) {
+    EXPECT_CALL(mock_image_ctx, test_features(features))
+                  .WillOnce(Return(enabled));
+  }
+
   void expect_set_size(librbd::MockImageCtx &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"), _, _, _))
@@ -58,6 +65,15 @@ public:
                                   }))));
   }
 
+  void expect_object_map_resize(librbd::MockImageCtx &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::MockImageCtx &mock_image_ctx,
                    uint64_t snap_id, const std::string &snap_name) {
     mock_image_ctx.snap_ids[snap_name] = snap_id;
@@ -79,6 +95,7 @@ TEST_F(TestMockImageSyncSnapshotCreateRequest, Resize) {
   InSequence seq;
   expect_set_size(mock_local_image_ctx, 0);
   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,
@@ -107,6 +124,7 @@ TEST_F(TestMockImageSyncSnapshotCreateRequest, SnapCreate) {
 
   InSequence seq;
   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,
@@ -132,6 +150,40 @@ TEST_F(TestMockImageSyncSnapshotCreateRequest, SnapCreateError) {
   ASSERT_EQ(-EINVAL, ctx.wait());
 }
 
+TEST_F(TestMockImageSyncSnapshotCreateRequest, ResizeObjectMap) {
+  librbd::MockImageCtx mock_local_image_ctx(*m_local_image_ctx);
+
+  InSequence seq;
+  expect_snap_create(mock_local_image_ctx, "snap1", 10, 0);
+  expect_test_features(mock_local_image_ctx, RBD_FEATURE_OBJECT_MAP, true);
+  expect_object_map_resize(mock_local_image_ctx, 10, 0);
+
+  C_SaferCond ctx;
+  MockSnapshotCreateRequest *request = create_request(mock_local_image_ctx,
+                                                      "snap1",
+                                                      m_local_image_ctx->size,
+                                                      &ctx);
+  request->send();
+  ASSERT_EQ(0, ctx.wait());
+}
+
+TEST_F(TestMockImageSyncSnapshotCreateRequest, ResizeObjectMapError) {
+  librbd::MockImageCtx mock_local_image_ctx(*m_local_image_ctx);
+
+  InSequence seq;
+  expect_snap_create(mock_local_image_ctx, "snap1", 10, 0);
+  expect_test_features(mock_local_image_ctx, RBD_FEATURE_OBJECT_MAP, true);
+  expect_object_map_resize(mock_local_image_ctx, 10, -EINVAL);
+
+  C_SaferCond ctx;
+  MockSnapshotCreateRequest *request = create_request(mock_local_image_ctx,
+                                                      "snap1",
+                                                      m_local_image_ctx->size,
+                                                      &ctx);
+  request->send();
+  ASSERT_EQ(-EINVAL, ctx.wait());
+}
+
 } // namespace image_sync
 } // namespace mirror
 } // namespace rbd
index 9d90bc9a37d20b8a6d8c5134e65bc36abaf3f405..016e4b4e4bbbb76de6d1c949471d8747d966cb9f 100644 (file)
@@ -276,7 +276,8 @@ void SnapshotCopyRequest<I>::send_snap_create() {
 
   ldout(cct, 20) << ": "
                  << "snap_name=" << m_snap_name << ", "
-                 << "snap_id=" << m_prev_snap_id << dendl;
+                 << "snap_id=" << m_prev_snap_id << ", "
+                 << "size=" << size << dendl;
 
   Context *ctx = create_context_callback<
     SnapshotCopyRequest<I>, &SnapshotCopyRequest<I>::handle_snap_create>(
index ec69dffb8b82ec41f39cf9afe13848abf193aea5..60d03ffa1eb91ae167a2aeb4dd03fe8e98554cbd 100644 (file)
@@ -4,8 +4,10 @@
 #include "SnapshotCreateRequest.h"
 #include "common/errno.h"
 #include "cls/rbd/cls_rbd_client.h"
+#include "librbd/ObjectMap.h"
 #include "librbd/Operations.h"
 #include "librbd/Utils.h"
+#include "osdc/Striper.h"
 
 #define dout_subsys ceph_subsys_rbd_mirror
 #undef dout_prefix
@@ -149,15 +151,43 @@ void SnapshotCreateRequest<I>::handle_snap_create(int r) {
 }
 template <typename I>
 void SnapshotCreateRequest<I>::send_create_object_map() {
-  // TODO
-  if (true) {
+  CephContext *cct = m_local_image_ctx->cct;
+
+  if (!m_local_image_ctx->test_features(RBD_FEATURE_OBJECT_MAP)) {
     finish(0);
     return;
   }
 
-  CephContext *cct = m_local_image_ctx->cct;
-  ldout(cct, 20) << dendl;
+  m_local_image_ctx->snap_lock.get_read();
+  auto snap_it = m_local_image_ctx->snap_ids.find(m_snap_name);
+  if (snap_it == m_local_image_ctx->snap_ids.end()) {
+    lderr(cct) << "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);
+  ldout(cct, 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);
 
+  librados::AioCompletion *comp = create_rados_safe_callback<
+    SnapshotCreateRequest<I>,
+    &SnapshotCreateRequest<I>::handle_create_object_map>(this);
+  int r = m_local_image_ctx->md_ctx.aio_operate(object_map_oid, comp, &op);
+  assert(r == 0);
+  comp->release();
 }
 
 template <typename I>