]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: optionally disable read-from-parent for object-extent IO requests
authorJason Dillaman <dillaman@redhat.com>
Thu, 3 Sep 2020 13:40:50 +0000 (09:40 -0400)
committerJason Dillaman <dillaman@redhat.com>
Mon, 21 Sep 2020 11:51:56 +0000 (07:51 -0400)
Deep-copy (and eventually crypto) will need a way to prevent read-from-parent
IO requests. This introduces an optional flag at the object-extent IO layer
to disable that functionality.

Signed-off-by: Jason Dillaman <dillaman@redhat.com>
27 files changed:
src/librbd/cache/ObjectCacherObjectDispatch.cc
src/librbd/cache/ObjectCacherObjectDispatch.h
src/librbd/cache/ObjectCacherWriteback.cc
src/librbd/cache/ObjectCacherWriteback.h
src/librbd/cache/ParentCacheObjectDispatch.cc
src/librbd/cache/ParentCacheObjectDispatch.h
src/librbd/cache/WriteAroundObjectDispatch.cc
src/librbd/cache/WriteAroundObjectDispatch.h
src/librbd/crypto/CryptoObjectDispatch.cc
src/librbd/crypto/CryptoObjectDispatch.h
src/librbd/io/ImageRequest.cc
src/librbd/io/ObjectDispatch.cc
src/librbd/io/ObjectDispatch.h
src/librbd/io/ObjectDispatchInterface.h
src/librbd/io/ObjectDispatchSpec.h
src/librbd/io/ObjectDispatcher.cc
src/librbd/io/ObjectRequest.cc
src/librbd/io/ObjectRequest.h
src/librbd/io/SimpleSchedulerObjectDispatch.cc
src/librbd/io/SimpleSchedulerObjectDispatch.h
src/librbd/io/Types.h
src/librbd/journal/ObjectDispatch.h
src/test/librbd/cache/test_mock_ParentCacheObjectDispatch.cc
src/test/librbd/crypto/test_mock_CryptoObjectDispatch.cc
src/test/librbd/io/test_mock_ObjectRequest.cc
src/test/librbd/io/test_mock_SimpleSchedulerObjectDispatch.cc
src/test/librbd/mock/io/MockObjectDispatch.h

index 71b72e90f8782c2f7cd4c8d4e5a1fc48967777ec..92539478d764f2ae8b2ec8a2ebb902529745f665 100644 (file)
@@ -183,7 +183,7 @@ void ObjectCacherObjectDispatch<I>::shut_down(Context* on_finish) {
 template <typename I>
 bool ObjectCacherObjectDispatch<I>::read(
     uint64_t object_no, const io::Extents &extents, IOContext io_context,
-    int op_flags, const ZTracer::Trace &parent_trace,
+    int op_flags, int read_flags, const ZTracer::Trace &parent_trace,
     ceph::bufferlist* read_data, io::Extents* extent_map, uint64_t* version,
     int* object_dispatch_flags, io::DispatchResult* dispatch_result,
     Context** on_finish, Context* on_dispatched) {
@@ -202,6 +202,11 @@ bool ObjectCacherObjectDispatch<I>::read(
   on_dispatched = util::create_async_context_callback(*m_image_ctx,
                                                       on_dispatched);
 
+  // embed the RBD-internal read flags in the genenric RADOS op_flags and
+  op_flags = ((op_flags & ~ObjectCacherWriteback::READ_FLAGS_MASK) |
+              ((read_flags << ObjectCacherWriteback::READ_FLAGS_SHIFT) &
+               ObjectCacherWriteback::READ_FLAGS_MASK));
+
   m_image_ctx->image_lock.lock_shared();
   auto rd = m_object_cacher->prepare_read(
     io_context->read_snap().value_or(CEPH_NOSNAP), read_data, op_flags);
index ece4a75146721e44e41b918ed6fe03f309820954..ca60b04b1d8fb75c58333389fa38abffca3de697 100644 (file)
@@ -43,7 +43,7 @@ public:
 
   bool read(
       uint64_t object_no, const io::Extents &extents, IOContext io_context,
-      int op_flags, const ZTracer::Trace &parent_trace,
+      int op_flags, int read_flags, const ZTracer::Trace &parent_trace,
       ceph::bufferlist* read_data, io::Extents* extent_map,
       uint64_t* version, int* object_dispatch_flags,
       io::DispatchResult* dispatch_result, Context** on_finish,
index 4c7f193f7ae308af8c5e84a3a4c949e6ce58c6eb..b99438a65d6b9471d28dc1b78e7a7bc0dc0d2c77 100644 (file)
@@ -142,9 +142,13 @@ void ObjectCacherWriteback::read(const object_t& oid, uint64_t object_no,
     io_context->read_snap(snapid);
   }
 
+  // extract the embedded RBD read flags from the op_flags
+  int read_flags = (op_flags & READ_FLAGS_MASK) >> READ_FLAGS_SHIFT;
+  op_flags &= ~READ_FLAGS_MASK;
+
   auto req = io::ObjectDispatchSpec::create_read(
     m_ictx, io::OBJECT_DISPATCH_LAYER_CACHE, object_no, {{off, len}},
-    io_context, op_flags, trace, &req_comp->bl,
+    io_context, op_flags, read_flags, trace, &req_comp->bl,
     &req_comp->extent_map, nullptr, req_comp);
   req->send();
 }
index 6d7f367b614fc149af1820431c112112d8f7c0e8..d8c2ebbd991d007607fc7f88d471dc86e003a342 100644 (file)
@@ -19,6 +19,9 @@ namespace cache {
 
 class ObjectCacherWriteback : public WritebackHandler {
 public:
+  static const int READ_FLAGS_MASK  = 0xF000;
+  static const int READ_FLAGS_SHIFT = 24;
+
   ObjectCacherWriteback(ImageCtx *ictx, ceph::mutex& lock);
 
   // Note that oloc, trunc_size, and trunc_seq are ignored
index 78abaa148c86ca2ea640a49df8c3722ea6689549..6b81198b961378d759ee4569e3eed75e7644037c 100644 (file)
@@ -66,7 +66,7 @@ void ParentCacheObjectDispatch<I>::init(Context* on_finish) {
 template <typename I>
 bool ParentCacheObjectDispatch<I>::read(
     uint64_t object_no, const io::Extents &extents, IOContext io_context,
-    int op_flags, const ZTracer::Trace &parent_trace,
+    int op_flags, int read_flags, const ZTracer::Trace &parent_trace,
     ceph::bufferlist* read_data, io::Extents* extent_map, uint64_t* version,
     int* object_dispatch_flags, io::DispatchResult* dispatch_result,
     Context** on_finish, Context* on_dispatched) {
index 603ae252fdfaeecfdbd4ca44935aeaf0bc4a19fd..910c5e32b15a1d1c3aee12413de937ba0f83deb0 100644 (file)
@@ -45,7 +45,7 @@ public:
 
   bool read(
       uint64_t object_no, const io::Extents &extents, IOContext io_context,
-      int op_flags, const ZTracer::Trace &parent_trace,
+      int op_flags, int read_flags, const ZTracer::Trace &parent_trace,
       ceph::bufferlist* read_data, io::Extents* extent_map,
       uint64_t* version, int* object_dispatch_flags,
       io::DispatchResult* dispatch_result, Context** on_finish,
index 0992afafbddb8b3d5b6fc1f8754e706cdc3213d2..e202b08b6c068f66e0fbf5cedd2cafc94f84e958 100644 (file)
@@ -58,7 +58,7 @@ void WriteAroundObjectDispatch<I>::shut_down(Context* on_finish) {
 template <typename I>
 bool WriteAroundObjectDispatch<I>::read(
     uint64_t object_no, const io::Extents &extents, IOContext io_context,
-    int op_flags, const ZTracer::Trace &parent_trace,
+    int op_flags, int read_flags, const ZTracer::Trace &parent_trace,
     ceph::bufferlist* read_data, io::Extents* extent_map, uint64_t* version,
     int* object_dispatch_flags, io::DispatchResult* dispatch_result,
     Context** on_finish, Context* on_dispatched) {
index 73c470f6aad54bc8637e4bf1b5c2364835825551..8086ddc546b581d37d97990daac5f9e7e3821f66 100644 (file)
@@ -43,7 +43,7 @@ public:
 
   bool read(
       uint64_t object_no, const io::Extents &extents, IOContext io_context,
-      int op_flags, const ZTracer::Trace &parent_trace,
+      int op_flags, int read_flags, const ZTracer::Trace &parent_trace,
       ceph::bufferlist* read_data, io::Extents* extent_map,
       uint64_t* version, int* object_dispatch_flags,
       io::DispatchResult* dispatch_result, Context** on_finish,
index 197747628bc0b8fdcf65c8cdb0e9e2f49cbcb9ef..782d1468a850490f339563f0ed3b374dc03e625c 100644 (file)
@@ -38,7 +38,7 @@ struct C_EncryptedObjectReadRequest : public Context {
     C_EncryptedObjectReadRequest(
             I* image_ctx, CryptoInterface* crypto, uint64_t object_no,
             uint64_t object_off, uint64_t object_len, IOContext io_context,
-            int op_flags, const ZTracer::Trace &parent_trace,
+            int op_flags, int read_flags, const ZTracer::Trace &parent_trace,
             ceph::bufferlist* read_data, int* object_dispatch_flags,
             Context** on_finish,
             Context* on_dispatched) : image_ctx(image_ctx),
@@ -61,8 +61,9 @@ struct C_EncryptedObjectReadRequest : public Context {
 
       req = io::ObjectDispatchSpec::create_read(
               image_ctx, io::OBJECT_DISPATCH_LAYER_CRYPTO, object_no,
-              {{object_off, object_len}}, io_context, op_flags, parent_trace,
-              &req_comp->bl, &req_comp->extent_map, nullptr, req_comp);
+              {{object_off, object_len}}, io_context, op_flags, read_flags,
+              parent_trace, &req_comp->bl, &req_comp->extent_map, nullptr,
+              req_comp);
     }
 
     void send() {
@@ -111,8 +112,8 @@ void CryptoObjectDispatch<I>::shut_down(Context* on_finish) {
 
 template <typename I>
 bool CryptoObjectDispatch<I>::read(
-    uint64_t object_no, const io::Extents &extents,
-    IOContext io_context, int op_flags, const ZTracer::Trace &parent_trace,
+    uint64_t object_no, const io::Extents &extents, IOContext io_context,
+    int op_flags, int read_flags, const ZTracer::Trace &parent_trace,
     ceph::bufferlist* read_data, io::Extents* extent_map, uint64_t* version,
     int* object_dispatch_flags, io::DispatchResult* dispatch_result,
     Context** on_finish, Context* on_dispatched) {
@@ -132,8 +133,8 @@ bool CryptoObjectDispatch<I>::read(
   *dispatch_result = io::DISPATCH_RESULT_COMPLETE;
   auto req = new C_EncryptedObjectReadRequest<I>(
           m_image_ctx, m_crypto, object_no, object_off, object_len, io_context,
-          op_flags, parent_trace, read_data, object_dispatch_flags, on_finish,
-          on_dispatched);
+          op_flags, read_flags, parent_trace, read_data, object_dispatch_flags,
+          on_finish, on_dispatched);
   req->send();
   return true;
 }
index 053be22d4ef607dda6473b6166e3d37603cf5028..68f1acf48d06fbfa5f036259c96af526a2b84e0d 100644 (file)
@@ -33,7 +33,7 @@ public:
 
   bool read(
       uint64_t object_no, const io::Extents &extents,
-      IOContext io_context, int op_flags,
+      IOContext io_context, int op_flags, int read_flags,
       const ZTracer::Trace &parent_trace, ceph::bufferlist* read_data,
       io::Extents* extent_map, uint64_t* version, int* object_dispatch_flags,
       io::DispatchResult* dispatch_result, Context** on_finish,
index 8869e5b19813c245b103b4939e4e770d20444ff2..b9b624b5975156b313c323b9053f6983b9dbbc7f 100644 (file)
@@ -177,7 +177,7 @@ void readahead(I *ictx, const Extents& image_extents, IOContext io_context) {
                                              object_extent.length);
       auto req = io::ObjectDispatchSpec::create_read(
         ictx, io::OBJECT_DISPATCH_LAYER_NONE, object_extent.object_no,
-        {{object_extent.offset, object_extent.length}}, io_context, 0, {},
+        {{object_extent.offset, object_extent.length}}, io_context, 0, 0, {},
         &req_comp->read_data, &req_comp->extent_map, nullptr, req_comp);
       req->send();
     }
@@ -482,7 +482,7 @@ void ImageReadRequest<I>::send_request() {
       aio_comp, oe.offset, oe.length, std::move(oe.buffer_extents));
     auto req = ObjectDispatchSpec::create_read(
       &image_ctx, OBJECT_DISPATCH_LAYER_NONE, oe.object_no,
-      {{oe.offset, oe.length}}, this->m_io_context, m_op_flags, this->m_trace,
+      {{oe.offset, oe.length}}, this->m_io_context, m_op_flags, 0, this->m_trace,
       &req_comp->bl, &req_comp->extent_map, nullptr, req_comp);
     req->send();
   }
index af8ec04df24b0ae0346bf05707d1d3352fd732bc..fde16482b5c3732a7134323aca098019d006a747 100644 (file)
@@ -34,7 +34,7 @@ void ObjectDispatch<I>::shut_down(Context* on_finish) {
 template <typename I>
 bool ObjectDispatch<I>::read(
     uint64_t object_no, const Extents &extents, IOContext io_context,
-    int op_flags, const ZTracer::Trace &parent_trace,
+    int op_flags, int read_flags, const ZTracer::Trace &parent_trace,
     ceph::bufferlist* read_data, Extents* extent_map, uint64_t* version,
     int* object_dispatch_flags, DispatchResult* dispatch_result,
     Context** on_finish, Context* on_dispatched) {
@@ -43,9 +43,9 @@ bool ObjectDispatch<I>::read(
 
   *dispatch_result = DISPATCH_RESULT_COMPLETE;
   auto req = new ObjectReadRequest<I>(m_image_ctx, object_no, extents,
-                                     io_context,  op_flags, parent_trace,
-                                     read_data, extent_map, version,
-                                     on_dispatched);
+                                      io_context, op_flags, read_flags,
+                                      parent_trace, read_data, extent_map,
+                                      version, on_dispatched);
   req->send();
   return true;
 }
index 9bbaa5e2f65d4dabeb1b2730989430eae5b25b76..3d7f9eba9a3355891704e61fae32dbf47b1e685f 100644 (file)
@@ -34,7 +34,7 @@ public:
 
   bool read(
       uint64_t object_no, const Extents &extents, IOContext io_context,
-      int op_flags, const ZTracer::Trace &parent_trace,
+      int op_flags, int read_flags, const ZTracer::Trace &parent_trace,
       ceph::bufferlist* read_data, Extents* extent_map,
       uint64_t* version, int* object_dispatch_flags,
       DispatchResult* dispatch_result, Context** on_finish,
index a4525bee883e7d6e3a67545a504152a918ae4bdd..92fd13de7f15fd512b26557ad14d74e0c2553dd2 100644 (file)
@@ -35,7 +35,7 @@ struct ObjectDispatchInterface {
 
   virtual bool read(
       uint64_t object_no, const Extents &extents,
-      IOContext io_context, int op_flags,
+      IOContext io_context, int op_flags, int read_flags,
       const ZTracer::Trace &parent_trace, ceph::bufferlist* read_data,
       Extents* extent_map, uint64_t* version, int* object_dispatch_flags,
       DispatchResult* dispatch_result, Context** on_finish,
index ee0e88fed7e4f16e4542ce77395530004dbf7c2b..c9daae6c082820af32566d2505ba1a69b4c0ba7e 100644 (file)
@@ -44,15 +44,16 @@ public:
 
   struct ReadRequest : public RequestBase {
     const Extents extents;
+    int read_flags;
     ceph::bufferlist* read_data;
     Extents* extent_map;
     uint64_t* version;
 
     ReadRequest(uint64_t object_no, const Extents &extents,
-                ceph::bufferlist* read_data, Extents* extent_map,
-                uint64_t* version)
-      : RequestBase(object_no), extents(extents), read_data(read_data),
-        extent_map(extent_map), version(version) {
+                int read_flags, ceph::bufferlist* read_data,
+                Extents* extent_map, uint64_t* version)
+      : RequestBase(object_no), extents(extents), read_flags(read_flags),
+        read_data(read_data), extent_map(extent_map), version(version) {
     }
   };
 
@@ -170,13 +171,14 @@ public:
   static ObjectDispatchSpec* create_read(
       ImageCtxT* image_ctx, ObjectDispatchLayer object_dispatch_layer,
       uint64_t object_no, const Extents &extents, IOContext io_context,
-      int op_flags, const ZTracer::Trace &parent_trace,
+      int op_flags, int read_flags, const ZTracer::Trace &parent_trace,
       ceph::bufferlist* read_data, Extents* extent_map, uint64_t* version,
       Context* on_finish) {
     return new ObjectDispatchSpec(image_ctx->io_object_dispatcher,
                                   object_dispatch_layer,
                                   ReadRequest{object_no, extents,
-                                              read_data, extent_map, version},
+                                              read_flags, read_data, extent_map,
+                                              version},
                                   io_context, op_flags, parent_trace,
                                   on_finish);
   }
index 380cda279d96f75117fb410fa74a327cfa6a40bc..432573c132be6df5e2775929c4fdf3b4e5dd7330 100644 (file)
@@ -108,7 +108,8 @@ struct ObjectDispatcher<I>::SendVisitor : public boost::static_visitor<bool> {
   bool operator()(ObjectDispatchSpec::ReadRequest& read) const {
     return object_dispatch->read(
       read.object_no, read.extents, object_dispatch_spec->io_context,
-      object_dispatch_spec->op_flags, object_dispatch_spec->parent_trace,
+      object_dispatch_spec->op_flags, read.read_flags,
+      object_dispatch_spec->parent_trace,
       read.read_data, read.extent_map, read.version,
       &object_dispatch_spec->object_dispatch_flags,
       &object_dispatch_spec->dispatch_result,
index 04646fcd8b3bfebc6d9a5eebf30367a204187082..bdb724535a9bebc067390f401b3fe3d51182857d 100644 (file)
@@ -201,13 +201,13 @@ void ObjectRequest<I>::finish(int r) {
 template <typename I>
 ObjectReadRequest<I>::ObjectReadRequest(
     I *ictx, uint64_t objectno, const Extents &extents,
-    IOContext io_context, int op_flags, const ZTracer::Trace &parent_trace,
-    ceph::bufferlist* read_data, Extents* extent_map, uint64_t* version,
-    Context *completion)
-  : ObjectRequest<I>(ictx, objectno, io_context, "read", parent_trace,
-                     completion),
-    m_extents(extents), m_op_flags(op_flags), m_read_data(read_data),
-    m_extent_map(extent_map), m_version(version) {
+    IOContext io_context, int op_flags, int read_flags,
+    const ZTracer::Trace &parent_trace, ceph::bufferlist* read_data,
+    Extents* extent_map, uint64_t* version, Context *completion)
+  : ObjectRequest<I>(ictx, objectno, io_context, "read",
+                     parent_trace, completion),
+    m_extents(extents), m_op_flags(op_flags), m_read_flags(read_flags),
+    m_read_data(read_data), m_extent_map(extent_map), m_version(version) {
 }
 
 template <typename I>
@@ -299,6 +299,11 @@ void ObjectReadRequest<I>::handle_read_object(int r) {
 
 template <typename I>
 void ObjectReadRequest<I>::read_parent() {
+  if ((m_read_flags & READ_FLAG_DISABLE_READ_FROM_PARENT) != 0) {
+    this->finish(-ENOENT);
+    return;
+  }
+
   I *image_ctx = this->m_ictx;
   ldout(image_ctx->cct, 20) << dendl;
 
index dab819f637a733c9a58a48fbe8a91f6b1e7ac17c..35da69abdd83c385da0cc4810ea7c21840c79ea8 100644 (file)
@@ -94,19 +94,19 @@ class ObjectReadRequest : public ObjectRequest<ImageCtxT> {
 public:
   static ObjectReadRequest* create(
       ImageCtxT *ictx, uint64_t objectno, const Extents &extents,
-      IOContext io_context, int op_flags, const ZTracer::Trace &parent_trace,
-      ceph::bufferlist* read_data, Extents* extent_map, uint64_t* version,
-      Context *completion) {
+      IOContext io_context, int op_flags, int read_flags,
+      const ZTracer::Trace &parent_trace, ceph::bufferlist* read_data,
+      Extents* extent_map, uint64_t* version, Context *completion) {
     return new ObjectReadRequest(ictx, objectno, extents, io_context, op_flags,
-                                 parent_trace, read_data, extent_map, version,
-                                 completion);
+                                 read_flags, parent_trace, read_data,
+                                 extent_map, version, completion);
   }
 
   ObjectReadRequest(
       ImageCtxT *ictx, uint64_t objectno, const Extents &extents,
-      IOContext io_context, int op_flags, const ZTracer::Trace &parent_trace,
-      ceph::bufferlist* read_data, Extents* extent_map, uint64_t* version,
-      Context *completion);
+      IOContext io_context, int op_flags, int read_flags,
+      const ZTracer::Trace &parent_trace, ceph::bufferlist* read_data,
+      Extents* extent_map, uint64_t* version, Context *completion);
 
   void send() override;
 
@@ -142,6 +142,7 @@ private:
   typedef std::vector<ExtentResult> ExtentResults;
   ExtentResults m_extent_results;
   int m_op_flags;
+  int m_read_flags;
 
   ceph::bufferlist* m_read_data;
   Extents* m_extent_map;
index f16167957dbe4a20b95da2d75d6e8b7657bf5dc7..2886de0aba08032c94fc9a184c176c58d3b43ea7 100644 (file)
@@ -220,7 +220,7 @@ void SimpleSchedulerObjectDispatch<I>::shut_down(Context* on_finish) {
 template <typename I>
 bool SimpleSchedulerObjectDispatch<I>::read(
     uint64_t object_no, const Extents &extents, IOContext io_context,
-    int op_flags, const ZTracer::Trace &parent_trace,
+    int op_flags, int read_flags, const ZTracer::Trace &parent_trace,
     ceph::bufferlist* read_data, Extents* extent_map, uint64_t* version,
     int* object_dispatch_flags, DispatchResult* dispatch_result,
     Context** on_finish, Context* on_dispatched) {
index cc34ac9903975f170d1a733ef0ad54fedec1fa8d..faf965dc14992f77ecb3b5dd27c213dc1e309328 100644 (file)
@@ -50,7 +50,7 @@ public:
 
   bool read(
       uint64_t object_no, const Extents &extents, IOContext io_context,
-      int op_flags, const ZTracer::Trace &parent_trace,
+      int op_flags, int read_flags, const ZTracer::Trace &parent_trace,
       ceph::bufferlist* read_data, Extents* extent_map,
       uint64_t* version, int* object_dispatch_flags,
       DispatchResult* dispatch_result, Context** on_finish,
index 58f4ef3919905f88aec3c4449ad23157d84be513..bce9fd22762e4d6f60aca319566fbbd154dd1cb6 100644 (file)
@@ -106,6 +106,10 @@ enum ObjectDispatchLayer {
   OBJECT_DISPATCH_LAYER_LAST
 };
 
+enum {
+  READ_FLAG_DISABLE_READ_FROM_PARENT            = 1UL << 0,
+};
+
 enum {
   OBJECT_WRITE_FLAG_CREATE_EXCLUSIVE            = 1UL << 0
 };
index 64f0ab251d68b2e911d58f62543b75f80860c26e..a523fa390de1252d09a2cc36a981bad8fdb39fc1 100644 (file)
@@ -38,7 +38,7 @@ public:
 
   bool read(
       uint64_t object_no, const io::Extents &extents, IOContext io_context,
-      int op_flags, const ZTracer::Trace &parent_trace,
+      int op_flags, int read_flags, const ZTracer::Trace &parent_trace,
       ceph::bufferlist* read_data, io::Extents* extent_map,
       uint64_t* version, int* object_dispatch_flags,
       io::DispatchResult* dispatch_result, Context** on_finish,
index 1185500e332dec330311a88538572fa1414d6046..f3947ebe84d80ca975525be666bb4012e6314f9d 100644 (file)
@@ -362,7 +362,7 @@ TEST_F(TestMockParentCacheObjectDispatch, test_read) {
   io::DispatchResult dispatch_result;
   ceph::bufferlist read_data;
   mock_parent_image_cache->read(
-    0, {{0, 4096}}, mock_image_ctx.get_data_io_context(), 0, {}, &read_data,
+    0, {{0, 4096}}, mock_image_ctx.get_data_io_context(), 0, 0, {}, &read_data,
     nullptr, nullptr, nullptr, &dispatch_result, nullptr, &on_dispatched);
   ASSERT_EQ(0, on_dispatched.wait());
 
@@ -415,7 +415,7 @@ TEST_F(TestMockParentCacheObjectDispatch, test_read_dne) {
   C_SaferCond on_dispatched;
   io::DispatchResult dispatch_result;
   mock_parent_image_cache->read(
-    0, {{0, 4096}}, mock_image_ctx.get_data_io_context(), 0, {}, nullptr,
+    0, {{0, 4096}}, mock_image_ctx.get_data_io_context(), 0, 0, {}, nullptr,
     nullptr, nullptr, nullptr, &dispatch_result, nullptr, &on_dispatched);
   ASSERT_EQ(0, on_dispatched.wait());
 
index 8ae7c1d39aea5a6248a08efb30f539a465ca0f73..af5932130512d3d47bc957af8a581a658b4f282d 100644 (file)
@@ -136,7 +136,7 @@ TEST_F(TestMockCryptoCryptoObjectDispatch, Discard) {
 TEST_F(TestMockCryptoCryptoObjectDispatch, ReadFail) {
   expect_object_read();
   ASSERT_TRUE(mock_crypto_object_dispatch->read(
-      0, {{0, 4096}}, mock_image_ctx->get_data_io_context(), 0, {}, &data,
+      0, {{0, 4096}}, mock_image_ctx->get_data_io_context(), 0, 0, {}, &data,
       &extent_map, nullptr, &object_dispatch_flags, &dispatch_result,
       &on_finish, on_dispatched));
   ASSERT_EQ(dispatch_result, io::DISPATCH_RESULT_COMPLETE);
@@ -150,8 +150,8 @@ TEST_F(TestMockCryptoCryptoObjectDispatch, ReadFail) {
 TEST_F(TestMockCryptoCryptoObjectDispatch, Read) {
   expect_object_read();
   ASSERT_TRUE(mock_crypto_object_dispatch->read(
-          0, {{0, 4096}}, mock_image_ctx->get_data_io_context(), 0, {}, &data,
-          &extent_map, nullptr, &object_dispatch_flags, &dispatch_result,
+          0, {{0, 4096}}, mock_image_ctx->get_data_io_context(), 0, 0, {},
+          &data, &extent_map, nullptr, &object_dispatch_flags, &dispatch_result,
           &on_finish, on_dispatched));
   ASSERT_EQ(dispatch_result, io::DISPATCH_RESULT_COMPLETE);
   ASSERT_NE(on_finish, &finished_cond);
index 902dc41be32ee6d03e9cd1bc41cd5e571b13ca03..3e2fbbdbeb84984b832daf865b9e2c8a70e33df1 100644 (file)
@@ -427,7 +427,7 @@ TEST_F(TestMockIoObjectRequest, Read) {
   uint64_t version;
   auto req = MockObjectReadRequest::create(
           &mock_image_ctx, 0, {{0, 4096}, {8192, 4096}},
-          mock_image_ctx.get_data_io_context(), 0, {},
+          mock_image_ctx.get_data_io_context(), 0, 0, {},
           &bl, &extent_map, &version, &ctx);
   req->send();
   ASSERT_EQ(0, ctx.wait());
@@ -468,7 +468,7 @@ TEST_F(TestMockIoObjectRequest, SparseReadThreshold) {
   auto req = MockObjectReadRequest::create(
     &mock_image_ctx, 0,
     {{0, ictx->sparse_read_threshold_bytes}},
-    mock_image_ctx.get_data_io_context(), 0, {}, &bl,
+    mock_image_ctx.get_data_io_context(), 0, 0, {}, &bl,
     &extent_map, nullptr, &ctx);
   req->send();
   ASSERT_EQ(0, ctx.wait());
@@ -496,7 +496,7 @@ TEST_F(TestMockIoObjectRequest, ReadError) {
   C_SaferCond ctx;
   auto req = MockObjectReadRequest::create(
     &mock_image_ctx, 0, {{0, 4096}},
-    mock_image_ctx.get_data_io_context(), 0, {}, &bl, &extent_map,
+    mock_image_ctx.get_data_io_context(), 0, 0, {}, &bl, &extent_map,
     nullptr, &ctx);
   req->send();
   ASSERT_EQ(-EPERM, ctx.wait());
@@ -543,7 +543,7 @@ TEST_F(TestMockIoObjectRequest, ParentRead) {
   C_SaferCond ctx;
   auto req = MockObjectReadRequest::create(
     &mock_image_ctx, 0, {{0, 4096}},
-    mock_image_ctx.get_data_io_context(), 0, {}, &bl, &extent_map,
+    mock_image_ctx.get_data_io_context(), 0, 0, {}, &bl, &extent_map,
     nullptr, &ctx);
   req->send();
   ASSERT_EQ(0, ctx.wait());
@@ -590,12 +590,56 @@ TEST_F(TestMockIoObjectRequest, ParentReadError) {
   C_SaferCond ctx;
   auto req = MockObjectReadRequest::create(
     &mock_image_ctx, 0, {{0, 4096}},
-    mock_image_ctx.get_data_io_context(), 0, {}, &bl, &extent_map,
+    mock_image_ctx.get_data_io_context(), 0, 0, {}, &bl, &extent_map,
     nullptr, &ctx);
   req->send();
   ASSERT_EQ(-EPERM, ctx.wait());
 }
 
+TEST_F(TestMockIoObjectRequest, SkipParentRead) {
+  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));
+  ictx->sparse_read_threshold_bytes = 8096;
+  ictx->clone_copy_on_read = false;
+
+  MockTestImageCtx mock_image_ctx(*ictx);
+  mock_image_ctx.parent = &mock_image_ctx;
+
+  MockObjectMap mock_object_map;
+  if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) {
+    mock_image_ctx.object_map = &mock_object_map;
+  }
+
+  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, ictx->get_object_name(0), 0, 4096, "", -ENOENT);
+
+  bufferlist bl;
+  Extents extent_map;
+  C_SaferCond ctx;
+  auto req = MockObjectReadRequest::create(
+    &mock_image_ctx, 0, {{0, 4096}}, mock_image_ctx.get_data_io_context(), 0,
+    READ_FLAG_DISABLE_READ_FROM_PARENT, {}, &bl, &extent_map,
+    nullptr, &ctx);
+  req->send();
+  ASSERT_EQ(-ENOENT, ctx.wait());
+}
+
 TEST_F(TestMockIoObjectRequest, CopyOnRead) {
   REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
 
@@ -642,7 +686,7 @@ TEST_F(TestMockIoObjectRequest, CopyOnRead) {
   C_SaferCond ctx;
   auto req = MockObjectReadRequest::create(
     &mock_image_ctx, 0, {{0, 4096}},
-    mock_image_ctx.get_data_io_context(), 0, {}, &bl, &extent_map,
+    mock_image_ctx.get_data_io_context(), 0, 0, {}, &bl, &extent_map,
     nullptr, &ctx);
   req->send();
   ASSERT_EQ(0, ctx.wait());
index febbfdb8bdbb124878d5f2ad5ca953d6e969df2f..dd7625cecb8a455759975a66c566fef4cc403bde 100644 (file)
@@ -132,7 +132,7 @@ TEST_F(TestMockIoSimpleSchedulerObjectDispatch, Read) {
   C_SaferCond cond;
   Context *on_finish = &cond;
   ASSERT_FALSE(mock_simple_scheduler_object_dispatch.read(
-      0, {{0, 4096}}, mock_image_ctx.get_data_io_context(), 0, {}, nullptr,
+      0, {{0, 4096}}, mock_image_ctx.get_data_io_context(), 0, 0, {}, nullptr,
       nullptr, nullptr, nullptr, nullptr, &on_finish, nullptr));
   ASSERT_EQ(on_finish, &cond); // not modified
   on_finish->complete(0);
index b873964c21e081f4f01ce2df993d30d24bc28102..ccdde9f74b1605f92749a6da9e087bf33e083962 100644 (file)
@@ -30,7 +30,7 @@ public:
                     DispatchResult*, Context*));
   bool read(
       uint64_t object_no, const Extents& extents, IOContext io_context,
-      int op_flags, const ZTracer::Trace& parent_trace,
+      int op_flags, int read_flags, const ZTracer::Trace& parent_trace,
       ceph::bufferlist* read_data, Extents* extent_map, uint64_t* version,
       int* dispatch_flags, DispatchResult* dispatch_result,
       Context** on_finish, Context* on_dispatched) {