From: Mykola Golub Date: Fri, 17 Jul 2020 10:33:59 +0000 (+0100) Subject: librbd: handle DNE from immutable-object-cache X-Git-Tag: v15.2.9~122^2~92^2~3 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=07cc9b75e4e4e4b8e15497b1de0f78dff503095e;p=ceph.git librbd: handle DNE from immutable-object-cache Fixes: https://tracker.ceph.com/issues/46581 Signed-off-by: Mykola Golub (cherry picked from commit 6b24320271d2dd06d737494d0f31d0891c7f29bf) Conflicts: src/librbd/cache/ParentCacheObjectDispatch.cc: trivial resolution src/test/librbd/cache/test_mock_ParentCacheObjectDispatch.cc: ASIO refactor --- diff --git a/src/librbd/cache/ParentCacheObjectDispatch.cc b/src/librbd/cache/ParentCacheObjectDispatch.cc index 9463c41f1178..172fd9c69e6a 100644 --- a/src/librbd/cache/ParentCacheObjectDispatch.cc +++ b/src/librbd/cache/ParentCacheObjectDispatch.cc @@ -2,6 +2,7 @@ // vim: ts=8 sw=2 smarttab #include "common/WorkQueue.h" +#include "common/errno.h" #include "librbd/ImageCtx.h" #include "librbd/Journal.h" #include "librbd/Utils.h" @@ -87,10 +88,11 @@ bool ParentCacheObjectDispatch::read( CacheGenContextURef ctx = make_gen_lambda_context> - ([this, read_data, dispatch_result, on_dispatched, - oid, object_off, object_len](ObjectCacheRequest* ack) { - handle_read_cache(ack, object_off, object_len, read_data, - dispatch_result, on_dispatched); + ([this, read_data, dispatch_result, on_dispatched, object_no, object_off, + object_len, snap_id, &parent_trace](ObjectCacheRequest* ack) { + handle_read_cache(ack, object_no, object_off, object_len, snap_id, + parent_trace, read_data, dispatch_result, + on_dispatched); }); m_cache_client->lookup_object(m_image_ctx->data_ctx.get_namespace(), @@ -101,9 +103,10 @@ bool ParentCacheObjectDispatch::read( template void ParentCacheObjectDispatch::handle_read_cache( - ObjectCacheRequest* ack, uint64_t read_off, uint64_t read_len, - ceph::bufferlist* read_data, io::DispatchResult* dispatch_result, - Context* on_dispatched) { + ObjectCacheRequest* ack, uint64_t object_no, uint64_t read_off, + uint64_t read_len, librados::snap_t snap_id, + const ZTracer::Trace &parent_trace, ceph::bufferlist* read_data, + io::DispatchResult* dispatch_result, Context* on_dispatched) { auto cct = m_image_ctx->cct; ldout(cct, 20) << dendl; @@ -116,7 +119,20 @@ void ParentCacheObjectDispatch::handle_read_cache( ceph_assert(ack->type == RBDSC_READ_REPLY); std::string file_path = ((ObjectCacheReadReplyData*)ack)->cache_path; - ceph_assert(file_path != ""); + if (file_path.empty()) { + auto ctx = new LambdaContext( + [this, dispatch_result, on_dispatched](int r) { + if (r < 0 && r != -ENOENT) { + lderr(m_image_ctx->cct) << "failed to read parent: " + << cpp_strerror(r) << dendl; + } + *dispatch_result = io::DISPATCH_RESULT_COMPLETE; + on_dispatched->complete(r); + }); + io::util::read_parent(m_image_ctx, object_no, read_off, read_len, + snap_id, parent_trace, read_data, ctx); + return; + } // try to read from parent image cache int r = read_object(file_path, read_data, read_off, read_len, on_dispatched); diff --git a/src/librbd/cache/ParentCacheObjectDispatch.h b/src/librbd/cache/ParentCacheObjectDispatch.h index a32bdbf9fee8..9480b48b9088 100644 --- a/src/librbd/cache/ParentCacheObjectDispatch.h +++ b/src/librbd/cache/ParentCacheObjectDispatch.h @@ -117,12 +117,13 @@ private: int read_object(std::string file_path, ceph::bufferlist* read_data, uint64_t offset, uint64_t length, Context *on_finish); - void handle_read_cache( - ceph::immutable_obj_cache::ObjectCacheRequest* ack, - uint64_t read_off, uint64_t read_len, - ceph::bufferlist* read_data, - io::DispatchResult* dispatch_result, - Context* on_dispatched); + void handle_read_cache(ceph::immutable_obj_cache::ObjectCacheRequest* ack, + uint64_t object_no, uint64_t read_off, + uint64_t read_len, librados::snap_t snap_id, + const ZTracer::Trace &parent_trace, + ceph::bufferlist* read_data, + io::DispatchResult* dispatch_result, + Context* on_dispatched); int handle_register_client(bool reg); void create_cache_session(Context* on_finish, bool is_reconnect); diff --git a/src/test/librbd/cache/test_mock_ParentCacheObjectDispatch.cc b/src/test/librbd/cache/test_mock_ParentCacheObjectDispatch.cc index a4f033f32d04..12f2b12f3a91 100644 --- a/src/test/librbd/cache/test_mock_ParentCacheObjectDispatch.cc +++ b/src/test/librbd/cache/test_mock_ParentCacheObjectDispatch.cc @@ -9,6 +9,7 @@ #include "include/Context.h" #include "tools/immutable_object_cache/CacheClient.h" #include "test/immutable_object_cache/MockCacheDaemon.h" +#include "librbd/io/Utils.h" #include "librbd/cache/ParentCacheObjectDispatch.h" #include "test/librbd/test_mock_fixture.h" #include "test/librbd/mock/MockImageCtx.h" @@ -21,11 +22,9 @@ namespace { struct MockParentImageCacheImageCtx : public MockImageCtx { MockParentImageCacheImageCtx(ImageCtx& image_ctx) - : MockImageCtx(image_ctx), shared_cache_path("/tmp/socket/path"){ + : MockImageCtx(image_ctx) { } ~MockParentImageCacheImageCtx() {} - - std::string shared_cache_path; }; }; // anonymous namespace @@ -39,6 +38,39 @@ struct TypeTraits { }; // namespace cache +namespace io { +namespace util { + +namespace { + +struct Mock { + static Mock* s_instance; + + Mock() { + s_instance = this; + } + + MOCK_METHOD8(read_parent, + void(librbd::MockParentImageCacheImageCtx *, uint64_t, uint64_t, + uint64_t, librados::snap_t, const ZTracer::Trace &, + ceph::bufferlist*, Context*)); +}; + +Mock *Mock::s_instance = nullptr; + +} // anonymous namespace + +template<> void read_parent( + librbd::MockParentImageCacheImageCtx *image_ctx, uint64_t object_no, + uint64_t off, uint64_t len, librados::snap_t snap_id, + const ZTracer::Trace &trace, ceph::bufferlist* data, Context* on_finish) { + Mock::s_instance->read_parent(image_ctx, object_no, off, len, snap_id, trace, + data, on_finish); +} + +} // namespace util +} // namespace io + }; // namespace librbd #include "librbd/cache/ParentCacheObjectDispatch.cc" @@ -57,6 +89,7 @@ using ::testing::WithArgs; class TestMockParentCacheObjectDispatch : public TestMockFixture { public : typedef cache::ParentCacheObjectDispatch MockParentImageCache; + typedef io::util::Mock MockUtils; // ====== mock cache client ==== void expect_cache_run(MockParentImageCache& mparent_image_cache, bool ret_val) { @@ -102,6 +135,14 @@ public : }))); } + void expect_read_parent(MockUtils &mock_utils, uint64_t object_no, + uint64_t off, uint64_t len, librados::snap_t snap_id, + int r) { + EXPECT_CALL(mock_utils, + read_parent(_, object_no, off, len, snap_id, _, _, _)) + .WillOnce(WithArg<7>(CompleteContext(r, static_cast(nullptr)))); + } + void expect_cache_close(MockParentImageCache& mparent_image_cache, int ret_val) { auto& expect = EXPECT_CALL(*(mparent_image_cache.get_cache_client()), close()); @@ -339,4 +380,56 @@ TEST_F(TestMockParentCacheObjectDispatch, test_read) { delete mock_parent_image_cache; } +TEST_F(TestMockParentCacheObjectDispatch, test_read_dne) { + librbd::ImageCtx* ictx; + ASSERT_EQ(0, open_image(m_image_name, &ictx)); + MockParentImageCacheImageCtx mock_image_ctx(*ictx); + mock_image_ctx.child = &mock_image_ctx; + + auto mock_parent_image_cache = MockParentImageCache::create(&mock_image_ctx); + + expect_cache_run(*mock_parent_image_cache, 0); + C_SaferCond conn_cond; + Context* handle_connect = new LambdaContext([&conn_cond](int ret) { + ASSERT_EQ(ret, 0); + conn_cond.complete(0); + }); + expect_cache_async_connect(*mock_parent_image_cache, 0, handle_connect); + Context* ctx = new LambdaContext([](bool reg) { + ASSERT_EQ(reg, true); + }); + expect_cache_register(*mock_parent_image_cache, ctx, 0); + expect_io_object_dispatcher_register_state(*mock_parent_image_cache, 0); + expect_cache_close(*mock_parent_image_cache, 0); + expect_cache_stop(*mock_parent_image_cache, 0); + + mock_parent_image_cache->init(); + conn_cond.wait(); + + ASSERT_EQ(mock_parent_image_cache->get_object_dispatch_layer(), + io::OBJECT_DISPATCH_LAYER_PARENT_CACHE); + expect_cache_session_state(*mock_parent_image_cache, true); + ASSERT_EQ(mock_parent_image_cache->get_cache_client()->is_session_work(), + true); + + EXPECT_CALL(*(mock_parent_image_cache->get_cache_client()), is_session_work()) + .WillOnce(Return(true)); + + expect_cache_lookup_object(*mock_parent_image_cache, ""); + + MockUtils mock_utils; + expect_read_parent(mock_utils, 0, 0, 4096, CEPH_NOSNAP, 0); + + C_SaferCond on_dispatched; + io::DispatchResult dispatch_result; + mock_parent_image_cache->read(0, 0, 4096, CEPH_NOSNAP, 0, {}, nullptr, + nullptr, nullptr, &dispatch_result, nullptr, + &on_dispatched); + ASSERT_EQ(0, on_dispatched.wait()); + + mock_parent_image_cache->get_cache_client()->close(); + mock_parent_image_cache->get_cache_client()->stop(); + delete mock_parent_image_cache; +} + } // namespace librbd