]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: introduce ImageArea and split remap_extents() into two methods
authorIlya Dryomov <idryomov@gmail.com>
Mon, 12 Sep 2022 18:24:29 +0000 (20:24 +0200)
committerIlya Dryomov <idryomov@gmail.com>
Sun, 4 Dec 2022 17:19:19 +0000 (18:19 +0100)
Since remap in either direction can really be done only once, iterating
through image dispatch layers in ImageDispatcher::remap_extents() makes
no sense.  For now, just replace the iteration with CryptoImageDispatch
lookup.

Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
13 files changed:
src/librbd/ImageCtx.cc
src/librbd/crypto/CryptoImageDispatch.cc
src/librbd/crypto/CryptoImageDispatch.h
src/librbd/io/ImageDispatchInterface.h
src/librbd/io/ImageDispatcher.cc
src/librbd/io/ImageDispatcher.h
src/librbd/io/ImageDispatcherInterface.h
src/librbd/io/Types.cc
src/librbd/io/Types.h
src/librbd/io/Utils.cc
src/librbd/io/Utils.h
src/test/librbd/crypto/test_mock_CryptoObjectDispatch.cc
src/test/librbd/mock/io/MockImageDispatcher.h

index b990d8adc76a278190d06076cdcd95b025a6876b..ab74d6a07818a368bf89d614572e312074436970 100644 (file)
@@ -36,6 +36,7 @@
 #include "librbd/io/ObjectDispatcher.h"
 #include "librbd/io/QosImageDispatch.h"
 #include "librbd/io/IoOperations.h"
+#include "librbd/io/Utils.h"
 #include "librbd/journal/StandardPolicy.h"
 #include "librbd/operation/ResizeRequest.h"
 
@@ -542,10 +543,7 @@ librados::IoCtx duplicate_io_ctx(librados::IoCtx& io_ctx) {
       return 0;
     }
 
-    io::Extents extents = {{raw_size, 0}};
-    io_image_dispatcher->remap_extents(
-            extents, io::IMAGE_EXTENTS_MAP_TYPE_PHYSICAL_TO_LOGICAL);
-    return extents.front().first;
+    return io::util::raw_to_area_offset(*this, raw_size).first;
   }
 
   uint64_t ImageCtx::get_object_count(snap_t in_snap_id) const {
index 15513bf55be364d09e3f2f21a6ecd1978020f7b8..4d4c360dc5ef9280fd82d15d67be263539788375 100644 (file)
@@ -10,18 +10,39 @@ CryptoImageDispatch::CryptoImageDispatch(
         uint64_t data_offset) : m_data_offset(data_offset) {
 }
 
-
-void CryptoImageDispatch::remap_extents(
-        io::Extents& image_extents, io::ImageExtentsMapType type) {
-  if (type == io::IMAGE_EXTENTS_MAP_TYPE_LOGICAL_TO_PHYSICAL) {
-    for (auto& extent: image_extents) {
-      extent.first += m_data_offset;
+void CryptoImageDispatch::remap_to_physical(io::Extents& image_extents,
+                                            io::ImageArea area) {
+  switch (area) {
+  case io::ImageArea::DATA:
+    for (auto& [off, _] : image_extents) {
+      off += m_data_offset;
     }
-  } else if (type == io::IMAGE_EXTENTS_MAP_TYPE_PHYSICAL_TO_LOGICAL) {
-    for (auto& extent: image_extents) {
-      extent.first -= m_data_offset;
+    break;
+  case io::ImageArea::CRYPTO_HEADER:
+    // direct mapping
+    break;
+  default:
+    ceph_abort();
+  }
+}
+
+io::ImageArea CryptoImageDispatch::remap_to_logical(
+    io::Extents& image_extents) {
+  bool saw_data = false;
+  bool saw_crypto_header = false;
+  for (auto& [off, _] : image_extents) {
+    if (off >= m_data_offset) {
+      off -= m_data_offset;
+      saw_data = true;
+    } else {
+      saw_crypto_header = true;
     }
   }
+  if (saw_crypto_header) {
+    ceph_assert(!saw_data);
+    return io::ImageArea::CRYPTO_HEADER;
+  }
+  return io::ImageArea::DATA;
 }
 
 } // namespace crypto
index dae3dac853b1dcd7ab225c1df3f61e82bad431fb..737104006af2ad054106cfc89e074b83b04395f9 100644 (file)
@@ -97,8 +97,11 @@ public:
     return false;
   }
 
-  void remap_extents(io::Extents& image_extents,
-                     io::ImageExtentsMapType type) override;
+  // called directly by ImageDispatcher
+  // TODO: hoist these out and remove CryptoImageDispatch since it's
+  // just a placeholder
+  void remap_to_physical(io::Extents& image_extents, io::ImageArea area);
+  io::ImageArea remap_to_logical(io::Extents& image_extents);
 
 private:
   uint64_t m_data_offset;
index 64cea861286d9ede047fea7e566bc61f2d89af42..205c18c474fa724b7885e522636287ab68832b57 100644 (file)
@@ -80,10 +80,6 @@ struct ImageDispatchInterface {
       Context* on_dispatched) = 0;
 
   virtual bool invalidate_cache(Context* on_finish) = 0;
-  
-  virtual void remap_extents(Extents& image_extents,
-                             ImageExtentsMapType type) {}
-
 };
 
 } // namespace io
index 413218ad3b463713b415a9e7b2d261b944e18195..2dfdc58d4990e6c29089fe591fad5211052827cd 100644 (file)
@@ -6,6 +6,7 @@
 #include "common/AsyncOpTracker.h"
 #include "common/dout.h"
 #include "librbd/ImageCtx.h"
+#include "librbd/crypto/CryptoImageDispatch.h"
 #include "librbd/io/ImageDispatch.h"
 #include "librbd/io/ImageDispatchInterface.h"
 #include "librbd/io/ImageDispatchSpec.h"
@@ -266,22 +267,29 @@ void ImageDispatcher<I>::wait_on_writes_unblocked(Context *on_unblocked) {
 }
 
 template <typename I>
-void ImageDispatcher<I>::remap_extents(Extents& image_extents,
-                                       ImageExtentsMapType type) {
-  auto loop = [&image_extents, type](auto begin, auto end) {
-      for (auto it = begin; it != end; ++it) {
-        auto& image_dispatch_meta = it->second;
-        auto image_dispatch = image_dispatch_meta.dispatch;
-        image_dispatch->remap_extents(image_extents, type);
-      }
-  };
+void ImageDispatcher<I>::remap_to_physical(Extents& image_extents,
+                                           ImageArea area) {
+  std::shared_lock locker{this->m_lock};
+  auto it = this->m_dispatches.find(IMAGE_DISPATCH_LAYER_CRYPTO);
+  if (it == this->m_dispatches.end()) {
+    ceph_assert(area == ImageArea::DATA);
+    return;
+  }
+  auto crypto_image_dispatch = static_cast<crypto::CryptoImageDispatch*>(
+      it->second.dispatch);
+  crypto_image_dispatch->remap_to_physical(image_extents, area);
+}
 
+template <typename I>
+ImageArea ImageDispatcher<I>::remap_to_logical(Extents& image_extents) {
   std::shared_lock locker{this->m_lock};
-  if (type == IMAGE_EXTENTS_MAP_TYPE_LOGICAL_TO_PHYSICAL) {
-    loop(this->m_dispatches.cbegin(), this->m_dispatches.cend());
-  } else if (type == IMAGE_EXTENTS_MAP_TYPE_PHYSICAL_TO_LOGICAL) {
-    loop(this->m_dispatches.crbegin(), this->m_dispatches.crend());
+  auto it = this->m_dispatches.find(IMAGE_DISPATCH_LAYER_CRYPTO);
+  if (it == this->m_dispatches.end()) {
+    return ImageArea::DATA;
   }
+  auto crypto_image_dispatch = static_cast<crypto::CryptoImageDispatch*>(
+      it->second.dispatch);
+  return crypto_image_dispatch->remap_to_logical(image_extents);
 }
 
 template <typename I>
index f8eeeacda57f5ea8c61cc068a044b8f7701db5a9..5d5fb053521beed4d6c9fc645e05e8c788daa495 100644 (file)
@@ -46,8 +46,8 @@ public:
   void unblock_writes() override;
   void wait_on_writes_unblocked(Context *on_unblocked) override;
 
-  void remap_extents(Extents& image_extents,
-                     ImageExtentsMapType type) override;
+  void remap_to_physical(Extents& image_extents, ImageArea area) override;
+  ImageArea remap_to_logical(Extents& image_extents) override;
 
 protected:
   bool send_dispatch(
index 9737fb3b0af2c8ff7590c99db924ea8788a5b3d5..dcff3d96acd487f9abbcdf17fcc060834177edcc 100644 (file)
@@ -30,8 +30,9 @@ public:
   virtual void wait_on_writes_unblocked(Context *on_unblocked) = 0;
 
   virtual void invalidate_cache(Context* on_finish) = 0;
-  virtual void remap_extents(Extents& image_extents,
-                             ImageExtentsMapType type) = 0;
+
+  virtual void remap_to_physical(Extents& image_extents, ImageArea area) = 0;
+  virtual ImageArea remap_to_logical(Extents& image_extents) = 0;
 };
 
 } // namespace io
index 223c7728320fee60f433c1576ec3bebe6355170a..19fcc6b8905d88b57e553d0f96b4d7213e9262f6 100644 (file)
@@ -34,5 +34,16 @@ std::ostream& operator<<(std::ostream& os, const SparseExtent& se) {
   return os;
 }
 
+std::ostream& operator<<(std::ostream& os, ImageArea area) {
+  switch (area) {
+  case ImageArea::DATA:
+    return os << "data";
+  case ImageArea::CRYPTO_HEADER:
+    return os << "crypto_header";
+  default:
+    ceph_abort();
+  }
+}
+
 } // namespace io
 } // namespace librbd
index 12fea2bb3262ee79b52971f115d4ada227ae037d..8ca9ccb1b4332777c72d7f3fa592533441e8fc08 100644 (file)
@@ -112,11 +112,6 @@ enum {
     RBD_IO_OPERATION_COMPARE_AND_WRITE)
 };
 
-enum ImageExtentsMapType {
-    IMAGE_EXTENTS_MAP_TYPE_LOGICAL_TO_PHYSICAL,
-    IMAGE_EXTENTS_MAP_TYPE_PHYSICAL_TO_LOGICAL,
-};
-
 enum ObjectDispatchLayer {
   OBJECT_DISPATCH_LAYER_NONE = 0,
   OBJECT_DISPATCH_LAYER_CACHE,
@@ -275,6 +270,13 @@ using striper::LightweightObjectExtents;
 typedef std::pair<uint64_t,uint64_t> Extent;
 typedef std::vector<Extent> Extents;
 
+enum class ImageArea {
+  DATA,
+  CRYPTO_HEADER
+};
+
+std::ostream& operator<<(std::ostream& os, ImageArea area);
+
 struct ReadExtent {
     const uint64_t offset;
     const uint64_t length;
index 2ce9dd11fc67f8cc0286c6cf74f873cb8bbc8443..5b786ff8f52fd31ec47400e9b4499915cbd7901b 100644 (file)
@@ -186,8 +186,8 @@ void file_to_extents(I* image_ctx, uint64_t offset, uint64_t length,
                      uint64_t buffer_offset,
                      striper::LightweightObjectExtents* object_extents) {
   Extents extents = {{offset, length}};
-  image_ctx->io_image_dispatcher->remap_extents(
-          extents, IMAGE_EXTENTS_MAP_TYPE_LOGICAL_TO_PHYSICAL);
+  // TODO: pass area
+  image_ctx->io_image_dispatcher->remap_to_physical(extents, ImageArea::DATA);
   for (auto [off, len] : extents) {
     Striper::file_to_extents(image_ctx->cct, &image_ctx->layout, off, len, 0,
                              buffer_offset, object_extents);
@@ -200,8 +200,24 @@ void extent_to_file(I* image_ctx, uint64_t object_no, uint64_t offset,
                     std::vector<std::pair<uint64_t, uint64_t> >& extents) {
   Striper::extent_to_file(image_ctx->cct, &image_ctx->layout, object_no,
                           offset, length, extents);
-  image_ctx->io_image_dispatcher->remap_extents(
-          extents, IMAGE_EXTENTS_MAP_TYPE_PHYSICAL_TO_LOGICAL);
+  // TODO: return area
+  image_ctx->io_image_dispatcher->remap_to_logical(extents);
+}
+
+template <typename I>
+uint64_t area_to_raw_offset(const I& image_ctx, uint64_t offset,
+                            ImageArea area) {
+  Extents extents = {{offset, 0}};
+  image_ctx.io_image_dispatcher->remap_to_physical(extents, area);
+  return extents[0].first;
+}
+
+template <typename I>
+std::pair<uint64_t, ImageArea> raw_to_area_offset(const I& image_ctx,
+                                                  uint64_t offset) {
+  Extents extents = {{offset, 0}};
+  auto area = image_ctx.io_image_dispatcher->remap_to_logical(extents);
+  return {extents[0].first, area};
 }
 
 template <typename I>
@@ -209,8 +225,7 @@ uint64_t get_file_offset(I* image_ctx, uint64_t object_no, uint64_t offset) {
   auto off = Striper::get_file_offset(image_ctx->cct, &image_ctx->layout,
                                       object_no, offset);
   Extents extents = {{off, 0}};
-  image_ctx->io_image_dispatcher->remap_extents(
-          extents, IMAGE_EXTENTS_MAP_TYPE_PHYSICAL_TO_LOGICAL);
+  image_ctx->io_image_dispatcher->remap_to_logical(extents);
   return extents[0].first;
 }
 
@@ -234,6 +249,11 @@ template void librbd::io::util::extent_to_file(
         librbd::ImageCtx *image_ctx, uint64_t object_no, uint64_t offset,
         uint64_t length,
         std::vector<std::pair<uint64_t, uint64_t> >& extents);
+template uint64_t librbd::io::util::area_to_raw_offset(
+    const librbd::ImageCtx& image_ctx, uint64_t offset, ImageArea area);
+template auto librbd::io::util::raw_to_area_offset(
+    const librbd::ImageCtx& image_ctx, uint64_t offset)
+    -> std::pair<uint64_t, ImageArea>;
 template uint64_t librbd::io::util::get_file_offset(
         librbd::ImageCtx *image_ctx, uint64_t object_no, uint64_t offset);
  
index 9f7e0b94668bad13062cfbd88119a6a7c5b3978d..21218a8eb5be4af1ef81f951d3761328705ab571 100644 (file)
@@ -64,6 +64,14 @@ void extent_to_file(ImageCtxT *image_ctx, uint64_t object_no, uint64_t offset,
                     uint64_t length,
                     std::vector<std::pair<uint64_t, uint64_t> >& extents);
 
+template <typename ImageCtxT = librbd::ImageCtx>
+uint64_t area_to_raw_offset(const ImageCtxT& image_ctx, uint64_t offset,
+                            ImageArea area);
+
+template <typename ImageCtxT = librbd::ImageCtx>
+std::pair<uint64_t, ImageArea> raw_to_area_offset(const ImageCtxT& image_ctx,
+                                                  uint64_t offset);
+
 template <typename ImageCtxT = librbd::ImageCtx>
 uint64_t get_file_offset(ImageCtxT *image_ctx, uint64_t object_no,
                          uint64_t offset);
index c0d25d62b0bdf7175738b53a77fd3991dcd29dcf..f0920f09d354d6d31a0f1538f6dc8df373a4516f 100644 (file)
@@ -224,10 +224,9 @@ struct TestMockCryptoCryptoObjectDispatch : public TestMockFixture {
             mock_image_ctx->layout.object_size));
   }
 
-  void expect_remap_extents(uint64_t offset, uint64_t length) {
-    EXPECT_CALL(*mock_image_ctx->io_image_dispatcher, remap_extents(
-            ElementsAre(Pair(offset, length)),
-            io::IMAGE_EXTENTS_MAP_TYPE_PHYSICAL_TO_LOGICAL));
+  void expect_remap_to_logical(uint64_t offset, uint64_t length) {
+    EXPECT_CALL(*mock_image_ctx->io_image_dispatcher, remap_to_logical(
+            ElementsAre(Pair(offset, length))));
   }
 
   void expect_get_parent_overlap(uint64_t overlap) {
@@ -517,7 +516,7 @@ TEST_F(TestMockCryptoCryptoObjectDispatch, UnalignedWriteCopyup) {
 
   expect_get_object_size();
   expect_get_parent_overlap(mock_image_ctx->layout.object_size);
-  expect_remap_extents(0, mock_image_ctx->layout.object_size);
+  expect_remap_to_logical(0, mock_image_ctx->layout.object_size);
   expect_prune_parent_extents(mock_image_ctx->layout.object_size);
   EXPECT_CALL(mock_exclusive_lock, is_lock_owner()).WillRepeatedly(
           Return(true));
@@ -562,7 +561,7 @@ TEST_F(TestMockCryptoCryptoObjectDispatch, UnalignedWriteEmptyCopyup) {
 
   expect_get_object_size();
   expect_get_parent_overlap(mock_image_ctx->layout.object_size);
-  expect_remap_extents(0, mock_image_ctx->layout.object_size);
+  expect_remap_to_logical(0, mock_image_ctx->layout.object_size);
   expect_prune_parent_extents(mock_image_ctx->layout.object_size);
   EXPECT_CALL(mock_exclusive_lock, is_lock_owner()).WillRepeatedly(
           Return(true));
@@ -751,12 +750,12 @@ TEST_F(TestMockCryptoCryptoObjectDispatch, PrepareCopyup) {
   expect_get_object_size();
   expect_encrypt(6);
   InSequence seq;
-  expect_remap_extents(0, 4096);
-  expect_remap_extents(4096, 4096);
-  expect_remap_extents(8192, 4096);
-  expect_remap_extents(0, 4096);
-  expect_remap_extents(4096, 8192);
-  expect_remap_extents(16384, 4096);
+  expect_remap_to_logical(0, 4096);
+  expect_remap_to_logical(4096, 4096);
+  expect_remap_to_logical(8192, 4096);
+  expect_remap_to_logical(0, 4096);
+  expect_remap_to_logical(4096, 8192);
+  expect_remap_to_logical(16384, 4096);
   ASSERT_EQ(0, mock_crypto_object_dispatch->prepare_copyup(
           0, &snapshot_sparse_bufferlist));
 
index 43ceb25265477032e7f29bccc492b75a728daad8..92cddd501f2dce4f632121d5443af7204a075b15 100644 (file)
@@ -40,7 +40,8 @@ public:
   MOCK_METHOD0(unblock_writes, void());
   MOCK_METHOD1(wait_on_writes_unblocked, void(Context*));
 
-  MOCK_METHOD2(remap_extents, void(Extents&, ImageExtentsMapType));
+  MOCK_METHOD2(remap_to_physical, void(Extents&, ImageArea));
+  MOCK_METHOD1(remap_to_logical, ImageArea(Extents&));
 };
 
 } // namespace io