From: Jason Dillaman Date: Fri, 29 Apr 2016 20:43:07 +0000 (-0400) Subject: librbd: optionally skip object map creation upon snapshot X-Git-Tag: v10.2.1~14^2~9 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=fa8a61df1570893e222c0d9431ba61e192a23c40;p=ceph.git librbd: optionally skip object map creation upon snapshot This feature is used by rbd-mirror during image bootstrap since it will directly create an empty object map. Signed-off-by: Jason Dillaman (cherry picked from commit db16240c79be7e28d65edac2088352b9b146da5f) --- diff --git a/src/librbd/ImageWatcher.cc b/src/librbd/ImageWatcher.cc index b48974e9925f..d3d4e701a736 100644 --- a/src/librbd/ImageWatcher.cc +++ b/src/librbd/ImageWatcher.cc @@ -714,7 +714,7 @@ bool ImageWatcher::handle_payload(const SnapCreatePayload &payload, m_image_ctx.operations->execute_snap_create(payload.snap_name.c_str(), new C_ResponseMessage(ack_ctx), - 0); + 0, false); return false; } return true; diff --git a/src/librbd/Operations.cc b/src/librbd/Operations.cc index 620b0bf6cee1..c523b912680d 100644 --- a/src/librbd/Operations.cc +++ b/src/librbd/Operations.cc @@ -596,7 +596,8 @@ void Operations::snap_create(const char *snap_name, Context *on_finish) { C_InvokeAsyncRequest *req = new C_InvokeAsyncRequest( m_image_ctx, "snap_create", true, - boost::bind(&Operations::execute_snap_create, this, snap_name, _1, 0), + boost::bind(&Operations::execute_snap_create, this, snap_name, _1, 0, + false), boost::bind(&ImageWatcher::notify_snap_create, m_image_ctx.image_watcher, snap_name, _1), {-EEXIST}, on_finish); @@ -606,7 +607,8 @@ void Operations::snap_create(const char *snap_name, Context *on_finish) { template void Operations::execute_snap_create(const char *snap_name, Context *on_finish, - uint64_t journal_op_tid) { + uint64_t journal_op_tid, + bool skip_object_map) { assert(m_image_ctx.owner_lock.is_locked()); assert(m_image_ctx.exclusive_lock == nullptr || m_image_ctx.exclusive_lock->is_lock_owner()); @@ -618,7 +620,7 @@ void Operations::execute_snap_create(const char *snap_name, operation::SnapshotCreateRequest *req = new operation::SnapshotCreateRequest( m_image_ctx, new C_NotifyUpdate(m_image_ctx, on_finish), snap_name, - journal_op_tid); + journal_op_tid, skip_object_map); req->send(); } diff --git a/src/librbd/Operations.h b/src/librbd/Operations.h index a32116a01566..95af4dcf1e96 100644 --- a/src/librbd/Operations.h +++ b/src/librbd/Operations.h @@ -38,7 +38,7 @@ public: int snap_create(const char *snap_name); void snap_create(const char *snap_name, Context *on_finish); void execute_snap_create(const char *snap_name, Context *on_finish, - uint64_t journal_op_tid); + uint64_t journal_op_tid, bool skip_object_map); int snap_rollback(const char *snap_name, ProgressContext& prog_ctx); void execute_snap_rollback(const char *snap_name, ProgressContext& prog_ctx, diff --git a/src/librbd/journal/Replay.cc b/src/librbd/journal/Replay.cc index efe534c7fcdb..c6c4f55b602f 100644 --- a/src/librbd/journal/Replay.cc +++ b/src/librbd/journal/Replay.cc @@ -41,7 +41,7 @@ struct ExecuteOp : public Context { void execute(const journal::SnapCreateEvent &_) { image_ctx.operations->execute_snap_create(event.snap_name.c_str(), on_op_complete, - event.op_tid); + event.op_tid, false); } void execute(const journal::SnapRemoveEvent &_) { diff --git a/src/librbd/operation/SnapshotCreateRequest.cc b/src/librbd/operation/SnapshotCreateRequest.cc index e4a1fc31e166..cb92c6cac764 100644 --- a/src/librbd/operation/SnapshotCreateRequest.cc +++ b/src/librbd/operation/SnapshotCreateRequest.cc @@ -62,9 +62,10 @@ template SnapshotCreateRequest::SnapshotCreateRequest(I &image_ctx, Context *on_finish, const std::string &snap_name, - uint64_t journal_op_tid) + uint64_t journal_op_tid, + bool skip_object_map) : Request(image_ctx, on_finish, journal_op_tid), m_snap_name(snap_name), - m_ret_val(0), m_snap_id(CEPH_NOSNAP) { + m_skip_object_map(skip_object_map), m_ret_val(0), m_snap_id(CEPH_NOSNAP) { } template @@ -247,7 +248,7 @@ Context *SnapshotCreateRequest::send_create_object_map() { update_snap_context(); image_ctx.snap_lock.get_read(); - if (image_ctx.object_map == nullptr) { + if (image_ctx.object_map == nullptr || m_skip_object_map) { image_ctx.snap_lock.put_read(); finalize(0); diff --git a/src/librbd/operation/SnapshotCreateRequest.h b/src/librbd/operation/SnapshotCreateRequest.h index 6b5268189629..35f8b53d60ab 100644 --- a/src/librbd/operation/SnapshotCreateRequest.h +++ b/src/librbd/operation/SnapshotCreateRequest.h @@ -60,7 +60,8 @@ public: * (if enabled) and bubble the originating error code back to the client. */ SnapshotCreateRequest(ImageCtxT &image_ctx, Context *on_finish, - const std::string &snap_name, uint64_t journal_op_tid); + const std::string &snap_name, uint64_t journal_op_tid, + bool skip_object_map); protected: virtual void send_op(); @@ -76,6 +77,7 @@ protected: private: std::string m_snap_name; + bool m_skip_object_map; int m_ret_val; diff --git a/src/test/librbd/journal/test_mock_Replay.cc b/src/test/librbd/journal/test_mock_Replay.cc index 2fc434433477..f4145e1f6b1b 100644 --- a/src/test/librbd/journal/test_mock_Replay.cc +++ b/src/test/librbd/journal/test_mock_Replay.cc @@ -147,7 +147,7 @@ public: Context **on_finish, const char *snap_name, uint64_t op_tid) { EXPECT_CALL(*mock_image_ctx.operations, execute_snap_create(CStrEq(snap_name), _, - op_tid)) + op_tid, false)) .WillOnce(DoAll(SaveArg<1>(on_finish), NotifyInvoke(&m_invoke_lock, &m_invoke_cond))); } diff --git a/src/test/librbd/mock/MockOperations.h b/src/test/librbd/mock/MockOperations.h index c92578a36f1a..5bbd9b364968 100644 --- a/src/test/librbd/mock/MockOperations.h +++ b/src/test/librbd/mock/MockOperations.h @@ -22,9 +22,10 @@ struct MockOperations { Context *on_finish, uint64_t journal_op_tid)); MOCK_METHOD2(snap_create, void(const char *snap_name, Context *on_finish)); - MOCK_METHOD3(execute_snap_create, void(const char *snap_name, + MOCK_METHOD4(execute_snap_create, void(const char *snap_name, Context *on_finish, - uint64_t journal_op_tid)); + uint64_t journal_op_tid, + bool skip_object_map)); MOCK_METHOD2(snap_remove, void(const char *snap_name, Context *on_finish)); MOCK_METHOD2(execute_snap_remove, void(const char *snap_name, Context *on_finish)); diff --git a/src/test/librbd/operation/test_mock_SnapshotCreateRequest.cc b/src/test/librbd/operation/test_mock_SnapshotCreateRequest.cc index 8cc5fda42cfa..1b94b7e1f9f1 100644 --- a/src/test/librbd/operation/test_mock_SnapshotCreateRequest.cc +++ b/src/test/librbd/operation/test_mock_SnapshotCreateRequest.cc @@ -138,7 +138,7 @@ TEST_F(TestMockOperationSnapshotCreateRequest, Success) { C_SaferCond cond_ctx; MockSnapshotCreateRequest *req = new MockSnapshotCreateRequest( - mock_image_ctx, &cond_ctx, "snap1", 0); + mock_image_ctx, &cond_ctx, "snap1", 0, false); { RWLock::RLocker owner_locker(mock_image_ctx.owner_lock); req->send(); @@ -167,7 +167,7 @@ TEST_F(TestMockOperationSnapshotCreateRequest, AllocateSnapIdError) { C_SaferCond cond_ctx; MockSnapshotCreateRequest *req = new MockSnapshotCreateRequest( - mock_image_ctx, &cond_ctx, "snap1", 0); + mock_image_ctx, &cond_ctx, "snap1", 0, false); { RWLock::RLocker owner_locker(mock_image_ctx.owner_lock); req->send(); @@ -205,7 +205,7 @@ TEST_F(TestMockOperationSnapshotCreateRequest, CreateSnapStale) { C_SaferCond cond_ctx; MockSnapshotCreateRequest *req = new MockSnapshotCreateRequest( - mock_image_ctx, &cond_ctx, "snap1", 0); + mock_image_ctx, &cond_ctx, "snap1", 0, false); { RWLock::RLocker owner_locker(mock_image_ctx.owner_lock); req->send(); @@ -235,7 +235,7 @@ TEST_F(TestMockOperationSnapshotCreateRequest, CreateSnapError) { C_SaferCond cond_ctx; MockSnapshotCreateRequest *req = new MockSnapshotCreateRequest( - mock_image_ctx, &cond_ctx, "snap1", 0); + mock_image_ctx, &cond_ctx, "snap1", 0, false); { RWLock::RLocker owner_locker(mock_image_ctx.owner_lock); req->send(); @@ -265,7 +265,7 @@ TEST_F(TestMockOperationSnapshotCreateRequest, ReleaseSnapIdError) { C_SaferCond cond_ctx; MockSnapshotCreateRequest *req = new MockSnapshotCreateRequest( - mock_image_ctx, &cond_ctx, "snap1", 0); + mock_image_ctx, &cond_ctx, "snap1", 0, false); { RWLock::RLocker owner_locker(mock_image_ctx.owner_lock); req->send(); @@ -273,5 +273,41 @@ TEST_F(TestMockOperationSnapshotCreateRequest, ReleaseSnapIdError) { ASSERT_EQ(-EINVAL, cond_ctx.wait()); } +TEST_F(TestMockOperationSnapshotCreateRequest, SkipObjectMap) { + REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP); + + librbd::ImageCtx *ictx; + ASSERT_EQ(0, open_image(m_image_name, &ictx)); + + MockImageCtx mock_image_ctx(*ictx); + + MockExclusiveLock mock_exclusive_lock; + if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) { + mock_image_ctx.exclusive_lock = &mock_exclusive_lock; + } + + MockObjectMap mock_object_map; + mock_image_ctx.object_map = &mock_object_map; + + expect_verify_lock_ownership(mock_image_ctx); + expect_op_work_queue(mock_image_ctx); + + ::testing::InSequence seq; + expect_block_writes(mock_image_ctx); + expect_allocate_snap_id(mock_image_ctx, 0); + expect_snap_create(mock_image_ctx, 0); + expect_update_snap_context(mock_image_ctx); + expect_unblock_writes(mock_image_ctx); + + C_SaferCond cond_ctx; + MockSnapshotCreateRequest *req = new MockSnapshotCreateRequest( + mock_image_ctx, &cond_ctx, "snap1", 0, true); + { + RWLock::RLocker owner_locker(mock_image_ctx.owner_lock); + req->send(); + } + ASSERT_EQ(0, cond_ctx.wait()); +} + } // namespace operation } // namespace librbd 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 f8778212053b..5d8d78d991f3 100644 --- a/src/test/rbd_mirror/image_sync/test_mock_SnapshotCreateRequest.cc +++ b/src/test/rbd_mirror/image_sync/test_mock_SnapshotCreateRequest.cc @@ -49,7 +49,7 @@ public: void expect_snap_create(librbd::MockImageCtx &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)) + 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); }), diff --git a/src/tools/rbd_mirror/image_sync/SnapshotCreateRequest.cc b/src/tools/rbd_mirror/image_sync/SnapshotCreateRequest.cc index 7b5ce250cb93..ec69dffb8b82 100644 --- a/src/tools/rbd_mirror/image_sync/SnapshotCreateRequest.cc +++ b/src/tools/rbd_mirror/image_sync/SnapshotCreateRequest.cc @@ -130,7 +130,7 @@ void SnapshotCreateRequest::send_snap_create() { this); RWLock::RLocker owner_locker(m_local_image_ctx->owner_lock); m_local_image_ctx->operations->execute_snap_create(m_snap_name.c_str(), ctx, - 0U); + 0U, true); } template