#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"
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);
}
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;
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);
}
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;
}