From 3c11d5a2eb39e68a36c1eaf64805809c9d38d82e Mon Sep 17 00:00:00 2001 From: Or Ozeri Date: Mon, 2 Nov 2020 15:20:18 +0200 Subject: [PATCH] librbd: add encryption support for copyup This commit implements the prepare_copyup api by the crypto object dispatch layer. Signed-off-by: Or Ozeri --- src/librbd/cache/ObjectCacherObjectDispatch.h | 3 +- src/librbd/cache/ParentCacheObjectDispatch.h | 3 +- src/librbd/cache/WriteAroundObjectDispatch.h | 3 +- src/librbd/crypto/CryptoObjectDispatch.cc | 60 +++++++++++++++++++ src/librbd/crypto/CryptoObjectDispatch.h | 5 +- src/librbd/deep_copy/ObjectCopyRequest.cc | 8 ++- src/librbd/io/CopyupRequest.cc | 20 ++++++- src/librbd/io/CopyupRequest.h | 2 +- src/librbd/io/ObjectDispatch.h | 3 +- src/librbd/io/ObjectDispatchInterface.h | 2 +- src/librbd/io/ObjectDispatcher.cc | 10 +++- src/librbd/io/ObjectDispatcher.h | 2 +- src/librbd/io/ObjectDispatcherInterface.h | 2 +- src/librbd/io/SimpleSchedulerObjectDispatch.h | 3 +- src/librbd/journal/ObjectDispatch.h | 3 +- .../crypto/test_mock_CryptoObjectDispatch.cc | 57 ++++++++++++++++++ .../deep_copy/test_mock_ObjectCopyRequest.cc | 43 ++++++++++++- src/test/librbd/io/test_mock_CopyupRequest.cc | 40 ++++++++++++- src/test/librbd/mock/io/MockObjectDispatch.h | 2 +- .../librbd/mock/io/MockObjectDispatcher.h | 2 +- 20 files changed, 248 insertions(+), 25 deletions(-) diff --git a/src/librbd/cache/ObjectCacherObjectDispatch.h b/src/librbd/cache/ObjectCacherObjectDispatch.h index 5762c6914397b..0cc87bd87ba80 100644 --- a/src/librbd/cache/ObjectCacherObjectDispatch.h +++ b/src/librbd/cache/ObjectCacherObjectDispatch.h @@ -101,9 +101,10 @@ public: uint64_t journal_tid, uint64_t new_journal_tid) { } - void prepare_copyup( + int prepare_copyup( uint64_t object_no, io::SnapshotSparseBufferlist* snapshot_sparse_bufferlist) override { + return 0; } private: diff --git a/src/librbd/cache/ParentCacheObjectDispatch.h b/src/librbd/cache/ParentCacheObjectDispatch.h index 6d9c90828c080..1cf9c73b07cf7 100644 --- a/src/librbd/cache/ParentCacheObjectDispatch.h +++ b/src/librbd/cache/ParentCacheObjectDispatch.h @@ -118,9 +118,10 @@ public: uint64_t journal_tid, uint64_t new_journal_tid) { } - void prepare_copyup( + int prepare_copyup( uint64_t object_no, io::SnapshotSparseBufferlist* snapshot_sparse_bufferlist) override { + return 0; } ImageCtxT* get_image_ctx() { diff --git a/src/librbd/cache/WriteAroundObjectDispatch.h b/src/librbd/cache/WriteAroundObjectDispatch.h index b91ab979e1ea0..bc289f91cc84f 100644 --- a/src/librbd/cache/WriteAroundObjectDispatch.h +++ b/src/librbd/cache/WriteAroundObjectDispatch.h @@ -106,9 +106,10 @@ public: uint64_t journal_tid, uint64_t new_journal_tid) override { } - void prepare_copyup( + int prepare_copyup( uint64_t object_no, io::SnapshotSparseBufferlist* snapshot_sparse_bufferlist) override { + return 0; } private: diff --git a/src/librbd/crypto/CryptoObjectDispatch.cc b/src/librbd/crypto/CryptoObjectDispatch.cc index b09aad720a6b5..4110c2e5a8ba9 100644 --- a/src/librbd/crypto/CryptoObjectDispatch.cc +++ b/src/librbd/crypto/CryptoObjectDispatch.cc @@ -591,6 +591,66 @@ bool CryptoObjectDispatch::discard( return true; } +template +int CryptoObjectDispatch::prepare_copyup( + uint64_t object_no, + io::SnapshotSparseBufferlist* snapshot_sparse_bufferlist) { + ceph::bufferlist current_bl; + current_bl.append_zero(m_image_ctx->get_object_size()); + + for (auto& [key, extent_map]: *snapshot_sparse_bufferlist) { + // update current_bl with data from extent_map + for (auto& extent : extent_map) { + auto &sbe = extent.get_val(); + if (sbe.state == io::SPARSE_EXTENT_STATE_DATA) { + current_bl.begin(extent.get_off()).copy_in(extent.get_len(), sbe.bl); + } else if (sbe.state == io::SPARSE_EXTENT_STATE_ZEROED) { + ceph::bufferlist zeros; + zeros.append_zero(extent.get_len()); + current_bl.begin(extent.get_off()).copy_in(extent.get_len(), zeros); + } + } + + // encrypt + io::SparseBufferlist encrypted_sparse_bufferlist; + for (auto& extent : extent_map) { + auto [aligned_off, aligned_len] = m_crypto->align( + extent.get_off(), extent.get_len()); + + io::Extents image_extents; + Striper::extent_to_file( + m_image_ctx->cct, &m_image_ctx->layout, object_no, aligned_off, + aligned_len, image_extents); + + ceph::bufferlist encrypted_bl; + uint64_t position = 0; + for (auto [image_offset, image_length]: image_extents) { + ceph::bufferlist aligned_bl; + aligned_bl.substr_of(current_bl, aligned_off + position, image_length); + aligned_bl.rebuild(); // to deep copy aligned_bl from current_bl + position += image_length; + + auto r = m_crypto->encrypt(&aligned_bl, image_offset); + if (r != 0) { + return r; + } + + encrypted_bl.append(aligned_bl); + } + + encrypted_sparse_bufferlist.insert( + aligned_off, aligned_len, {io::SPARSE_EXTENT_STATE_DATA, aligned_len, + std::move(encrypted_bl)}); + } + + // replace original plaintext sparse bufferlist with encrypted one + extent_map.clear(); + extent_map.insert(std::move(encrypted_sparse_bufferlist)); + } + + return 0; +} + } // namespace crypto } // namespace librbd diff --git a/src/librbd/crypto/CryptoObjectDispatch.h b/src/librbd/crypto/CryptoObjectDispatch.h index a6cd87a9468fd..6df32ffee6d36 100644 --- a/src/librbd/crypto/CryptoObjectDispatch.h +++ b/src/librbd/crypto/CryptoObjectDispatch.h @@ -98,10 +98,9 @@ public: uint64_t journal_tid, uint64_t new_journal_tid) override { } - void prepare_copyup( + int prepare_copyup( uint64_t object_no, - io::SnapshotSparseBufferlist* snapshot_sparse_bufferlist) override { - } + io::SnapshotSparseBufferlist* snapshot_sparse_bufferlist) override; private: diff --git a/src/librbd/deep_copy/ObjectCopyRequest.cc b/src/librbd/deep_copy/ObjectCopyRequest.cc index aa8dfdfe8c39d..13cff743e6369 100644 --- a/src/librbd/deep_copy/ObjectCopyRequest.cc +++ b/src/librbd/deep_copy/ObjectCopyRequest.cc @@ -277,8 +277,14 @@ void ObjectCopyRequest::process_copyup() { // let dispatch layers have a chance to process the data but // assume that the dispatch layer will only touch the sparse bufferlist - m_dst_image_ctx->io_object_dispatcher->prepare_copyup( + auto r = m_dst_image_ctx->io_object_dispatcher->prepare_copyup( m_dst_object_number, &m_snapshot_sparse_bufferlist); + if (r < 0) { + lderr(m_cct) << "failed to prepare copyup data: " << cpp_strerror(r) + << dendl; + finish(r); + return; + } send_write_object(); } diff --git a/src/librbd/io/CopyupRequest.cc b/src/librbd/io/CopyupRequest.cc index 93effcb1cbb68..4be133076c2b1 100644 --- a/src/librbd/io/CopyupRequest.cc +++ b/src/librbd/io/CopyupRequest.cc @@ -209,7 +209,16 @@ void CopyupRequest::handle_read_from_parent(int r) { m_lock.lock(); disable_append_requests(); - prepare_copyup_data(); + r = prepare_copyup_data(); + if (r < 0) { + m_lock.unlock(); + m_image_ctx->image_lock.unlock_shared(); + + lderr(m_image_ctx->cct) << "failed to prepare copyup data: " + << cpp_strerror(r) << dendl; + finish(r); + return; + } m_copyup_is_zero = m_copyup_data.is_zero(); m_copyup_required = is_copyup_required(); @@ -678,7 +687,7 @@ void CopyupRequest::convert_copyup_extent_map() { } template -void CopyupRequest::prepare_copyup_data() { +int CopyupRequest::prepare_copyup_data() { ceph_assert(ceph_mutex_is_locked(m_image_ctx->image_lock)); auto cct = m_image_ctx->cct; @@ -735,8 +744,11 @@ void CopyupRequest::prepare_copyup_data() { } // Let dispatch layers have a chance to process the data - m_image_ctx->io_object_dispatcher->prepare_copyup( + auto r = m_image_ctx->io_object_dispatcher->prepare_copyup( m_object_no, &snapshot_sparse_bufferlist); + if (r < 0) { + return r; + } // Convert sparse extents back to extent map m_copyup_data.clear(); @@ -749,6 +761,8 @@ void CopyupRequest::prepare_copyup_data() { m_copyup_data.append(sbe.bl); } } + + return 0; } } // namespace io diff --git a/src/librbd/io/CopyupRequest.h b/src/librbd/io/CopyupRequest.h index 127fc4a00bf16..a6a20294c7f4b 100644 --- a/src/librbd/io/CopyupRequest.h +++ b/src/librbd/io/CopyupRequest.h @@ -132,7 +132,7 @@ private: void compute_deep_copy_snap_ids(); void convert_copyup_extent_map(); - void prepare_copyup_data(); + int prepare_copyup_data(); }; } // namespace io diff --git a/src/librbd/io/ObjectDispatch.h b/src/librbd/io/ObjectDispatch.h index e66fba134fdc0..dd1f7261dddfc 100644 --- a/src/librbd/io/ObjectDispatch.h +++ b/src/librbd/io/ObjectDispatch.h @@ -96,9 +96,10 @@ public: uint64_t journal_tid, uint64_t new_journal_tid) override { } - void prepare_copyup( + int prepare_copyup( uint64_t object_no, SnapshotSparseBufferlist* snapshot_sparse_bufferlist) override { + return 0; } private: diff --git a/src/librbd/io/ObjectDispatchInterface.h b/src/librbd/io/ObjectDispatchInterface.h index 1cd72dd1b9b14..2e9dd1300cf5f 100644 --- a/src/librbd/io/ObjectDispatchInterface.h +++ b/src/librbd/io/ObjectDispatchInterface.h @@ -90,7 +90,7 @@ struct ObjectDispatchInterface { uint64_t object_no, uint64_t object_off, uint64_t object_len, uint64_t journal_tid, uint64_t new_journal_tid) = 0; - virtual void prepare_copyup( + virtual int prepare_copyup( uint64_t object_no, SnapshotSparseBufferlist* snapshot_sparse_bufferlist) = 0; diff --git a/src/librbd/io/ObjectDispatcher.cc b/src/librbd/io/ObjectDispatcher.cc index 3bc55a57fd642..b66c6bb18c8e7 100644 --- a/src/librbd/io/ObjectDispatcher.cc +++ b/src/librbd/io/ObjectDispatcher.cc @@ -173,7 +173,7 @@ void ObjectDispatcher::extent_overwritten( } template -void ObjectDispatcher::prepare_copyup( +int ObjectDispatcher::prepare_copyup( uint64_t object_no, SnapshotSparseBufferlist* snapshot_sparse_bufferlist) { auto cct = this->m_image_ctx->cct; @@ -183,8 +183,14 @@ void ObjectDispatcher::prepare_copyup( for (auto it : this->m_dispatches) { auto& object_dispatch_meta = it.second; auto object_dispatch = object_dispatch_meta.dispatch; - object_dispatch->prepare_copyup(object_no, snapshot_sparse_bufferlist); + auto r = object_dispatch->prepare_copyup( + object_no, snapshot_sparse_bufferlist); + if (r < 0) { + return r; + } } + + return 0; } template diff --git a/src/librbd/io/ObjectDispatcher.h b/src/librbd/io/ObjectDispatcher.h index 7b356afe6de14..1e5e78d8b7f9c 100644 --- a/src/librbd/io/ObjectDispatcher.h +++ b/src/librbd/io/ObjectDispatcher.h @@ -34,7 +34,7 @@ public: uint64_t object_no, uint64_t object_off, uint64_t object_len, uint64_t journal_tid, uint64_t new_journal_tid) override; - void prepare_copyup( + int prepare_copyup( uint64_t object_no, SnapshotSparseBufferlist* snapshot_sparse_bufferlist) override; diff --git a/src/librbd/io/ObjectDispatcherInterface.h b/src/librbd/io/ObjectDispatcherInterface.h index b9f9197c02a4b..0f3d33330f57f 100644 --- a/src/librbd/io/ObjectDispatcherInterface.h +++ b/src/librbd/io/ObjectDispatcherInterface.h @@ -23,7 +23,7 @@ public: uint64_t object_no, uint64_t object_off, uint64_t object_len, uint64_t journal_tid, uint64_t new_journal_tid) = 0; - virtual void prepare_copyup( + virtual int prepare_copyup( uint64_t object_no, SnapshotSparseBufferlist* snapshot_sparse_bufferlist) = 0; diff --git a/src/librbd/io/SimpleSchedulerObjectDispatch.h b/src/librbd/io/SimpleSchedulerObjectDispatch.h index ea125082d1d33..ca8a57f3a4e28 100644 --- a/src/librbd/io/SimpleSchedulerObjectDispatch.h +++ b/src/librbd/io/SimpleSchedulerObjectDispatch.h @@ -112,9 +112,10 @@ public: uint64_t journal_tid, uint64_t new_journal_tid) override { } - void prepare_copyup( + int prepare_copyup( uint64_t object_no, SnapshotSparseBufferlist* snapshot_sparse_bufferlist) override { + return 0; } private: diff --git a/src/librbd/journal/ObjectDispatch.h b/src/librbd/journal/ObjectDispatch.h index 18967a33aa498..45e4773ccc40f 100644 --- a/src/librbd/journal/ObjectDispatch.h +++ b/src/librbd/journal/ObjectDispatch.h @@ -101,9 +101,10 @@ public: uint64_t object_no, uint64_t object_off, uint64_t object_len, uint64_t journal_tid, uint64_t new_journal_tid) override; - void prepare_copyup( + int prepare_copyup( uint64_t object_no, io::SnapshotSparseBufferlist* snapshot_sparse_bufferlist) override { + return 0; } private: diff --git a/src/test/librbd/crypto/test_mock_CryptoObjectDispatch.cc b/src/test/librbd/crypto/test_mock_CryptoObjectDispatch.cc index 805a83d75bda1..2fb8f9f702409 100644 --- a/src/test/librbd/crypto/test_mock_CryptoObjectDispatch.cc +++ b/src/test/librbd/crypto/test_mock_CryptoObjectDispatch.cc @@ -671,5 +671,62 @@ TEST_F(TestMockCryptoCryptoObjectDispatch, WriteSame) { ASSERT_EQ(0, dispatched_cond.wait()); } +TEST_F(TestMockCryptoCryptoObjectDispatch, PrepareCopyup) { + char* data = (char*)"0123456789"; + io::SnapshotSparseBufferlist snapshot_sparse_bufferlist; + auto& snap1 = snapshot_sparse_bufferlist[0]; + auto& snap2 = snapshot_sparse_bufferlist[1]; + + snap1.insert(0, 1, {io::SPARSE_EXTENT_STATE_DATA, 1, + ceph::bufferlist::static_from_mem(data + 1, 1)}); + snap1.insert(8191, 1, {io::SPARSE_EXTENT_STATE_DATA, 1, + ceph::bufferlist::static_from_mem(data + 2, 1)}); + snap1.insert(8193, 3, {io::SPARSE_EXTENT_STATE_DATA, 3, + ceph::bufferlist::static_from_mem(data + 3, 3)}); + + snap2.insert(0, 2, {io::SPARSE_EXTENT_STATE_ZEROED, 2}); + snap2.insert(8191, 3, {io::SPARSE_EXTENT_STATE_DATA, 3, + ceph::bufferlist::static_from_mem(data + 6, 3)}); + snap2.insert(16384, 1, {io::SPARSE_EXTENT_STATE_DATA, 1, + ceph::bufferlist::static_from_mem(data + 9, 1)}); + + expect_get_object_size(); + expect_encrypt(6); + ASSERT_EQ(0, mock_crypto_object_dispatch->prepare_copyup( + 0, &snapshot_sparse_bufferlist)); + + ASSERT_EQ(2, snapshot_sparse_bufferlist.size()); + + auto& snap1_result = snapshot_sparse_bufferlist[0]; + auto& snap2_result = snapshot_sparse_bufferlist[1]; + + auto it = snap1_result.begin(); + ASSERT_NE(it, snap1_result.end()); + ASSERT_EQ(0, it.get_off()); + ASSERT_EQ(4096 * 3, it.get_len()); + + ASSERT_TRUE(it.get_val().bl.to_str() == + std::string("1") + std::string(4095, '\0') + + std::string(4095, '\0') + std::string("2") + + std::string(1, '\0') + std::string("345") + std::string(4092, '\0')); + ASSERT_EQ(++it, snap1_result.end()); + + it = snap2_result.begin(); + ASSERT_NE(it, snap2_result.end()); + ASSERT_EQ(0, it.get_off()); + ASSERT_EQ(4096 * 3, it.get_len()); + ASSERT_TRUE(it.get_val().bl.to_str() == + std::string(4096, '\0') + + std::string(4095, '\0') + std::string("6") + + std::string("7845") + std::string(4092, '\0')); + + ASSERT_NE(++it, snap2_result.end()); + ASSERT_EQ(16384, it.get_off()); + ASSERT_EQ(4096, it.get_len()); + ASSERT_TRUE(it.get_val().bl.to_str() == + std::string("9") + std::string(4095, '\0')); + ASSERT_EQ(++it, snap2_result.end()); +} + } // namespace io } // namespace librbd diff --git a/src/test/librbd/deep_copy/test_mock_ObjectCopyRequest.cc b/src/test/librbd/deep_copy/test_mock_ObjectCopyRequest.cc index 3860a9aa1c93a..34ed54987859d 100644 --- a/src/test/librbd/deep_copy/test_mock_ObjectCopyRequest.cc +++ b/src/test/librbd/deep_copy/test_mock_ObjectCopyRequest.cc @@ -298,8 +298,9 @@ public: } } - void expect_prepare_copyup(MockTestImageCtx& mock_image_ctx) { - EXPECT_CALL(*mock_image_ctx.io_object_dispatcher, prepare_copyup(_, _)); + void expect_prepare_copyup(MockTestImageCtx& mock_image_ctx, int r = 0) { + EXPECT_CALL(*mock_image_ctx.io_object_dispatcher, + prepare_copyup(_, _)).WillOnce(Return(r)); } int create_snap(librbd::ImageCtx *image_ctx, const char* snap_name, @@ -826,6 +827,44 @@ TEST_F(TestMockDeepCopyObjectCopyRequest, ObjectMapUpdateError) { ASSERT_EQ(-EBLOCKLISTED, ctx.wait()); } +TEST_F(TestMockDeepCopyObjectCopyRequest, PrepareCopyupError) { + // scribble some data + interval_set one; + scribble(m_src_image_ctx, 10, 102400, &one); + + ASSERT_EQ(0, create_snap("copy")); + librbd::MockTestImageCtx mock_src_image_ctx(*m_src_image_ctx); + librbd::MockTestImageCtx mock_dst_image_ctx(*m_dst_image_ctx); + + librbd::MockExclusiveLock mock_exclusive_lock; + prepare_exclusive_lock(mock_dst_image_ctx, mock_exclusive_lock); + + librbd::MockObjectMap mock_object_map; + mock_dst_image_ctx.object_map = &mock_object_map; + + expect_op_work_queue(mock_src_image_ctx); + expect_test_features(mock_dst_image_ctx); + expect_get_object_count(mock_dst_image_ctx); + + C_SaferCond ctx; + MockObjectCopyRequest *request = create_request(mock_src_image_ctx, + mock_dst_image_ctx, 0, 0, + &ctx); + + InSequence seq; + expect_list_snaps(mock_src_image_ctx, 0); + expect_read(mock_src_image_ctx, m_src_snap_ids[0], 0, one.range_end(), 0); + + expect_start_op(mock_exclusive_lock); + expect_update_object_map(mock_dst_image_ctx, mock_object_map, + m_dst_snap_ids[0], OBJECT_EXISTS, 0); + + expect_prepare_copyup(mock_dst_image_ctx, -EIO); + + request->send(); + ASSERT_EQ(-EIO, ctx.wait()); +} + TEST_F(TestMockDeepCopyObjectCopyRequest, WriteSnapsStart) { // scribble some data interval_set one; diff --git a/src/test/librbd/io/test_mock_CopyupRequest.cc b/src/test/librbd/io/test_mock_CopyupRequest.cc index ee7a911c43e2c..c8931d2c8aaa3 100644 --- a/src/test/librbd/io/test_mock_CopyupRequest.cc +++ b/src/test/librbd/io/test_mock_CopyupRequest.cc @@ -338,8 +338,9 @@ struct TestMockIoCopyupRequest : public TestMockFixture { })); } - void expect_prepare_copyup(MockTestImageCtx& mock_image_ctx) { - EXPECT_CALL(*mock_image_ctx.io_object_dispatcher, prepare_copyup(_, _)); + void expect_prepare_copyup(MockTestImageCtx& mock_image_ctx, int r = 0) { + EXPECT_CALL(*mock_image_ctx.io_object_dispatcher, + prepare_copyup(_, _)).WillOnce(Return(r)); } void expect_prepare_copyup(MockTestImageCtx& mock_image_ctx, @@ -354,6 +355,7 @@ struct TestMockIoCopyupRequest : public TestMockFixture { EXPECT_EQ(in_sparse_bl, sparse_bl); sparse_bl = out_sparse_bl; + return 0; }))); } @@ -977,6 +979,40 @@ TEST_F(TestMockIoCopyupRequest, ReadFromParentError) { ASSERT_EQ(-EPERM, mock_write_request.ctx.wait()); } +TEST_F(TestMockIoCopyupRequest, PrepareCopyupError) { + REQUIRE_FEATURE(RBD_FEATURE_LAYERING); + + librbd::ImageCtx *ictx; + ASSERT_EQ(0, open_image(m_image_name, &ictx)); + + MockTestImageCtx mock_parent_image_ctx(*ictx->parent); + MockTestImageCtx mock_image_ctx(*ictx, &mock_parent_image_ctx); + + MockExclusiveLock mock_exclusive_lock; + MockJournal mock_journal; + MockObjectMap mock_object_map; + initialize_features(ictx, mock_image_ctx, mock_exclusive_lock, mock_journal, + mock_object_map); + + expect_op_work_queue(mock_image_ctx); + expect_is_lock_owner(mock_image_ctx); + + InSequence seq; + + std::string data(4096, '1'); + expect_read_parent(mock_parent_image_ctx, {{0, 4096}}, data, 0); + expect_prepare_copyup(mock_image_ctx, -EIO); + + auto req = new MockCopyupRequest(&mock_image_ctx, 0, + {{0, 4096}}, {}); + mock_image_ctx.copyup_list[0] = req; + MockAbstractObjectWriteRequest mock_write_request; + req->append_request(&mock_write_request, {}); + req->send(); + + ASSERT_EQ(-EIO, mock_write_request.ctx.wait()); +} + TEST_F(TestMockIoCopyupRequest, DeepCopyError) { REQUIRE_FEATURE(RBD_FEATURE_LAYERING); diff --git a/src/test/librbd/mock/io/MockObjectDispatch.h b/src/test/librbd/mock/io/MockObjectDispatch.h index 262e76bde337b..baf86d9fb85e1 100644 --- a/src/test/librbd/mock/io/MockObjectDispatch.h +++ b/src/test/librbd/mock/io/MockObjectDispatch.h @@ -128,7 +128,7 @@ public: MOCK_METHOD5(extent_overwritten, void(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t)); - MOCK_METHOD2(prepare_copyup, void(uint64_t, SnapshotSparseBufferlist*)); + MOCK_METHOD2(prepare_copyup, int(uint64_t, SnapshotSparseBufferlist*)); }; } // namespace io diff --git a/src/test/librbd/mock/io/MockObjectDispatcher.h b/src/test/librbd/mock/io/MockObjectDispatcher.h index 0c3fc2c2c4ad8..688744bcbe540 100644 --- a/src/test/librbd/mock/io/MockObjectDispatcher.h +++ b/src/test/librbd/mock/io/MockObjectDispatcher.h @@ -32,7 +32,7 @@ public: MOCK_METHOD5(extent_overwritten, void(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t)); - MOCK_METHOD2(prepare_copyup, void(uint64_t, SnapshotSparseBufferlist*)); + MOCK_METHOD2(prepare_copyup, int(uint64_t, SnapshotSparseBufferlist*)); MOCK_METHOD1(send, void(ObjectDispatchSpec*)); }; -- 2.39.5