]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/librbd/image/OpenRequest.cc
import 15.2.0 Octopus source
[ceph.git] / ceph / src / librbd / image / OpenRequest.cc
index 7d4625aea1c28081f157725fd26ad1723fc2ff42..88d5d62e0e5ab27a981a4f7f5a6c4d3355067119 100644 (file)
@@ -8,9 +8,12 @@
 #include "librbd/ImageCtx.h"
 #include "librbd/Utils.h"
 #include "librbd/cache/ObjectCacherObjectDispatch.h"
+#include "librbd/cache/WriteAroundObjectDispatch.h"
+#include "librbd/cache/ParentCacheObjectDispatch.cc"
 #include "librbd/image/CloseRequest.h"
 #include "librbd/image/RefreshRequest.h"
 #include "librbd/image/SetSnapRequest.h"
+#include "librbd/io/SimpleSchedulerObjectDispatch.h"
 #include <boost/algorithm/string/predicate.hpp>
 #include "include/ceph_assert.h"
 
@@ -516,35 +519,85 @@ Context *OpenRequest<I>::handle_refresh(int *result) {
     return nullptr;
   }
 
+  return send_parent_cache(result);
+}
+
+template <typename I>
+Context* OpenRequest<I>::send_parent_cache(int *result) {
+  CephContext *cct = m_image_ctx->cct;
+  ldout(cct, 10) << __func__ << ": r=" << *result << dendl;
+
+  bool parent_cache_enabled = m_image_ctx->config.template get_val<bool>(
+    "rbd_parent_cache_enabled");
+
+  if (m_image_ctx->child == nullptr || !parent_cache_enabled) {
+    return send_init_cache(result);
+  }
+
+  auto parent_cache = cache::ParentCacheObjectDispatch<I>::create(m_image_ctx);
+  using klass = OpenRequest<I>;
+  Context *ctx = create_context_callback<
+    klass, &klass::handle_parent_cache>(this);
+
+  parent_cache->init(ctx);
+  return nullptr;
+}
+
+template <typename I>
+Context* OpenRequest<I>::handle_parent_cache(int* result) {
+  CephContext *cct = m_image_ctx->cct;
+  ldout(cct, 10) << __func__ << ": r=" << *result << dendl;
+
+  if (*result < 0) {
+    lderr(cct) << "failed to parent cache " << dendl;
+    send_close_image(*result);
+    return nullptr;
+  }
+
   return send_init_cache(result);
 }
 
 template <typename I>
 Context *OpenRequest<I>::send_init_cache(int *result) {
   // cache is disabled or parent image context
-  if (!m_image_ctx->cache || m_image_ctx->child != nullptr ||
-      !m_image_ctx->data_ctx.is_valid()) {
+  if (!m_image_ctx->cache || m_image_ctx->child != nullptr) {
     return send_register_watch(result);
   }
 
   CephContext *cct = m_image_ctx->cct;
   ldout(cct, 10) << this << " " << __func__ << dendl;
 
-  auto cache = cache::ObjectCacherObjectDispatch<I>::create(m_image_ctx);
-  cache->init();
+  size_t max_dirty = m_image_ctx->config.template get_val<Option::size_t>(
+    "rbd_cache_max_dirty");
+  auto writethrough_until_flush = m_image_ctx->config.template get_val<bool>(
+    "rbd_cache_writethrough_until_flush");
+  auto cache_policy = m_image_ctx->config.template get_val<std::string>(
+    "rbd_cache_policy");
+  if (cache_policy == "writearound") {
+    auto cache = cache::WriteAroundObjectDispatch<I>::create(
+      m_image_ctx, max_dirty, writethrough_until_flush);
+    cache->init();
+  } else if (cache_policy == "writethrough" || cache_policy == "writeback") {
+    if (cache_policy == "writethrough") {
+      max_dirty = 0;
+    }
 
-  // readahead requires the cache
-  m_image_ctx->readahead.set_trigger_requests(
-    m_image_ctx->config.template get_val<uint64_t>("rbd_readahead_trigger_requests"));
-  m_image_ctx->readahead.set_max_readahead_size(
-    m_image_ctx->config.template get_val<Option::size_t>("rbd_readahead_max_bytes"));
+    auto cache = cache::ObjectCacherObjectDispatch<I>::create(
+      m_image_ctx, max_dirty, writethrough_until_flush);
+    cache->init();
 
+    // readahead requires the object cacher cache
+    m_image_ctx->readahead.set_trigger_requests(
+      m_image_ctx->config.template get_val<uint64_t>("rbd_readahead_trigger_requests"));
+    m_image_ctx->readahead.set_max_readahead_size(
+      m_image_ctx->config.template get_val<Option::size_t>("rbd_readahead_max_bytes"));
+  }
   return send_register_watch(result);
 }
 
 template <typename I>
 Context *OpenRequest<I>::send_register_watch(int *result) {
-  if (m_image_ctx->read_only) {
+  if ((m_image_ctx->read_only_flags & IMAGE_READ_ONLY_FLAG_USER) != 0U) {
     return send_set_snap(result);
   }
 
@@ -582,7 +635,7 @@ Context *OpenRequest<I>::send_set_snap(int *result) {
   if (m_image_ctx->snap_name.empty() &&
       m_image_ctx->open_snap_id == CEPH_NOSNAP) {
     *result = 0;
-    return m_on_finish;
+    return finalize(*result);
   }
 
   CephContext *cct = m_image_ctx->cct;
@@ -591,7 +644,7 @@ Context *OpenRequest<I>::send_set_snap(int *result) {
   uint64_t snap_id = CEPH_NOSNAP;
   std::swap(m_image_ctx->open_snap_id, snap_id);
   if (snap_id == CEPH_NOSNAP) {
-    RWLock::RLocker snap_locker(m_image_ctx->snap_lock);
+    std::shared_lock image_locker{m_image_ctx->image_lock};
     snap_id = m_image_ctx->get_snap_id(m_image_ctx->snap_namespace,
                                        m_image_ctx->snap_name);
   }
@@ -621,6 +674,22 @@ Context *OpenRequest<I>::handle_set_snap(int *result) {
     return nullptr;
   }
 
+  return finalize(*result);
+}
+
+template <typename I>
+Context *OpenRequest<I>::finalize(int r) {
+  if (r == 0) {
+    auto io_scheduler_cfg =
+      m_image_ctx->config.template get_val<std::string>("rbd_io_scheduler");
+
+    if (io_scheduler_cfg == "simple" && !m_image_ctx->read_only) {
+      auto io_scheduler =
+        io::SimpleSchedulerObjectDispatch<I>::create(m_image_ctx);
+      io_scheduler->init();
+    }
+  }
+
   return m_on_finish;
 }