From: Jason Dillaman Date: Wed, 4 May 2016 01:42:05 +0000 (-0400) Subject: rbd-mirror: allocate empty object map during snapshot create X-Git-Tag: v11.0.0~602^2~8 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=57a7fe0f44c5542a72120d0beed8b38e9ccd66db;p=ceph.git rbd-mirror: allocate empty object map during snapshot create Signed-off-by: Jason Dillaman --- diff --git a/src/test/rbd_mirror/image_sync/test_mock_SnapshotCreateRequest.cc b/src/test/rbd_mirror/image_sync/test_mock_SnapshotCreateRequest.cc index 5d8d78d991f3..dd8305de0249 100644 --- a/src/test/rbd_mirror/image_sync/test_mock_SnapshotCreateRequest.cc +++ b/src/test/rbd_mirror/image_sync/test_mock_SnapshotCreateRequest.cc @@ -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 diff --git a/src/tools/rbd_mirror/image_sync/SnapshotCopyRequest.cc b/src/tools/rbd_mirror/image_sync/SnapshotCopyRequest.cc index 9d90bc9a37d2..016e4b4e4bbb 100644 --- a/src/tools/rbd_mirror/image_sync/SnapshotCopyRequest.cc +++ b/src/tools/rbd_mirror/image_sync/SnapshotCopyRequest.cc @@ -276,7 +276,8 @@ void SnapshotCopyRequest::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, &SnapshotCopyRequest::handle_snap_create>( diff --git a/src/tools/rbd_mirror/image_sync/SnapshotCreateRequest.cc b/src/tools/rbd_mirror/image_sync/SnapshotCreateRequest.cc index ec69dffb8b82..60d03ffa1eb9 100644 --- a/src/tools/rbd_mirror/image_sync/SnapshotCreateRequest.cc +++ b/src/tools/rbd_mirror/image_sync/SnapshotCreateRequest.cc @@ -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::handle_snap_create(int r) { } template void SnapshotCreateRequest::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, + &SnapshotCreateRequest::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