diff options
author | Jason Dillaman <dillaman@redhat.com> | 2017-11-09 18:10:30 +0100 |
---|---|---|
committer | Jason Dillaman <dillaman@redhat.com> | 2017-11-16 13:31:59 +0100 |
commit | 0e643fb926f0484bb4f860740c7f85b692de6737 (patch) | |
tree | ec53359c3f8e05b1edef48d0731836650ac29a71 /src/test/librbd | |
parent | librbd: consolidate all object discard-related logic into single state machine (diff) | |
download | ceph-0e643fb926f0484bb4f860740c7f85b692de6737.tar.xz ceph-0e643fb926f0484bb4f860740c7f85b692de6737.zip |
librbd: refactor object write request state machines
Fixes: http://tracker.ceph.com/issues/20789
Signed-off-by: Jason Dillaman <dillaman@redhat.com>
Diffstat (limited to 'src/test/librbd')
-rw-r--r-- | src/test/librbd/io/test_mock_ImageRequest.cc | 2 | ||||
-rw-r--r-- | src/test/librbd/io/test_mock_ObjectRequest.cc | 888 | ||||
-rw-r--r-- | src/test/librbd/mock/MockImageCtx.h | 5 | ||||
-rw-r--r-- | src/test/librbd/operation/test_mock_TrimRequest.cc | 2 |
4 files changed, 865 insertions, 32 deletions
diff --git a/src/test/librbd/io/test_mock_ImageRequest.cc b/src/test/librbd/io/test_mock_ImageRequest.cc index bd1ff679530..e85ae259cd0 100644 --- a/src/test/librbd/io/test_mock_ImageRequest.cc +++ b/src/test/librbd/io/test_mock_ImageRequest.cc @@ -102,8 +102,8 @@ struct ObjectRequest<librbd::MockTestImageCtx> : public ObjectRequestHandle { s_instance = nullptr; } - MOCK_METHOD1(complete, void(int)); MOCK_METHOD0(send, void()); + MOCK_METHOD1(fail, void(int)); }; template <> diff --git a/src/test/librbd/io/test_mock_ObjectRequest.cc b/src/test/librbd/io/test_mock_ObjectRequest.cc index 7e6eb15d1a8..6f0425029ec 100644 --- a/src/test/librbd/io/test_mock_ObjectRequest.cc +++ b/src/test/librbd/io/test_mock_ObjectRequest.cc @@ -35,23 +35,27 @@ namespace io { template <> struct CopyupRequest<librbd::MockImageCtx> { + MOCK_METHOD0(send, void()); + MOCK_METHOD1(append_request, void(AbstractObjectWriteRequest<librbd::MockTestImageCtx>*)); +}; + +template <> +struct CopyupRequest<librbd::MockTestImageCtx> : public CopyupRequest<librbd::MockImageCtx> { static CopyupRequest* s_instance; - static CopyupRequest* create(librbd::MockImageCtx *ictx, + static CopyupRequest* create(librbd::MockTestImageCtx *ictx, const std::string &oid, uint64_t objectno, Extents &&image_extents, const ZTracer::Trace &parent_trace) { return s_instance; } - MOCK_METHOD0(send, void()); - CopyupRequest() { s_instance = this; } }; template <> -struct ImageRequest<librbd::MockImageCtx> { +struct ImageRequest<librbd::MockTestImageCtx> { static ImageRequest *s_instance; static void aio_read(librbd::MockImageCtx *ictx, AioCompletion *c, Extents &&image_extents, ReadResult &&read_result, @@ -66,8 +70,8 @@ struct ImageRequest<librbd::MockImageCtx> { } }; -CopyupRequest<librbd::MockImageCtx>* CopyupRequest<librbd::MockImageCtx>::s_instance = nullptr; -ImageRequest<librbd::MockImageCtx>* ImageRequest<librbd::MockImageCtx>::s_instance = nullptr; +CopyupRequest<librbd::MockTestImageCtx>* CopyupRequest<librbd::MockTestImageCtx>::s_instance = nullptr; +ImageRequest<librbd::MockTestImageCtx>* ImageRequest<librbd::MockTestImageCtx>::s_instance = nullptr; } // namespace io } // namespace librbd @@ -86,10 +90,15 @@ using ::testing::WithArg; using ::testing::WithArgs; struct TestMockIoObjectRequest : public TestMockFixture { - typedef ObjectRequest<librbd::MockImageCtx> MockObjectRequest; - typedef ObjectReadRequest<librbd::MockImageCtx> MockObjectReadRequest; - typedef CopyupRequest<librbd::MockImageCtx> MockCopyupRequest; - typedef ImageRequest<librbd::MockImageCtx> MockImageRequest; + typedef ObjectRequest<librbd::MockTestImageCtx> MockObjectRequest; + typedef ObjectReadRequest<librbd::MockTestImageCtx> MockObjectReadRequest; + typedef ObjectWriteRequest<librbd::MockTestImageCtx> MockObjectWriteRequest; + typedef ObjectDiscardRequest<librbd::MockTestImageCtx> MockObjectDiscardRequest; + typedef ObjectWriteSameRequest<librbd::MockTestImageCtx> MockObjectWriteSameRequest; + typedef ObjectCompareAndWriteRequest<librbd::MockTestImageCtx> MockObjectCompareAndWriteRequest; + typedef AbstractObjectWriteRequest<librbd::MockTestImageCtx> MockAbstractObjectWriteRequest; + typedef CopyupRequest<librbd::MockTestImageCtx> MockCopyupRequest; + typedef ImageRequest<librbd::MockTestImageCtx> MockImageRequest; void expect_object_may_exist(MockTestImageCtx &mock_image_ctx, uint64_t object_no, bool exists) { @@ -99,6 +108,11 @@ struct TestMockIoObjectRequest : public TestMockFixture { } } + void expect_get_object_size(MockTestImageCtx &mock_image_ctx) { + EXPECT_CALL(mock_image_ctx, get_object_size()).WillRepeatedly(Return( + mock_image_ctx.layout.object_size)); + } + void expect_get_parent_overlap(MockTestImageCtx &mock_image_ctx, librados::snap_t snap_id, uint64_t overlap, int r) { @@ -125,6 +139,11 @@ struct TestMockIoObjectRequest : public TestMockFixture { .WillOnce(Return(flags)); } + void expect_is_lock_owner(MockExclusiveLock& mock_exclusive_lock) { + EXPECT_CALL(mock_exclusive_lock, is_lock_owner()).WillRepeatedly( + Return(true)); + } + void expect_read(MockTestImageCtx &mock_image_ctx, const std::string& oid, uint64_t off, uint64_t len, const std::string& data, int r) { @@ -192,6 +211,114 @@ struct TestMockIoObjectRequest : public TestMockFixture { .WillOnce(Invoke([&mock_copyup_request, r]() { })); } + + void expect_copyup(MockCopyupRequest& mock_copyup_request, + MockAbstractObjectWriteRequest** write_request, int r) { + EXPECT_CALL(mock_copyup_request, append_request(_)) + .WillOnce(Invoke([write_request](MockAbstractObjectWriteRequest *req) { + *write_request = req; + })); + EXPECT_CALL(mock_copyup_request, send()) + .WillOnce(Invoke([write_request, r]() { + (*write_request)->handle_copyup(r); + })); + } + + void expect_object_map_update(MockTestImageCtx &mock_image_ctx, + uint64_t start_object, uint64_t end_object, + uint8_t state, + const boost::optional<uint8_t> ¤t_state, + bool updated, int ret_val) { + if (mock_image_ctx.object_map != nullptr) { + EXPECT_CALL(*mock_image_ctx.object_map, + aio_update(CEPH_NOSNAP, start_object, end_object, state, + current_state, _, _)) + .WillOnce(WithArg<6>(Invoke([&mock_image_ctx, updated, ret_val](Context *ctx) { + if (updated) { + mock_image_ctx.op_work_queue->queue(ctx, ret_val); + } + return updated; + }))); + } + } + + void expect_assert_exists(MockTestImageCtx &mock_image_ctx, int r) { + EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.data_ctx), assert_exists(_)) + .WillOnce(Return(r)); + } + + void expect_write(MockTestImageCtx &mock_image_ctx, + uint64_t offset, uint64_t length, int r) { + auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.data_ctx), + write(_, _, length, offset, _)); + if (r < 0) { + expect.WillOnce(Return(r)); + } else { + expect.WillOnce(DoDefault()); + } + } + + void expect_write_full(MockTestImageCtx &mock_image_ctx, int r) { + auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.data_ctx), + write_full(_, _, _)); + if (r < 0) { + expect.WillOnce(Return(r)); + } else { + expect.WillOnce(DoDefault()); + } + } + + void expect_writesame(MockTestImageCtx &mock_image_ctx, + uint64_t offset, uint64_t length, int r) { + auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.data_ctx), + writesame(_, _, length, offset, _)); + if (r < 0) { + expect.WillOnce(Return(r)); + } else { + expect.WillOnce(DoDefault()); + } + } + + void expect_remove(MockTestImageCtx &mock_image_ctx, int r) { + auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.data_ctx), + remove(_, _)); + if (r < 0) { + expect.WillOnce(Return(r)); + } else { + expect.WillOnce(DoDefault()); + } + } + + void expect_truncate(MockTestImageCtx &mock_image_ctx, int offset, int r) { + auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.data_ctx), + truncate(_, offset, _)); + if (r < 0) { + expect.WillOnce(Return(r)); + } else { + expect.WillOnce(DoDefault()); + } + } + + void expect_zero(MockTestImageCtx &mock_image_ctx, int offset, int length, + int r) { + auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.data_ctx), + zero(_, offset, length, _)); + if (r < 0) { + expect.WillOnce(Return(r)); + } else { + expect.WillOnce(DoDefault()); + } + } + + void expect_cmpext(MockTestImageCtx &mock_image_ctx, int offset, int r) { + auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.data_ctx), + cmpext(_, offset, _)); + if (r < 0) { + expect.WillOnce(Return(r)); + } else { + expect.WillOnce(DoDefault()); + } + } }; TEST_F(TestMockIoObjectRequest, Read) { @@ -210,11 +337,13 @@ TEST_F(TestMockIoObjectRequest, Read) { InSequence seq; expect_object_may_exist(mock_image_ctx, 0, true); expect_get_read_flags(mock_image_ctx, CEPH_NOSNAP, 0); - expect_read(mock_image_ctx, "object0", 0, 4096, std::string(4096, '1'), 0); + expect_read(mock_image_ctx, ictx->get_object_name(0), 0, 4096, + std::string(4096, '1'), 0); C_SaferCond ctx; auto req = MockObjectReadRequest::create( - &mock_image_ctx, "object0", 0, 0, 4096, CEPH_NOSNAP, 0, false, {}, &ctx); + &mock_image_ctx, ictx->get_object_name(0), 0, 0, 4096, CEPH_NOSNAP, 0, + false, {}, &ctx); req->send(); ASSERT_EQ(0, ctx.wait()); } @@ -235,14 +364,14 @@ TEST_F(TestMockIoObjectRequest, SparseReadThreshold) { InSequence seq; expect_object_may_exist(mock_image_ctx, 0, true); expect_get_read_flags(mock_image_ctx, CEPH_NOSNAP, 0); - expect_sparse_read(mock_image_ctx, "object0", 0, + expect_sparse_read(mock_image_ctx, ictx->get_object_name(0), 0, ictx->sparse_read_threshold_bytes, std::string(ictx->sparse_read_threshold_bytes, '1'), 0); C_SaferCond ctx; auto req = MockObjectReadRequest::create( - &mock_image_ctx, "object0", 0, 0, ictx->sparse_read_threshold_bytes, - CEPH_NOSNAP, 0, false, {}, &ctx); + &mock_image_ctx, ictx->get_object_name(0), 0, 0, + ictx->sparse_read_threshold_bytes, CEPH_NOSNAP, 0, false, {}, &ctx); req->send(); ASSERT_EQ(0, ctx.wait()); } @@ -263,11 +392,12 @@ TEST_F(TestMockIoObjectRequest, ReadError) { InSequence seq; expect_object_may_exist(mock_image_ctx, 0, true); expect_get_read_flags(mock_image_ctx, CEPH_NOSNAP, 0); - expect_read(mock_image_ctx, "object0", 0, 4096, "", -EPERM); + expect_read(mock_image_ctx, ictx->get_object_name(0), 0, 4096, "", -EPERM); C_SaferCond ctx; auto req = MockObjectReadRequest::create( - &mock_image_ctx, "object0", 0, 0, 4096, CEPH_NOSNAP, 0, false, {}, &ctx); + &mock_image_ctx, ictx->get_object_name(0), 0, 0, 4096, CEPH_NOSNAP, 0, + false, {}, &ctx); req->send(); ASSERT_EQ(-EPERM, ctx.wait()); } @@ -286,12 +416,13 @@ TEST_F(TestMockIoObjectRequest, CacheRead) { expect_op_work_queue(mock_image_ctx); InSequence seq; - expect_cache_read(mock_image_ctx, "object0", 0, 0, 4096, + expect_cache_read(mock_image_ctx, ictx->get_object_name(0), 0, 0, 4096, std::string(4096, '1'), 0); C_SaferCond ctx; auto req = MockObjectReadRequest::create( - &mock_image_ctx, "object0", 0, 0, 4096, CEPH_NOSNAP, 0, false, {}, &ctx); + &mock_image_ctx, ictx->get_object_name(0), 0, 0, 4096, CEPH_NOSNAP, 0, + false, {}, &ctx); req->send(); ASSERT_EQ(0, ctx.wait()); } @@ -310,12 +441,13 @@ TEST_F(TestMockIoObjectRequest, CacheReadError) { expect_op_work_queue(mock_image_ctx); InSequence seq; - expect_cache_read(mock_image_ctx, "object0", 0, 0, 4096, + expect_cache_read(mock_image_ctx, ictx->get_object_name(0), 0, 0, 4096, "", -EPERM); C_SaferCond ctx; auto req = MockObjectReadRequest::create( - &mock_image_ctx, "object0", 0, 0, 4096, CEPH_NOSNAP, 0, false, {}, &ctx); + &mock_image_ctx, ictx->get_object_name(0), 0, 0, 4096, CEPH_NOSNAP, 0, + false, {}, &ctx); req->send(); ASSERT_EQ(-EPERM, ctx.wait()); } @@ -352,7 +484,7 @@ TEST_F(TestMockIoObjectRequest, ParentRead) { InSequence seq; expect_object_may_exist(mock_image_ctx, 0, true); expect_get_read_flags(mock_image_ctx, CEPH_NOSNAP, 0); - expect_read(mock_image_ctx, "object0", 0, 4096, "", -ENOENT); + expect_read(mock_image_ctx, ictx->get_object_name(0), 0, 4096, "", -ENOENT); MockImageRequest mock_image_request; expect_get_parent_overlap(mock_image_ctx, CEPH_NOSNAP, 4096, 0); @@ -361,7 +493,8 @@ TEST_F(TestMockIoObjectRequest, ParentRead) { C_SaferCond ctx; auto req = MockObjectReadRequest::create( - &mock_image_ctx, "object0", 0, 0, 4096, CEPH_NOSNAP, 0, false, {}, &ctx); + &mock_image_ctx, ictx->get_object_name(0), 0, 0, 4096, CEPH_NOSNAP, 0, + false, {}, &ctx); req->send(); ASSERT_EQ(0, ctx.wait()); } @@ -398,7 +531,7 @@ TEST_F(TestMockIoObjectRequest, ParentReadError) { InSequence seq; expect_object_may_exist(mock_image_ctx, 0, true); expect_get_read_flags(mock_image_ctx, CEPH_NOSNAP, 0); - expect_read(mock_image_ctx, "object0", 0, 4096, "", -ENOENT); + expect_read(mock_image_ctx, ictx->get_object_name(0), 0, 4096, "", -ENOENT); MockImageRequest mock_image_request; expect_get_parent_overlap(mock_image_ctx, CEPH_NOSNAP, 4096, 0); @@ -407,7 +540,8 @@ TEST_F(TestMockIoObjectRequest, ParentReadError) { C_SaferCond ctx; auto req = MockObjectReadRequest::create( - &mock_image_ctx, "object0", 0, 0, 4096, CEPH_NOSNAP, 0, false, {}, &ctx); + &mock_image_ctx, ictx->get_object_name(0), 0, 0, 4096, CEPH_NOSNAP, 0, + false, {}, &ctx); req->send(); ASSERT_EQ(-EPERM, ctx.wait()); } @@ -443,11 +577,12 @@ TEST_F(TestMockIoObjectRequest, CacheInitiated) { InSequence seq; expect_object_may_exist(mock_image_ctx, 0, true); expect_get_read_flags(mock_image_ctx, CEPH_NOSNAP, 0); - expect_read(mock_image_ctx, "object0", 0, 4096, "", -ENOENT); + expect_read(mock_image_ctx, ictx->get_object_name(0), 0, 4096, "", -ENOENT); C_SaferCond ctx; auto req = MockObjectReadRequest::create( - &mock_image_ctx, "object0", 0, 0, 4096, CEPH_NOSNAP, 0, true, {}, &ctx); + &mock_image_ctx, ictx->get_object_name(0), 0, 0, 4096, CEPH_NOSNAP, 0, true, + {}, &ctx); req->send(); ASSERT_EQ(-ENOENT, ctx.wait()); } @@ -484,7 +619,7 @@ TEST_F(TestMockIoObjectRequest, CopyOnRead) { InSequence seq; expect_object_may_exist(mock_image_ctx, 0, true); expect_get_read_flags(mock_image_ctx, CEPH_NOSNAP, 0); - expect_read(mock_image_ctx, "object0", 0, 4096, "", -ENOENT); + expect_read(mock_image_ctx, ictx->get_object_name(0), 0, 4096, "", -ENOENT); MockImageRequest mock_image_request; expect_get_parent_overlap(mock_image_ctx, CEPH_NOSNAP, 4096, 0); @@ -498,10 +633,705 @@ TEST_F(TestMockIoObjectRequest, CopyOnRead) { C_SaferCond ctx; auto req = MockObjectReadRequest::create( - &mock_image_ctx, "object0", 0, 0, 4096, CEPH_NOSNAP, 0, false, {}, &ctx); + &mock_image_ctx, ictx->get_object_name(0), 0, 0, 4096, CEPH_NOSNAP, 0, + false, {}, &ctx); + req->send(); + ASSERT_EQ(0, ctx.wait()); +} + +TEST_F(TestMockIoObjectRequest, Write) { + librbd::ImageCtx *ictx; + ASSERT_EQ(0, open_image(m_image_name, &ictx)); + + MockTestImageCtx mock_image_ctx(*ictx); + expect_get_object_size(mock_image_ctx); + + MockExclusiveLock mock_exclusive_lock; + if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) { + mock_image_ctx.exclusive_lock = &mock_exclusive_lock; + expect_is_lock_owner(mock_exclusive_lock); + } + + MockObjectMap mock_object_map; + if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) { + mock_image_ctx.object_map = &mock_object_map; + } + + bufferlist bl; + bl.append(std::string(4096, '1')); + + InSequence seq; + expect_get_parent_overlap(mock_image_ctx, CEPH_NOSNAP, 0, 0); + expect_object_may_exist(mock_image_ctx, 0, true); + expect_object_map_update(mock_image_ctx, 0, 1, OBJECT_EXISTS, {}, false, 0); + expect_write(mock_image_ctx, 0, 4096, 0); + + C_SaferCond ctx; + auto req = MockObjectWriteRequest::create_write( + &mock_image_ctx, ictx->get_object_name(0), 0, 0, bl, mock_image_ctx.snapc, + 0, {}, &ctx); + req->send(); + ASSERT_EQ(0, ctx.wait()); +} + +TEST_F(TestMockIoObjectRequest, WriteFull) { + librbd::ImageCtx *ictx; + ASSERT_EQ(0, open_image(m_image_name, &ictx)); + + MockTestImageCtx mock_image_ctx(*ictx); + expect_get_object_size(mock_image_ctx); + + MockExclusiveLock mock_exclusive_lock; + if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) { + mock_image_ctx.exclusive_lock = &mock_exclusive_lock; + expect_is_lock_owner(mock_exclusive_lock); + } + + MockObjectMap mock_object_map; + if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) { + mock_image_ctx.object_map = &mock_object_map; + } + + bufferlist bl; + bl.append(std::string(ictx->get_object_size(), '1')); + + InSequence seq; + expect_get_parent_overlap(mock_image_ctx, CEPH_NOSNAP, 0, 0); + expect_object_may_exist(mock_image_ctx, 0, true); + expect_object_map_update(mock_image_ctx, 0, 1, OBJECT_EXISTS, {}, false, 0); + expect_write_full(mock_image_ctx, 0); + + C_SaferCond ctx; + auto req = MockObjectWriteRequest::create_write( + &mock_image_ctx, ictx->get_object_name(0), 0, 0, bl, mock_image_ctx.snapc, + 0, {}, &ctx); + req->send(); + ASSERT_EQ(0, ctx.wait()); +} + +TEST_F(TestMockIoObjectRequest, WriteObjectMap) { + REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP); + + librbd::ImageCtx *ictx; + ASSERT_EQ(0, open_image(m_image_name, &ictx)); + + MockTestImageCtx mock_image_ctx(*ictx); + expect_op_work_queue(mock_image_ctx); + expect_get_object_size(mock_image_ctx); + + MockExclusiveLock mock_exclusive_lock; + mock_image_ctx.exclusive_lock = &mock_exclusive_lock; + expect_is_lock_owner(mock_exclusive_lock); + + MockObjectMap mock_object_map; + mock_image_ctx.object_map = &mock_object_map; + + bufferlist bl; + bl.append(std::string(4096, '1')); + + InSequence seq; + expect_get_parent_overlap(mock_image_ctx, CEPH_NOSNAP, 0, 0); + expect_object_may_exist(mock_image_ctx, 0, true); + expect_object_map_update(mock_image_ctx, 0, 1, OBJECT_EXISTS, {}, true, 0); + expect_write(mock_image_ctx, 0, 4096, 0); + + C_SaferCond ctx; + auto req = MockObjectWriteRequest::create_write( + &mock_image_ctx, ictx->get_object_name(0), 0, 0, bl, mock_image_ctx.snapc, + 0, {}, &ctx); + req->send(); + ASSERT_EQ(0, ctx.wait()); +} + +TEST_F(TestMockIoObjectRequest, WriteError) { + librbd::ImageCtx *ictx; + ASSERT_EQ(0, open_image(m_image_name, &ictx)); + + MockTestImageCtx mock_image_ctx(*ictx); + expect_get_object_size(mock_image_ctx); + + bufferlist bl; + bl.append(std::string(4096, '1')); + + InSequence seq; + expect_get_parent_overlap(mock_image_ctx, CEPH_NOSNAP, 0, 0); + expect_write(mock_image_ctx, 0, 4096, -EPERM); + + C_SaferCond ctx; + auto req = MockObjectWriteRequest::create_write( + &mock_image_ctx, ictx->get_object_name(0), 0, 0, bl, mock_image_ctx.snapc, + 0, {}, &ctx); + req->send(); + ASSERT_EQ(-EPERM, ctx.wait()); +} + +TEST_F(TestMockIoObjectRequest, Copyup) { + REQUIRE_FEATURE(RBD_FEATURE_LAYERING); + + librbd::Image image; + librbd::RBD rbd; + ASSERT_EQ(0, rbd.open(m_ioctx, image, m_image_name.c_str(), NULL)); + ASSERT_EQ(0, image.snap_create("one")); + ASSERT_EQ(0, image.snap_protect("one")); + image.close(); + + std::string clone_name = get_temp_image_name(); + int order = 0; + ASSERT_EQ(0, rbd.clone(m_ioctx, m_image_name.c_str(), "one", m_ioctx, + clone_name.c_str(), RBD_FEATURE_LAYERING, &order)); + + librbd::ImageCtx *ictx; + ASSERT_EQ(0, open_image(clone_name, &ictx)); + + MockTestImageCtx mock_image_ctx(*ictx); + expect_get_object_size(mock_image_ctx); + + MockExclusiveLock mock_exclusive_lock; + if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) { + mock_image_ctx.exclusive_lock = &mock_exclusive_lock; + expect_is_lock_owner(mock_exclusive_lock); + } + + MockObjectMap mock_object_map; + if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) { + mock_image_ctx.object_map = &mock_object_map; + } + + bufferlist bl; + bl.append(std::string(4096, '1')); + + InSequence seq; + expect_get_parent_overlap(mock_image_ctx, CEPH_NOSNAP, 4096, 0); + expect_prune_parent_extents(mock_image_ctx, {{0, 4096}}, 4096, 4096); + expect_object_may_exist(mock_image_ctx, 0, true); + expect_object_map_update(mock_image_ctx, 0, 1, OBJECT_EXISTS, {}, false, 0); + expect_assert_exists(mock_image_ctx, -ENOENT); + + MockAbstractObjectWriteRequest *write_request = nullptr; + MockCopyupRequest mock_copyup_request; + expect_copyup(mock_copyup_request, &write_request, 0); + + C_SaferCond ctx; + auto req = MockObjectWriteRequest::create_write( + &mock_image_ctx, ictx->get_object_name(0), 0, 0, bl, mock_image_ctx.snapc, + 0, {}, &ctx); + req->send(); + ASSERT_EQ(0, ctx.wait()); +} + +TEST_F(TestMockIoObjectRequest, CopyupOptimization) { + REQUIRE_FEATURE(RBD_FEATURE_LAYERING | RBD_FEATURE_OBJECT_MAP); + + librbd::Image image; + librbd::RBD rbd; + ASSERT_EQ(0, rbd.open(m_ioctx, image, m_image_name.c_str(), NULL)); + ASSERT_EQ(0, image.snap_create("one")); + ASSERT_EQ(0, image.snap_protect("one")); + image.close(); + + std::string clone_name = get_temp_image_name(); + int order = 0; + ASSERT_EQ(0, rbd.clone(m_ioctx, m_image_name.c_str(), "one", m_ioctx, + clone_name.c_str(), RBD_FEATURE_LAYERING, &order)); + + librbd::ImageCtx *ictx; + ASSERT_EQ(0, open_image(clone_name, &ictx)); + + MockTestImageCtx mock_image_ctx(*ictx); + expect_get_object_size(mock_image_ctx); + + MockExclusiveLock mock_exclusive_lock; + mock_image_ctx.exclusive_lock = &mock_exclusive_lock; + expect_is_lock_owner(mock_exclusive_lock); + + MockObjectMap mock_object_map; + mock_image_ctx.object_map = &mock_object_map; + + bufferlist bl; + bl.append(std::string(4096, '1')); + + InSequence seq; + expect_get_parent_overlap(mock_image_ctx, CEPH_NOSNAP, 4096, 0); + expect_prune_parent_extents(mock_image_ctx, {{0, 4096}}, 4096, 4096); + expect_object_may_exist(mock_image_ctx, 0, false); + + MockAbstractObjectWriteRequest *write_request = nullptr; + MockCopyupRequest mock_copyup_request; + expect_copyup(mock_copyup_request, &write_request, 0); + + C_SaferCond ctx; + auto req = MockObjectWriteRequest::create_write( + &mock_image_ctx, ictx->get_object_name(0), 0, 0, bl, mock_image_ctx.snapc, + 0, {}, &ctx); + req->send(); + ASSERT_EQ(0, ctx.wait()); +} + +TEST_F(TestMockIoObjectRequest, CopyupError) { + REQUIRE_FEATURE(RBD_FEATURE_LAYERING); + + librbd::Image image; + librbd::RBD rbd; + ASSERT_EQ(0, rbd.open(m_ioctx, image, m_image_name.c_str(), NULL)); + ASSERT_EQ(0, image.snap_create("one")); + ASSERT_EQ(0, image.snap_protect("one")); + image.close(); + + std::string clone_name = get_temp_image_name(); + int order = 0; + ASSERT_EQ(0, rbd.clone(m_ioctx, m_image_name.c_str(), "one", m_ioctx, + clone_name.c_str(), RBD_FEATURE_LAYERING, &order)); + + librbd::ImageCtx *ictx; + ASSERT_EQ(0, open_image(clone_name, &ictx)); + + MockTestImageCtx mock_image_ctx(*ictx); + expect_get_object_size(mock_image_ctx); + + bufferlist bl; + bl.append(std::string(4096, '1')); + + InSequence seq; + expect_get_parent_overlap(mock_image_ctx, CEPH_NOSNAP, 4096, 0); + expect_prune_parent_extents(mock_image_ctx, {{0, 4096}}, 4096, 4096); + expect_assert_exists(mock_image_ctx, -ENOENT); + + MockAbstractObjectWriteRequest *write_request = nullptr; + MockCopyupRequest mock_copyup_request; + expect_copyup(mock_copyup_request, &write_request, -EPERM); + + C_SaferCond ctx; + auto req = MockObjectWriteRequest::create_write( + &mock_image_ctx, ictx->get_object_name(0), 0, 0, bl, mock_image_ctx.snapc, + 0, {}, &ctx); + req->send(); + ASSERT_EQ(-EPERM, ctx.wait()); +} + +TEST_F(TestMockIoObjectRequest, DiscardRemove) { + librbd::ImageCtx *ictx; + ASSERT_EQ(0, open_image(m_image_name, &ictx)); + + MockTestImageCtx mock_image_ctx(*ictx); + expect_get_object_size(mock_image_ctx); + + MockExclusiveLock mock_exclusive_lock; + if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) { + mock_image_ctx.exclusive_lock = &mock_exclusive_lock; + expect_is_lock_owner(mock_exclusive_lock); + } + + MockObjectMap mock_object_map; + if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) { + mock_image_ctx.object_map = &mock_object_map; + } + + InSequence seq; + expect_get_parent_overlap(mock_image_ctx, CEPH_NOSNAP, 0, 0); + expect_object_may_exist(mock_image_ctx, 0, true); + expect_object_map_update(mock_image_ctx, 0, 1, OBJECT_PENDING, {}, false, 0); + expect_remove(mock_image_ctx, 0); + expect_object_map_update(mock_image_ctx, 0, 1, OBJECT_NONEXISTENT, + OBJECT_PENDING, false, 0); + + C_SaferCond ctx; + auto req = MockObjectDiscardRequest::create_discard( + &mock_image_ctx, ictx->get_object_name(0), 0, 0, + mock_image_ctx.get_object_size(), mock_image_ctx.snapc, false, true, {}, + &ctx); req->send(); ASSERT_EQ(0, ctx.wait()); } +TEST_F(TestMockIoObjectRequest, DiscardRemoveTruncate) { + REQUIRE_FEATURE(RBD_FEATURE_LAYERING); + + librbd::Image image; + librbd::RBD rbd; + ASSERT_EQ(0, rbd.open(m_ioctx, image, m_image_name.c_str(), NULL)); + ASSERT_EQ(0, image.snap_create("one")); + ASSERT_EQ(0, image.snap_protect("one")); + image.close(); + + std::string clone_name = get_temp_image_name(); + int order = 0; + ASSERT_EQ(0, rbd.clone(m_ioctx, m_image_name.c_str(), "one", m_ioctx, + clone_name.c_str(), RBD_FEATURE_LAYERING, &order)); + + librbd::ImageCtx *ictx; + ASSERT_EQ(0, open_image(clone_name, &ictx)); + + MockTestImageCtx mock_image_ctx(*ictx); + expect_get_object_size(mock_image_ctx); + + MockExclusiveLock mock_exclusive_lock; + if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) { + mock_image_ctx.exclusive_lock = &mock_exclusive_lock; + expect_is_lock_owner(mock_exclusive_lock); + } + + MockObjectMap mock_object_map; + if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) { + mock_image_ctx.object_map = &mock_object_map; + } + + InSequence seq; + expect_get_parent_overlap(mock_image_ctx, CEPH_NOSNAP, 4096, 0); + expect_prune_parent_extents(mock_image_ctx, {{0, 4096}}, 4096, 4096); + expect_object_may_exist(mock_image_ctx, 0, true); + expect_truncate(mock_image_ctx, 0, 0); + + C_SaferCond ctx; + auto req = MockObjectDiscardRequest::create_discard( + &mock_image_ctx, ictx->get_object_name(0), 0, 0, + mock_image_ctx.get_object_size(), mock_image_ctx.snapc, true, true, {}, + &ctx); + req->send(); + ASSERT_EQ(0, ctx.wait()); +} + +TEST_F(TestMockIoObjectRequest, DiscardTruncate) { + librbd::ImageCtx *ictx; + ASSERT_EQ(0, open_image(m_image_name, &ictx)); + + MockTestImageCtx mock_image_ctx(*ictx); + expect_get_object_size(mock_image_ctx); + + MockExclusiveLock mock_exclusive_lock; + if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) { + mock_image_ctx.exclusive_lock = &mock_exclusive_lock; + expect_is_lock_owner(mock_exclusive_lock); + } + + MockObjectMap mock_object_map; + if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) { + mock_image_ctx.object_map = &mock_object_map; + } + + InSequence seq; + expect_get_parent_overlap(mock_image_ctx, CEPH_NOSNAP, 0, 0); + expect_object_may_exist(mock_image_ctx, 0, true); + expect_object_map_update(mock_image_ctx, 0, 1, OBJECT_EXISTS, {}, false, 0); + expect_truncate(mock_image_ctx, 1, 0); + + C_SaferCond ctx; + auto req = MockObjectDiscardRequest::create_discard( + &mock_image_ctx, ictx->get_object_name(0), 0, 1, + mock_image_ctx.get_object_size() - 1, mock_image_ctx.snapc, false, true, {}, + &ctx); + req->send(); + ASSERT_EQ(0, ctx.wait()); +} + +TEST_F(TestMockIoObjectRequest, DiscardZero) { + librbd::ImageCtx *ictx; + ASSERT_EQ(0, open_image(m_image_name, &ictx)); + + MockTestImageCtx mock_image_ctx(*ictx); + expect_get_object_size(mock_image_ctx); + + MockExclusiveLock mock_exclusive_lock; + if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) { + mock_image_ctx.exclusive_lock = &mock_exclusive_lock; + expect_is_lock_owner(mock_exclusive_lock); + } + + MockObjectMap mock_object_map; + if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) { + mock_image_ctx.object_map = &mock_object_map; + } + + InSequence seq; + expect_get_parent_overlap(mock_image_ctx, CEPH_NOSNAP, 0, 0); + expect_object_may_exist(mock_image_ctx, 0, true); + expect_object_map_update(mock_image_ctx, 0, 1, OBJECT_EXISTS, {}, false, 0); + expect_zero(mock_image_ctx, 1, 1, 0); + + C_SaferCond ctx; + auto req = MockObjectDiscardRequest::create_discard( + &mock_image_ctx, ictx->get_object_name(0), 0, 1, 1, mock_image_ctx.snapc, + false, true, {}, &ctx); + req->send(); + ASSERT_EQ(0, ctx.wait()); +} + +TEST_F(TestMockIoObjectRequest, DiscardDisableObjectMapUpdate) { + REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP); + + librbd::ImageCtx *ictx; + ASSERT_EQ(0, open_image(m_image_name, &ictx)); + + MockTestImageCtx mock_image_ctx(*ictx); + expect_get_object_size(mock_image_ctx); + + MockExclusiveLock mock_exclusive_lock; + mock_image_ctx.exclusive_lock = &mock_exclusive_lock; + expect_is_lock_owner(mock_exclusive_lock); + + MockObjectMap mock_object_map; + mock_image_ctx.object_map = &mock_object_map; + + InSequence seq; + expect_get_parent_overlap(mock_image_ctx, CEPH_NOSNAP, 0, 0); + expect_object_may_exist(mock_image_ctx, 0, true); + expect_remove(mock_image_ctx, 0); + + C_SaferCond ctx; + auto req = MockObjectDiscardRequest::create_discard( + &mock_image_ctx, ictx->get_object_name(0), 0, 0, + mock_image_ctx.get_object_size(), mock_image_ctx.snapc, true, false, {}, + &ctx); + req->send(); + ASSERT_EQ(0, ctx.wait()); +} + +TEST_F(TestMockIoObjectRequest, DiscardNoOp) { + REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP); + + librbd::ImageCtx *ictx; + ASSERT_EQ(0, open_image(m_image_name, &ictx)); + + MockTestImageCtx mock_image_ctx(*ictx); + expect_op_work_queue(mock_image_ctx); + expect_get_object_size(mock_image_ctx); + + MockExclusiveLock mock_exclusive_lock; + mock_image_ctx.exclusive_lock = &mock_exclusive_lock; + expect_is_lock_owner(mock_exclusive_lock); + + MockObjectMap mock_object_map; + mock_image_ctx.object_map = &mock_object_map; + + InSequence seq; + expect_get_parent_overlap(mock_image_ctx, CEPH_NOSNAP, 0, 0); + expect_object_may_exist(mock_image_ctx, 0, false); + + C_SaferCond ctx; + auto req = MockObjectDiscardRequest::create_discard( + &mock_image_ctx, ictx->get_object_name(0), 0, 0, + mock_image_ctx.get_object_size(), mock_image_ctx.snapc, true, false, {}, + &ctx); + req->send(); + ASSERT_EQ(0, ctx.wait()); +} + +TEST_F(TestMockIoObjectRequest, WriteSame) { + librbd::ImageCtx *ictx; + ASSERT_EQ(0, open_image(m_image_name, &ictx)); + + MockTestImageCtx mock_image_ctx(*ictx); + expect_get_object_size(mock_image_ctx); + + MockExclusiveLock mock_exclusive_lock; + if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) { + mock_image_ctx.exclusive_lock = &mock_exclusive_lock; + expect_is_lock_owner(mock_exclusive_lock); + } + + MockObjectMap mock_object_map; + if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) { + mock_image_ctx.object_map = &mock_object_map; + } + + bufferlist bl; + bl.append(std::string(4096, '1')); + + InSequence seq; + expect_get_parent_overlap(mock_image_ctx, CEPH_NOSNAP, 0, 0); + expect_object_may_exist(mock_image_ctx, 0, true); + expect_object_map_update(mock_image_ctx, 0, 1, OBJECT_EXISTS, {}, false, 0); + expect_writesame(mock_image_ctx, 0, 4096, 0); + + C_SaferCond ctx; + auto req = MockObjectWriteSameRequest::create_writesame( + &mock_image_ctx, ictx->get_object_name(0), 0, 0, 4096, bl, + mock_image_ctx.snapc, 0, {}, &ctx); + req->send(); + ASSERT_EQ(0, ctx.wait()); +} + +TEST_F(TestMockIoObjectRequest, CompareAndWrite) { + librbd::ImageCtx *ictx; + ASSERT_EQ(0, open_image(m_image_name, &ictx)); + + MockTestImageCtx mock_image_ctx(*ictx); + expect_get_object_size(mock_image_ctx); + + MockExclusiveLock mock_exclusive_lock; + if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) { + mock_image_ctx.exclusive_lock = &mock_exclusive_lock; + expect_is_lock_owner(mock_exclusive_lock); + } + + MockObjectMap mock_object_map; + if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) { + mock_image_ctx.object_map = &mock_object_map; + } + + bufferlist cmp_bl; + cmp_bl.append_zero(4096); + + bufferlist bl; + bl.append(std::string(4096, '1')); + + InSequence seq; + expect_get_parent_overlap(mock_image_ctx, CEPH_NOSNAP, 0, 0); + expect_object_may_exist(mock_image_ctx, 0, true); + expect_object_map_update(mock_image_ctx, 0, 1, OBJECT_EXISTS, {}, false, 0); + expect_cmpext(mock_image_ctx, 0, 0); + expect_write(mock_image_ctx, 0, 4096, 0); + + C_SaferCond ctx; + uint64_t mismatch_offset; + auto req = MockObjectWriteSameRequest::create_compare_and_write( + &mock_image_ctx, ictx->get_object_name(0), 0, 0, cmp_bl, bl, + mock_image_ctx.snapc, &mismatch_offset, 0, {}, &ctx); + req->send(); + ASSERT_EQ(0, ctx.wait()); +} + +TEST_F(TestMockIoObjectRequest, CompareAndWriteFull) { + librbd::ImageCtx *ictx; + ASSERT_EQ(0, open_image(m_image_name, &ictx)); + + MockTestImageCtx mock_image_ctx(*ictx); + expect_get_object_size(mock_image_ctx); + + MockExclusiveLock mock_exclusive_lock; + if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) { + mock_image_ctx.exclusive_lock = &mock_exclusive_lock; + expect_is_lock_owner(mock_exclusive_lock); + } + + MockObjectMap mock_object_map; + if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) { + mock_image_ctx.object_map = &mock_object_map; + } + + bufferlist cmp_bl; + cmp_bl.append_zero(ictx->get_object_size()); + + bufferlist bl; + bl.append(std::string(ictx->get_object_size(), '1')); + + InSequence seq; + expect_get_parent_overlap(mock_image_ctx, CEPH_NOSNAP, 0, 0); + expect_object_may_exist(mock_image_ctx, 0, true); + expect_object_map_update(mock_image_ctx, 0, 1, OBJECT_EXISTS, {}, false, 0); + expect_cmpext(mock_image_ctx, 0, 0); + expect_write_full(mock_image_ctx, 0); + + C_SaferCond ctx; + uint64_t mismatch_offset; + auto req = MockObjectWriteSameRequest::create_compare_and_write( + &mock_image_ctx, ictx->get_object_name(0), 0, 0, cmp_bl, bl, + mock_image_ctx.snapc, &mismatch_offset, 0, {}, &ctx); + req->send(); + ASSERT_EQ(0, ctx.wait()); +} + +TEST_F(TestMockIoObjectRequest, CompareAndWriteCopyup) { + REQUIRE_FEATURE(RBD_FEATURE_LAYERING); + + librbd::Image image; + librbd::RBD rbd; + ASSERT_EQ(0, rbd.open(m_ioctx, image, m_image_name.c_str(), NULL)); + ASSERT_EQ(0, image.snap_create("one")); + ASSERT_EQ(0, image.snap_protect("one")); + image.close(); + + std::string clone_name = get_temp_image_name(); + int order = 0; + ASSERT_EQ(0, rbd.clone(m_ioctx, m_image_name.c_str(), "one", m_ioctx, + clone_name.c_str(), RBD_FEATURE_LAYERING, &order)); + + librbd::ImageCtx *ictx; + ASSERT_EQ(0, open_image(clone_name, &ictx)); + + MockTestImageCtx mock_image_ctx(*ictx); + expect_get_object_size(mock_image_ctx); + + MockExclusiveLock mock_exclusive_lock; + if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) { + mock_image_ctx.exclusive_lock = &mock_exclusive_lock; + expect_is_lock_owner(mock_exclusive_lock); + } + + MockObjectMap mock_object_map; + if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) { + mock_image_ctx.object_map = &mock_object_map; + } + + bufferlist cmp_bl; + cmp_bl.append_zero(4096); + + bufferlist bl; + bl.append(std::string(4096, '1')); + + InSequence seq; + expect_get_parent_overlap(mock_image_ctx, CEPH_NOSNAP, 4096, 0); + expect_prune_parent_extents(mock_image_ctx, {{0, 4096}}, 4096, 4096); + expect_object_may_exist(mock_image_ctx, 0, true); + expect_object_map_update(mock_image_ctx, 0, 1, OBJECT_EXISTS, {}, false, 0); + expect_assert_exists(mock_image_ctx, -ENOENT); + + MockAbstractObjectWriteRequest *write_request = nullptr; + MockCopyupRequest mock_copyup_request; + expect_copyup(mock_copyup_request, &write_request, 0); + + expect_assert_exists(mock_image_ctx, 0); + expect_cmpext(mock_image_ctx, 0, 0); + expect_write(mock_image_ctx, 0, 4096, 0); + + C_SaferCond ctx; + uint64_t mismatch_offset; + auto req = MockObjectWriteSameRequest::create_compare_and_write( + &mock_image_ctx, ictx->get_object_name(0), 0, 0, cmp_bl, bl, + mock_image_ctx.snapc, &mismatch_offset, 0, {}, &ctx); + req->send(); + ASSERT_EQ(0, ctx.wait()); +} + +TEST_F(TestMockIoObjectRequest, CompareAndWriteMismatch) { + librbd::ImageCtx *ictx; + ASSERT_EQ(0, open_image(m_image_name, &ictx)); + + MockTestImageCtx mock_image_ctx(*ictx); + expect_get_object_size(mock_image_ctx); + + MockExclusiveLock mock_exclusive_lock; + if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) { + mock_image_ctx.exclusive_lock = &mock_exclusive_lock; + expect_is_lock_owner(mock_exclusive_lock); + } + + MockObjectMap mock_object_map; + if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) { + mock_image_ctx.object_map = &mock_object_map; + } + + bufferlist cmp_bl; + cmp_bl.append_zero(4096); + + bufferlist bl; + bl.append(std::string(4096, '1')); + + InSequence seq; + expect_get_parent_overlap(mock_image_ctx, CEPH_NOSNAP, 0, 0); + expect_object_may_exist(mock_image_ctx, 0, true); + expect_object_map_update(mock_image_ctx, 0, 1, OBJECT_EXISTS, {}, false, 0); + expect_cmpext(mock_image_ctx, 0, -MAX_ERRNO - 1); + + C_SaferCond ctx; + uint64_t mismatch_offset; + auto req = MockObjectWriteSameRequest::create_compare_and_write( + &mock_image_ctx, ictx->get_object_name(0), 0, 0, cmp_bl, bl, + mock_image_ctx.snapc, &mismatch_offset, 0, {}, &ctx); + req->send(); + ASSERT_EQ(-EILSEQ, ctx.wait()); + ASSERT_EQ(1ULL, mismatch_offset); +} + } // namespace io } // namespace librbd + diff --git a/src/test/librbd/mock/MockImageCtx.h b/src/test/librbd/mock/MockImageCtx.h index ee020c13509..17697a12d19 100644 --- a/src/test/librbd/mock/MockImageCtx.h +++ b/src/test/librbd/mock/MockImageCtx.h @@ -108,7 +108,8 @@ struct MockImageCtx { image_ctx.mirroring_resync_after_disconnect), mirroring_replay_delay(image_ctx.mirroring_replay_delay), non_blocking_aio(image_ctx.non_blocking_aio), - blkin_trace_all(image_ctx.blkin_trace_all) + blkin_trace_all(image_ctx.blkin_trace_all), + enable_alloc_hint(image_ctx.enable_alloc_hint) { md_ctx.dup(image_ctx.md_ctx); data_ctx.dup(image_ctx.data_ctx); @@ -147,6 +148,7 @@ struct MockImageCtx { MOCK_METHOD0(init_layout, void()); MOCK_CONST_METHOD1(get_object_name, std::string(uint64_t)); + MOCK_CONST_METHOD0(get_object_size, uint64_t()); MOCK_CONST_METHOD0(get_current_size, uint64_t()); MOCK_CONST_METHOD1(get_image_size, uint64_t(librados::snap_t)); MOCK_CONST_METHOD1(get_object_count, uint64_t(librados::snap_t)); @@ -315,6 +317,7 @@ struct MockImageCtx { int mirroring_replay_delay; bool non_blocking_aio; bool blkin_trace_all; + bool enable_alloc_hint; }; } // namespace librbd diff --git a/src/test/librbd/operation/test_mock_TrimRequest.cc b/src/test/librbd/operation/test_mock_TrimRequest.cc index 8821a7cb9ed..9509b203fda 100644 --- a/src/test/librbd/operation/test_mock_TrimRequest.cc +++ b/src/test/librbd/operation/test_mock_TrimRequest.cc @@ -94,7 +94,7 @@ struct ObjectRequest<librbd::MockTestImageCtx> : public ObjectRequestHandle { MOCK_METHOD3(construct, void(uint64_t, uint64_t, bool)); MOCK_METHOD0(send, void()); - MOCK_METHOD1(complete, void(int)); + MOCK_METHOD1(fail, void(int)); }; ObjectRequest<librbd::MockTestImageCtx>* ObjectRequest<librbd::MockTestImageCtx>::s_instance = nullptr; |