]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: handle DNE from immutable-object-cache
authorMykola Golub <mgolub@suse.com>
Fri, 17 Jul 2020 10:33:59 +0000 (11:33 +0100)
committerJason Dillaman <dillaman@redhat.com>
Thu, 27 Aug 2020 17:56:05 +0000 (13:56 -0400)
Fixes: https://tracker.ceph.com/issues/46581
Signed-off-by: Mykola Golub <mgolub@suse.com>
(cherry picked from commit 6b24320271d2dd06d737494d0f31d0891c7f29bf)

Conflicts:
src/librbd/cache/ParentCacheObjectDispatch.cc: trivial resolution
src/test/librbd/cache/test_mock_ParentCacheObjectDispatch.cc: ASIO refactor

src/librbd/cache/ParentCacheObjectDispatch.cc
src/librbd/cache/ParentCacheObjectDispatch.h
src/test/librbd/cache/test_mock_ParentCacheObjectDispatch.cc

index 9463c41f117823b6ba94d409751482528518a45f..172fd9c69e6aac1b71a6493f93d7e417f2922388 100644 (file)
@@ -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<I>::read(
 
   CacheGenContextURef ctx = make_gen_lambda_context<ObjectCacheRequest*,
                                      std::function<void(ObjectCacheRequest*)>>
-   ([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<I>::read(
 
 template <typename I>
 void ParentCacheObjectDispatch<I>::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<I>::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<I>(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);
index a32bdbf9fee83710d9cec27f7e4d2d2afcfe67b5..9480b48b90885f1c8f0871c25c9fc22198f54627 100644 (file)
@@ -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);
 
index a4f033f32d048a60d05d393e1a4d69bc0d3b4b1f..12f2b12f3a913a429a37cbdb08d642d183f52ffd 100644 (file)
@@ -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<MockParentImageCacheImageCtx> {
 
 }; // 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<librbd::MockParentImageCacheImageCtx> 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<ContextWQ*>(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