rbd/cache: update RWL as ImageDispatch

This is a preparation work to make ReplicatedWriteLog as a plugin.

Signed-off-by: Li, Xiaoyan <xiaoyan.li@intel.com>
This commit is contained in:
lixiaoy1 2020-09-21 11:05:43 -04:00
parent f18ca093b6
commit 4ef11e7b73
20 changed files with 499 additions and 301 deletions

View File

@ -195,6 +195,7 @@ if(WITH_RBD_RWL)
cache/pwl/Types.cc
cache/pwl/ReplicatedWriteLog.cc
cache/pwl/AbstractWriteLog.cc
cache/pwl/ImageDispatch.cc
cache/WriteLogCache.cc)
endif()

View File

@ -57,7 +57,6 @@ namespace librbd {
template <typename> class PluginRegistry;
namespace asio { struct ContextWQ; }
namespace cache { template <typename> class ImageCache; }
namespace exclusive_lock { struct Policy; }
namespace io {
class AioCompletion;
@ -176,8 +175,6 @@ namespace librbd {
file_layout_t layout;
cache::ImageCache<ImageCtx> *image_cache = nullptr;
Readahead readahead;
std::atomic<uint64_t> total_bytes_read = {0};

View File

@ -7,6 +7,7 @@
#include "librbd/ImageCtx.h"
#include "librbd/Utils.h"
#include "librbd/io/AioCompletion.h"
#include "librbd/io/ImageDispatchSpec.h"
#include "librbd/io/ImageRequest.h"
#include "librbd/io/ReadResult.h"
@ -32,12 +33,13 @@ void ImageWriteback<I>::aio_read(Extents &&image_extents, bufferlist *bl,
ImageCtx *image_ctx = util::get_image_ctx(&m_image_ctx);
auto aio_comp = io::AioCompletion::create_and_start(
on_finish, image_ctx, io::AIO_TYPE_READ);
io::ImageReadRequest<> req(*image_ctx, aio_comp, std::move(image_extents),
io::ReadResult{bl},
image_ctx->get_data_io_context(), fadvise_flags,
0, {});
req.set_bypass_image_cache();
req.send();
ZTracer::Trace trace;
auto req = io::ImageDispatchSpec::create_read(
*image_ctx, io::IMAGE_DISPATCH_LAYER_WRITEBACK_CACHE, aio_comp,
std::move(image_extents), io::ReadResult{bl},
image_ctx->get_data_io_context(),
fadvise_flags, 0, trace);
req->send();
}
template <typename I>
@ -51,16 +53,17 @@ void ImageWriteback<I>::aio_write(Extents &&image_extents,
ImageCtx *image_ctx = util::get_image_ctx(&m_image_ctx);
auto aio_comp = io::AioCompletion::create_and_start(
on_finish, image_ctx, io::AIO_TYPE_WRITE);
io::ImageWriteRequest<> req(*image_ctx, aio_comp, std::move(image_extents),
std::move(bl), image_ctx->get_data_io_context(),
fadvise_flags, {});
req.set_bypass_image_cache();
req.send();
ZTracer::Trace trace;
auto req = io::ImageDispatchSpec::create_write(
*image_ctx, io::IMAGE_DISPATCH_LAYER_WRITEBACK_CACHE, aio_comp,
std::move(image_extents), std::move(bl),
image_ctx->get_data_io_context(), fadvise_flags, trace);
req->send();
}
template <typename I>
void ImageWriteback<I>::aio_discard(uint64_t offset, uint64_t length,
uint32_t discard_granularity_bytes,
uint32_t discard_granularity_bytes,
Context *on_finish) {
CephContext *cct = m_image_ctx.cct;
ldout(cct, 20) << "offset=" << offset << ", "
@ -70,11 +73,12 @@ void ImageWriteback<I>::aio_discard(uint64_t offset, uint64_t length,
ImageCtx *image_ctx = util::get_image_ctx(&m_image_ctx);
auto aio_comp = io::AioCompletion::create_and_start(
on_finish, image_ctx, io::AIO_TYPE_DISCARD);
io::ImageDiscardRequest<> req(*image_ctx, aio_comp, {{offset, length}},
discard_granularity_bytes,
image_ctx->get_data_io_context(), {});
req.set_bypass_image_cache();
req.send();
ZTracer::Trace trace;
auto req = io::ImageDispatchSpec::create_discard(
*image_ctx, io::IMAGE_DISPATCH_LAYER_WRITEBACK_CACHE, aio_comp, offset,
length, discard_granularity_bytes,
image_ctx->get_data_io_context(), trace);
req->send();
}
template <typename I>
@ -86,10 +90,12 @@ void ImageWriteback<I>::aio_flush(io::FlushSource flush_source,
ImageCtx *image_ctx = util::get_image_ctx(&m_image_ctx);
auto aio_comp = io::AioCompletion::create_and_start(
on_finish, image_ctx, io::AIO_TYPE_FLUSH);
io::ImageFlushRequest<> req(*image_ctx, aio_comp, flush_source,
{});
req.set_bypass_image_cache();
req.send();
ZTracer::Trace trace;
auto req = io::ImageDispatchSpec::create_flush(
*image_ctx, io::IMAGE_DISPATCH_LAYER_WRITEBACK_CACHE, aio_comp,
flush_source, trace);
req->send();
}
template <typename I>
@ -105,12 +111,12 @@ void ImageWriteback<I>::aio_writesame(uint64_t offset, uint64_t length,
ImageCtx *image_ctx = util::get_image_ctx(&m_image_ctx);
auto aio_comp = io::AioCompletion::create_and_start(
on_finish, image_ctx, io::AIO_TYPE_WRITESAME);
io::ImageWriteSameRequest<> req(*image_ctx, aio_comp, {{offset, length}},
std::move(bl),
image_ctx->get_data_io_context(),
fadvise_flags, {});
req.set_bypass_image_cache();
req.send();
ZTracer::Trace trace;
auto req = io::ImageDispatchSpec::create_write_same(
*image_ctx, io::IMAGE_DISPATCH_LAYER_WRITEBACK_CACHE, aio_comp, offset,
length, std::move(bl), image_ctx->get_data_io_context(),
fadvise_flags, trace);
req->send();
}
template <typename I>
@ -127,14 +133,13 @@ void ImageWriteback<I>::aio_compare_and_write(Extents &&image_extents,
ImageCtx *image_ctx = util::get_image_ctx(&m_image_ctx);
auto aio_comp = io::AioCompletion::create_and_start(
on_finish, image_ctx, io::AIO_TYPE_COMPARE_AND_WRITE);
io::ImageCompareAndWriteRequest<> req(*image_ctx, aio_comp,
std::move(image_extents),
std::move(cmp_bl), std::move(bl),
mismatch_offset,
image_ctx->get_data_io_context(),
fadvise_flags, {});
req.set_bypass_image_cache();
req.send();
ZTracer::Trace trace;
auto req = io::ImageDispatchSpec::create_compare_and_write(
*image_ctx, io::IMAGE_DISPATCH_LAYER_WRITEBACK_CACHE, aio_comp,
std::move(image_extents), std::move(cmp_bl), std::move(bl),
mismatch_offset, image_ctx->get_data_io_context(),
fadvise_flags, trace);
req->send();
}
} // namespace cache

View File

@ -16,9 +16,6 @@ namespace cache {
using namespace librbd::cache::pwl;
typedef WriteLogCache<ImageCtx>::Extent Extent;
typedef WriteLogCache<ImageCtx>::Extents Extents;
template <typename I>
WriteLogCache<I>::WriteLogCache(I &image_ctx, librbd::cache::pwl::ImageCacheState<I>* cache_state) {
m_write_log = new librbd::cache::pwl::ReplicatedWriteLog<I>(image_ctx, cache_state);
@ -103,4 +100,3 @@ void WriteLogCache<I>::flush(Context *on_finish) {
} // namespace librbd
template class librbd::cache::WriteLogCache<librbd::ImageCtx>;
template class librbd::cache::ImageCache<librbd::ImageCtx>;

View File

@ -5,6 +5,7 @@
#define CEPH_LIBRBD_CACHE_WRITE_LOG_CACHE
#include "librbd/cache/ImageCache.h"
#include "librbd/io/Types.h"
namespace librbd {
@ -18,10 +19,10 @@ template <typename> class ImageCacheState;
}
template <typename ImageCtxT>
class WriteLogCache : public ImageCache<ImageCtxT> {
class WriteLogCache {
public:
using typename ImageCache<ImageCtxT>::Extent;
using typename ImageCache<ImageCtxT>::Extents;
typedef io::Extent Extent;
typedef io::Extents Extents;
WriteLogCache(ImageCtxT &image_ctx, librbd::cache::pwl::ImageCacheState<ImageCtxT>* cache_state);
~WriteLogCache();
@ -30,26 +31,26 @@ public:
/// client AIO methods
void aio_read(Extents&& image_extents, ceph::bufferlist *bl,
int fadvise_flags, Context *on_finish) override;
int fadvise_flags, Context *on_finish) ;
void aio_write(Extents&& image_extents, ceph::bufferlist&& bl,
int fadvise_flags, Context *on_finish) override;
int fadvise_flags, Context *on_finish) ;
void aio_discard(uint64_t offset, uint64_t length,
uint32_t discard_granularity_bytes,
Context *on_finish) override;
void aio_flush(io::FlushSource flush_source, Context *on_finish) override;
Context *on_finish) ;
void aio_flush(io::FlushSource flush_source, Context *on_finish) ;
void aio_writesame(uint64_t offset, uint64_t length,
ceph::bufferlist&& bl,
int fadvise_flags, Context *on_finish) override;
int fadvise_flags, Context *on_finish) ;
void aio_compare_and_write(Extents&& image_extents,
ceph::bufferlist&& cmp_bl, ceph::bufferlist&& bl,
uint64_t *mismatch_offset,int fadvise_flags,
Context *on_finish) override;
Context *on_finish) ;
/// internal state methods
void init(Context *on_finish) override;
void shut_down(Context *on_finish) override;
void invalidate(Context *on_finish) override;
void flush(Context *on_finish) override;
void init(Context *on_finish) ;
void shut_down(Context *on_finish) ;
void invalidate(Context *on_finish) ;
void flush(Context *on_finish) ;
librbd::cache::pwl::AbstractWriteLog<ImageCtxT> *m_write_log;
};

View File

@ -756,6 +756,7 @@ void AbstractWriteLog<I>::shut_down(Context *on_finish) {
});
ctx = new LambdaContext(
[this, ctx](int r) {
ldout(m_image_ctx.cct, 6) << "image cache cleaned" << dendl;
Context *next_ctx = override_ctx(r, ctx);
bool periodic_stats_enabled = m_periodic_stats_enabled;
m_periodic_stats_enabled = false;
@ -2585,6 +2586,7 @@ void AbstractWriteLog<I>::internal_flush(bool invalidate, Context *on_finish) {
ctx = new LambdaContext(
[this, ctx, invalidate](int r) {
Context *next_ctx = ctx;
ldout(m_image_ctx.cct, 6) << "flush_dirty_entries finished" << dendl;
if (r < 0) {
/* Override on_finish status with this error */
next_ctx = new LambdaContext([r, ctx](int _r) {

234
src/librbd/cache/pwl/ImageDispatch.cc vendored Normal file
View File

@ -0,0 +1,234 @@
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
#include "common/dout.h"
#include "librbd/cache/pwl/ImageDispatch.h"
#include "librbd/cache/pwl/ShutdownRequest.h"
#include "librbd/cache/WriteLogCache.h"
#include "librbd/ImageCtx.h"
#include "librbd/io/AioCompletion.h"
#include "librbd/io/Utils.h"
#define dout_subsys ceph_subsys_rbd_pwl
#undef dout_prefix
#define dout_prefix *_dout << "librbd::cache::pwl::ImageDispatch: " << this << " " \
<< __func__ << ": "
namespace librbd {
namespace cache {
namespace pwl{
namespace {
void start_in_flight_io(io::AioCompletion* aio_comp) {
if (!aio_comp->async_op.started()) {
aio_comp->start_op();
}
}
} // anonymous namespace
template <typename I>
void ImageDispatch<I>::shut_down(Context* on_finish) {
ceph_assert(m_image_cache != nullptr);
Context* ctx = new LambdaContext(
[this, on_finish](int r) {
m_image_cache = nullptr;
on_finish->complete(r);
});
cache::pwl::ShutdownRequest<I> *req = cache::pwl::ShutdownRequest<I>::create(
*m_image_ctx, m_image_cache, ctx);
req->send();
}
template <typename I>
bool ImageDispatch<I>::read(
io::AioCompletion* aio_comp, io::Extents &&image_extents,
io::ReadResult &&read_result, IOContext io_context,
int op_flags, int read_flags,
const ZTracer::Trace &parent_trace, uint64_t tid,
std::atomic<uint32_t>* image_dispatch_flags,
io::DispatchResult* dispatch_result,
Context** on_finish, Context* on_dispatched) {
auto cct = m_image_ctx->cct;
ldout(cct, 20) << "image_extents=" << image_extents << dendl;
*dispatch_result = io::DISPATCH_RESULT_COMPLETE;
if (preprocess_length(aio_comp, image_extents)) {
return true;
}
start_in_flight_io(aio_comp);
aio_comp->set_request_count(1);
aio_comp->read_result = std::move(read_result);
uint64_t length = io::util::extents_length(image_extents);
aio_comp->read_result.set_clip_length(length);
auto *req_comp = new io::ReadResult::C_ImageReadRequest(
aio_comp, image_extents);
m_image_cache->aio_read(std::move(image_extents),
&req_comp->bl, op_flags,
req_comp);
return true;
}
template <typename I>
bool ImageDispatch<I>::write(
io::AioCompletion* aio_comp, io::Extents &&image_extents, bufferlist &&bl,
IOContext io_context, int op_flags, const ZTracer::Trace &parent_trace,
uint64_t tid, std::atomic<uint32_t>* image_dispatch_flags,
io::DispatchResult* dispatch_result,
Context** on_finish, Context* on_dispatched) {
auto cct = m_image_ctx->cct;
ldout(cct, 20) << "image_extents=" << image_extents << dendl;
*dispatch_result = io::DISPATCH_RESULT_COMPLETE;
if (preprocess_length(aio_comp, image_extents)) {
return true;
}
start_in_flight_io(aio_comp);
aio_comp->set_request_count(1);
io::C_AioRequest *req_comp = new io::C_AioRequest(aio_comp);
m_image_cache->aio_write(std::move(image_extents),
std::move(bl), op_flags, req_comp);
return true;
}
template <typename I>
bool ImageDispatch<I>::discard(
io::AioCompletion* aio_comp, io::Extents &&image_extents,
uint32_t discard_granularity_bytes, IOContext io_context,
const ZTracer::Trace &parent_trace,
uint64_t tid, std::atomic<uint32_t>* image_dispatch_flags,
io::DispatchResult* dispatch_result,
Context** on_finish, Context* on_dispatched) {
auto cct = m_image_ctx->cct;
ldout(cct, 20) << "image_extents=" << image_extents << dendl;
*dispatch_result = io::DISPATCH_RESULT_COMPLETE;
if (preprocess_length(aio_comp, image_extents)) {
return true;
}
start_in_flight_io(aio_comp);
aio_comp->set_request_count(image_extents.size());
for (auto &extent : image_extents) {
io::C_AioRequest *req_comp = new io::C_AioRequest(aio_comp);
m_image_cache->aio_discard(extent.first, extent.second,
discard_granularity_bytes,
req_comp);
}
return true;
}
template <typename I>
bool ImageDispatch<I>::write_same(
io::AioCompletion* aio_comp, io::Extents &&image_extents,
bufferlist &&bl, IOContext io_context,
int op_flags, const ZTracer::Trace &parent_trace, uint64_t tid,
std::atomic<uint32_t>* image_dispatch_flags,
io::DispatchResult* dispatch_result,
Context** on_finish, Context* on_dispatched) {
auto cct = m_image_ctx->cct;
ldout(cct, 20) << "image_extents=" << image_extents << dendl;
*dispatch_result = io::DISPATCH_RESULT_COMPLETE;
if (preprocess_length(aio_comp, image_extents)) {
return true;
}
start_in_flight_io(aio_comp);
aio_comp->set_request_count(image_extents.size());
for (auto &extent : image_extents) {
io::C_AioRequest *req_comp = new io::C_AioRequest(aio_comp);
m_image_cache->aio_writesame(extent.first, extent.second,
std::move(bl), op_flags,
req_comp);
}
return true;
}
template <typename I>
bool ImageDispatch<I>::compare_and_write(
io::AioCompletion* aio_comp, io::Extents &&image_extents, bufferlist &&cmp_bl,
bufferlist &&bl, uint64_t *mismatch_offset, IOContext io_context,
int op_flags, const ZTracer::Trace &parent_trace, uint64_t tid,
std::atomic<uint32_t>* image_dispatch_flags,
io::DispatchResult* dispatch_result,
Context** on_finish, Context* on_dispatched) {
auto cct = m_image_ctx->cct;
ldout(cct, 20) << "image_extents=" << image_extents << dendl;
*dispatch_result = io::DISPATCH_RESULT_COMPLETE;
if (preprocess_length(aio_comp, image_extents)) {
return true;
}
start_in_flight_io(aio_comp);
aio_comp->set_request_count(1);
io::C_AioRequest *req_comp = new io::C_AioRequest(aio_comp);
m_image_cache->aio_compare_and_write(
std::move(image_extents), std::move(cmp_bl), std::move(bl),
mismatch_offset, op_flags, req_comp);
return true;
}
template <typename I>
bool ImageDispatch<I>::flush(
io::AioCompletion* aio_comp, io::FlushSource flush_source,
const ZTracer::Trace &parent_trace, uint64_t tid,
std::atomic<uint32_t>* image_dispatch_flags,
io::DispatchResult* dispatch_result,
Context** on_finish, Context* on_dispatched) {
auto cct = m_image_ctx->cct;
ldout(cct, 20) << "tid=" << tid << dendl;
start_in_flight_io(aio_comp);
*dispatch_result = io::DISPATCH_RESULT_COMPLETE;
aio_comp->set_request_count(1);
io::C_AioRequest *req_comp = new io::C_AioRequest(aio_comp);
m_image_cache->aio_flush(flush_source, req_comp);
return true;
}
template <typename I>
bool ImageDispatch<I>::list_snaps(
io::AioCompletion* aio_comp, io::Extents&& image_extents,
io::SnapIds&& snap_ids,
int list_snaps_flags, io::SnapshotDelta* snapshot_delta,
const ZTracer::Trace &parent_trace, uint64_t tid,
std::atomic<uint32_t>* image_dispatch_flags,
io::DispatchResult* dispatch_result, Context** on_finish,
Context* on_dispatched) {
ceph_abort();
}
template <typename I>
bool ImageDispatch<I>::preprocess_length(
io::AioCompletion* aio_comp, io::Extents &image_extents) const {
auto total_bytes = io::util::extents_length(image_extents);
if (total_bytes == 0) {
aio_comp->set_request_count(0);
return true;
}
return false;
}
} // namespace pwl
} // namespace io
} // namespace librbd
template class librbd::cache::pwl::ImageDispatch<librbd::ImageCtx>;

106
src/librbd/cache/pwl/ImageDispatch.h vendored Normal file
View File

@ -0,0 +1,106 @@
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
#ifndef CEPH_LIBRBD_PWL_IMAGE_DISPATCH_H
#define CEPH_LIBRBD_PWL_IMAGE_DISPATCH_H
#include "librbd/io/ImageDispatchInterface.h"
#include "include/int_types.h"
#include "include/buffer.h"
#include "common/zipkin_trace.h"
#include "librbd/io/ReadResult.h"
#include "librbd/io/Types.h"
struct Context;
namespace librbd {
struct ImageCtx;
namespace cache {
template<typename>
class WriteLogCache;
namespace pwl {
template <typename ImageCtxT>
class ImageDispatch : public io::ImageDispatchInterface {
public:
ImageDispatch(ImageCtxT* image_ctx,
WriteLogCache<ImageCtx> *image_cache) :
m_image_ctx(image_ctx), m_image_cache(image_cache) {
}
io::ImageDispatchLayer get_dispatch_layer() const override {
return io::IMAGE_DISPATCH_LAYER_WRITEBACK_CACHE;
}
void shut_down(Context* on_finish) override;
bool read(
io::AioCompletion* aio_comp, io::Extents &&image_extents,
io::ReadResult &&read_result, IOContext io_context,
int op_flags, int read_flags,
const ZTracer::Trace &parent_trace, uint64_t tid,
std::atomic<uint32_t>* image_dispatch_flags,
io::DispatchResult* dispatch_result, Context** on_finish,
Context* on_dispatched) override;
bool write(
io::AioCompletion* aio_comp, io::Extents &&image_extents, bufferlist &&bl,
IOContext io_context, int op_flags, const ZTracer::Trace &parent_trace,
uint64_t tid, std::atomic<uint32_t>* image_dispatch_flags,
io::DispatchResult* dispatch_result,
Context** on_finish, Context* on_dispatched) override;
bool discard(
io::AioCompletion* aio_comp, io::Extents &&image_extents,
uint32_t discard_granularity_bytes, IOContext io_context,
const ZTracer::Trace &parent_trace, uint64_t tid,
std::atomic<uint32_t>* image_dispatch_flags,
io::DispatchResult* dispatch_result,
Context** on_finish, Context* on_dispatched) override;
bool write_same(
io::AioCompletion* aio_comp, io::Extents &&image_extents, bufferlist &&bl,
IOContext io_context, int op_flags, const ZTracer::Trace &parent_trace,
uint64_t tid, std::atomic<uint32_t>* image_dispatch_flags,
io::DispatchResult* dispatch_result,
Context** on_finish, Context* on_dispatched) override;
bool compare_and_write(
io::AioCompletion* aio_comp, io::Extents &&image_extents,
bufferlist &&cmp_bl,
bufferlist &&bl, uint64_t *mismatch_offset,
IOContext io_context, int op_flags,
const ZTracer::Trace &parent_trace, uint64_t tid,
std::atomic<uint32_t>* image_dispatch_flags,
io::DispatchResult* dispatch_result,
Context** on_finish, Context* on_dispatched) override;
bool flush(
io::AioCompletion* aio_comp, io::FlushSource flush_source,
const ZTracer::Trace &parent_trace, uint64_t tid,
std::atomic<uint32_t>* image_dispatch_flags,
io::DispatchResult* dispatch_result,
Context** on_finish, Context* on_dispatched) override;
bool list_snaps(
io::AioCompletion* aio_comp, io::Extents&& image_extents,
io::SnapIds&& snap_ids, int list_snaps_flags,
io::SnapshotDelta* snapshot_delta,
const ZTracer::Trace &parent_trace, uint64_t tid,
std::atomic<uint32_t>* image_dispatch_flags,
io::DispatchResult* dispatch_result, Context** on_finish,
Context* on_dispatched) override;
private:
ImageCtxT* m_image_ctx;
cache::WriteLogCache<ImageCtx> *m_image_cache;
bool preprocess_length(
io::AioCompletion* aio_comp, io::Extents &image_extents) const;
};
} // namespace pwl
} // namespace cache
} // namespace librbd
extern template class librbd::cache::pwl::ImageDispatch<librbd::ImageCtx>;
#endif // CEPH_LIBRBD_PWL_IMAGE_DISPATCH_H

View File

@ -2,6 +2,7 @@
// vim: ts=8 sw=2 smarttab
#include "librbd/cache/pwl/InitRequest.h"
#include "librbd/io/ImageDispatcher.h"
#include "librbd/Utils.h"
#include "common/dout.h"
#include "common/errno.h"
@ -9,6 +10,7 @@
#if defined(WITH_RBD_RWL)
#include "librbd/cache/pwl/ImageCacheState.h"
#include "librbd/cache/pwl/ImageDispatch.h"
#include "librbd/cache/WriteLogCache.h"
#endif // WITH_RBD_RWL
@ -75,7 +77,7 @@ void InitRequest<I>::get_image_cache_state() {
auto cache_type = cache_state->get_image_cache_type();
switch(cache_type) {
case cache::IMAGE_CACHE_TYPE_RWL:
m_image_ctx.image_cache =
m_image_cache =
new librbd::cache::WriteLogCache<I>(m_image_ctx,
cache_state);
break;
@ -98,7 +100,7 @@ void InitRequest<I>::init_image_cache() {
using klass = InitRequest<I>;
Context *ctx = create_context_callback<klass, &klass::handle_init_image_cache>(
this);
m_image_ctx.image_cache->init(ctx);
m_image_cache->init(ctx);
}
template <typename I>
@ -109,8 +111,8 @@ void InitRequest<I>::handle_init_image_cache(int r) {
if (r < 0) {
lderr(cct) << "failed to init image cache: " << cpp_strerror(r)
<< dendl;
delete m_image_ctx.image_cache;
m_image_ctx.image_cache = nullptr;
delete m_image_cache;
m_image_cache = nullptr;
save_result(r);
finish();
return;
@ -148,11 +150,47 @@ void InitRequest<I>::handle_set_feature_bit(int r) {
lderr(cct) << "failed to set feature bit: " << cpp_strerror(r)
<< dendl;
save_result(r);
} else if (m_image_ctx.discard_granularity_bytes) {
shutdown_image_cache();
}
if (m_image_ctx.discard_granularity_bytes) {
ldout(cct, 1) << "RWL image cache is enabled and "
<< "set discard_granularity_bytes = 0." << dendl;
m_image_ctx.discard_granularity_bytes = 0;
}
// Register RWL dispatch
auto image_dispatch = new cache::pwl::ImageDispatch<I>(&m_image_ctx, m_image_cache);
m_image_ctx.io_image_dispatcher->register_dispatch(image_dispatch);
finish();
}
template <typename I>
void InitRequest<I>::shutdown_image_cache() {
CephContext *cct = m_image_ctx.cct;
ldout(cct, 10) << dendl;
using klass = InitRequest<I>;
Context *ctx = create_context_callback<klass, &klass::handle_shutdown_image_cache>(
this);
m_image_cache->shut_down(ctx);
}
template <typename I>
void InitRequest<I>::handle_shutdown_image_cache(int r) {
CephContext *cct = m_image_ctx.cct;
ldout(cct, 10) << dendl;
if (r < 0) {
lderr(cct) << "failed to close image cache: " << cpp_strerror(r)
<< dendl;
}
delete m_image_cache;
m_image_cache = nullptr;
finish();
}

View File

@ -10,7 +10,13 @@ namespace librbd {
class ImageCtx;
namespace io { class ImageDispatchInterface; }
namespace cache {
template<typename>
class WriteLogCache;
namespace pwl {
template<typename>
@ -39,10 +45,10 @@ private:
* INIT_IMAGE_CACHE
* |
* v
* SET_FEATURE_BIT
* |
* v
* <finish>
* SET_FEATURE_BIT * * * > CLOSE_IMAGE_CACHE
* | |
* v |
* <finish> <-------------------/
*
* @endverbatim
*/
@ -50,6 +56,7 @@ private:
InitRequest(ImageCtxT &image_ctx, Context *on_finish);
ImageCtxT &m_image_ctx;
cache::WriteLogCache<ImageCtx> *m_image_cache;
Context *m_on_finish;
int m_error_result;
@ -64,6 +71,9 @@ private:
void set_feature_bit();
void handle_set_feature_bit(int r);
void shutdown_image_cache();
void handle_shutdown_image_cache(int r);
void finish();
void save_result(int result) {

View File

@ -2,13 +2,13 @@
// vim: ts=8 sw=2 smarttab
#include "librbd/cache/pwl/ShutdownRequest.h"
#include "librbd/cache/WriteLogCache.h"
#include "librbd/ImageCtx.h"
#include "librbd/Utils.h"
#include "common/dout.h"
#include "common/errno.h"
#include "librbd/Operations.h"
#include "librbd/asio/ContextWQ.h"
#include "librbd/cache/ImageCache.h"
#include "librbd/cache/Types.h"
@ -25,14 +25,20 @@ using librbd::util::create_async_context_callback;
using librbd::util::create_context_callback;
template <typename I>
ShutdownRequest<I>* ShutdownRequest<I>::create(I &image_ctx,
Context *on_finish) {
return new ShutdownRequest(image_ctx, on_finish);
ShutdownRequest<I>* ShutdownRequest<I>::create(
I &image_ctx,
cache::WriteLogCache<ImageCtx> *image_cache,
Context *on_finish) {
return new ShutdownRequest(image_ctx, image_cache, on_finish);
}
template <typename I>
ShutdownRequest<I>::ShutdownRequest(I &image_ctx, Context *on_finish)
ShutdownRequest<I>::ShutdownRequest(
I &image_ctx,
cache::WriteLogCache<ImageCtx> *image_cache,
Context *on_finish)
: m_image_ctx(image_ctx),
m_image_cache(image_cache),
m_on_finish(create_async_context_callback(image_ctx, on_finish)),
m_error_result(0) {
}
@ -47,7 +53,7 @@ void ShutdownRequest<I>::send_shutdown_image_cache() {
CephContext *cct = m_image_ctx.cct;
ldout(cct, 10) << dendl;
if (m_image_ctx.image_cache == nullptr) {
if (m_image_cache == nullptr) {
finish();
return;
}
@ -56,7 +62,7 @@ void ShutdownRequest<I>::send_shutdown_image_cache() {
Context *ctx = create_context_callback<klass, &klass::handle_shutdown_image_cache>(
this);
m_image_ctx.image_cache->shut_down(ctx);
m_image_cache->shut_down(ctx);
}
template <typename I>
@ -71,8 +77,8 @@ void ShutdownRequest<I>::handle_shutdown_image_cache(int r) {
finish();
return;
} else {
delete m_image_ctx.image_cache;
m_image_ctx.image_cache = nullptr;
delete m_image_cache;
m_image_cache = nullptr;
}
send_remove_feature_bit();
}

View File

@ -11,6 +11,10 @@ namespace librbd {
class ImageCtx;
namespace cache {
template<typename>
class WriteLogCache;
namespace pwl {
template<typename>
@ -19,7 +23,10 @@ class ImageCacheState;
template <typename ImageCtxT = ImageCtx>
class ShutdownRequest {
public:
static ShutdownRequest* create(ImageCtxT &image_ctx, Context *on_finish);
static ShutdownRequest* create(
ImageCtxT &image_ctx,
cache::WriteLogCache<ImageCtx> *image_cache,
Context *on_finish);
void send();
@ -47,9 +54,12 @@ private:
* @endverbatim
*/
ShutdownRequest(ImageCtxT &image_ctx, Context *on_finish);
ShutdownRequest(ImageCtxT &image_ctx,
cache::WriteLogCache<ImageCtx> *image_cache,
Context *on_finish);
ImageCtxT &m_image_ctx;
cache::WriteLogCache<ImageCtx> *m_image_cache;
Context *m_on_finish;
int m_error_result;

View File

@ -8,7 +8,6 @@
#include "common/errno.h"
#include "include/stringify.h"
#include "librbd/cache/pwl/InitRequest.h"
#include "librbd/cache/pwl/ShutdownRequest.h"
#include "librbd/ExclusiveLock.h"
#include "librbd/ImageCtx.h"
#include "librbd/ImageState.h"
@ -200,40 +199,13 @@ void PostAcquireRequest<I>::handle_open_image_cache(int r) {
if (r < 0) {
lderr(cct) << "failed to open image cache: " << cpp_strerror(r)
<< dendl;
send_close_image_cache();
send_close_journal();
return;
}
finish();
}
template <typename I>
void PostAcquireRequest<I>::send_close_image_cache() {
if (m_image_ctx.image_cache == nullptr) {
send_close_journal();
}
using klass = PostAcquireRequest<I>;
Context *ctx = create_context_callback<klass, &klass::handle_close_image_cache>(
this);
cache::pwl::ShutdownRequest<I> *req = cache::pwl::ShutdownRequest<I>::create(
m_image_ctx, ctx);
req->send();
}
template <typename I>
void PostAcquireRequest<I>::handle_close_image_cache(int r) {
CephContext *cct = m_image_ctx.cct;
ldout(cct, 10) << "r=" << r << dendl;
save_result(r);
if (r < 0) {
lderr(cct) << "failed to close image_cache: " << cpp_strerror(r) << dendl;
}
send_close_journal();
}
template <typename I>
void PostAcquireRequest<I>::send_close_journal() {
if (m_journal == nullptr) {

View File

@ -163,18 +163,12 @@ void PreReleaseRequest<I>::send_shut_down_image_cache() {
CephContext *cct = m_image_ctx.cct;
ldout(cct, 10) << dendl;
/* Shut down existing image cache whether the feature bit is on or not */
if (!m_image_ctx.image_cache) {
send_invalidate_cache();
return;
}
std::shared_lock owner_lock{m_image_ctx.owner_lock};
Context *ctx = create_async_context_callback(m_image_ctx, create_context_callback<
PreReleaseRequest<I>,
&PreReleaseRequest<I>::handle_shut_down_image_cache>(this));
cache::pwl::ShutdownRequest<I> *req = cache::pwl::ShutdownRequest<I>::create(
m_image_ctx, ctx);
req->send();
m_image_ctx.io_image_dispatcher->shut_down_dispatch(
io::IMAGE_DISPATCH_LAYER_WRITEBACK_CACHE, ctx);
}
template <typename I>

View File

@ -76,7 +76,10 @@ public:
{
std::unique_lock locker{m_lock};
auto it = m_dispatches.find(dispatch_layer);
ceph_assert(it != m_dispatches.end());
if (it == m_dispatches.end()) {
on_finish->complete(0);
return;
}
dispatch_meta = it->second;
m_dispatches.erase(it);

View File

@ -8,7 +8,6 @@
#include "librbd/Types.h"
#include "librbd/Utils.h"
#include "librbd/asio/ContextWQ.h"
#include "librbd/cache/ImageCache.h"
#include "librbd/io/AioCompletion.h"
#include "librbd/io/AsyncOperation.h"
#include "librbd/io/ObjectDispatchInterface.h"
@ -313,12 +312,8 @@ void ImageRequest<I>::send() {
ldout(cct, 20) << get_request_type() << ": ictx=" << &image_ctx << ", "
<< "completion=" << aio_comp << dendl;
if (m_bypass_image_cache || m_image_ctx.image_cache == nullptr) {
update_timestamp();
send_request();
} else {
send_image_cache_request();
}
update_timestamp();
send_request();
}
template <typename I>
@ -434,21 +429,6 @@ void ImageReadRequest<I>::send_request() {
image_ctx.perfcounter->inc(l_librbd_rd_bytes, buffer_ofs);
}
template <typename I>
void ImageReadRequest<I>::send_image_cache_request() {
I &image_ctx = this->m_image_ctx;
ceph_assert(image_ctx.image_cache != nullptr);
AioCompletion *aio_comp = this->m_aio_comp;
aio_comp->set_request_count(1);
auto *req_comp = new io::ReadResult::C_ImageReadRequest(
aio_comp, this->m_image_extents);
image_ctx.image_cache->aio_read(std::move(this->m_image_extents),
&req_comp->bl, m_op_flags,
req_comp);
}
template <typename I>
void AbstractImageWriteRequest<I>::send_request() {
I &image_ctx = this->m_image_ctx;
@ -549,18 +529,6 @@ uint64_t ImageWriteRequest<I>::append_journal_event(bool synchronous) {
return tid;
}
template <typename I>
void ImageWriteRequest<I>::send_image_cache_request() {
I &image_ctx = this->m_image_ctx;
ceph_assert(image_ctx.image_cache != nullptr);
AioCompletion *aio_comp = this->m_aio_comp;
aio_comp->set_request_count(1);
C_AioRequest *req_comp = new C_AioRequest(aio_comp);
image_ctx.image_cache->aio_write(std::move(this->m_image_extents),
std::move(m_bl), m_op_flags, req_comp);
}
template <typename I>
ObjectDispatchSpec *ImageWriteRequest<I>::create_object_request(
const LightweightObjectExtent &object_extent, IOContext io_context,
@ -608,21 +576,6 @@ uint64_t ImageDiscardRequest<I>::append_journal_event(bool synchronous) {
return tid;
}
template <typename I>
void ImageDiscardRequest<I>::send_image_cache_request() {
I &image_ctx = this->m_image_ctx;
ceph_assert(image_ctx.image_cache != nullptr);
AioCompletion *aio_comp = this->m_aio_comp;
aio_comp->set_request_count(this->m_image_extents.size());
for (auto &extent : this->m_image_extents) {
C_AioRequest *req_comp = new C_AioRequest(aio_comp);
image_ctx.image_cache->aio_discard(extent.first, extent.second,
this->m_discard_granularity_bytes,
req_comp);
}
}
template <typename I>
ObjectDispatchSpec *ImageDiscardRequest<I>::create_object_request(
const LightweightObjectExtent &object_extent, IOContext io_context,
@ -744,17 +697,6 @@ void ImageFlushRequest<I>::send_request() {
}
}
template <typename I>
void ImageFlushRequest<I>::send_image_cache_request() {
I &image_ctx = this->m_image_ctx;
ceph_assert(image_ctx.image_cache != nullptr);
AioCompletion *aio_comp = this->m_aio_comp;
aio_comp->set_request_count(1);
C_AioRequest *req_comp = new C_AioRequest(aio_comp);
image_ctx.image_cache->aio_flush(m_flush_source, req_comp);
}
template <typename I>
uint64_t ImageWriteSameRequest<I>::append_journal_event(bool synchronous) {
I &image_ctx = this->m_image_ctx;
@ -773,21 +715,6 @@ uint64_t ImageWriteSameRequest<I>::append_journal_event(bool synchronous) {
return tid;
}
template <typename I>
void ImageWriteSameRequest<I>::send_image_cache_request() {
I &image_ctx = this->m_image_ctx;
ceph_assert(image_ctx.image_cache != nullptr);
AioCompletion *aio_comp = this->m_aio_comp;
aio_comp->set_request_count(this->m_image_extents.size());
for (auto &extent : this->m_image_extents) {
C_AioRequest *req_comp = new C_AioRequest(aio_comp);
image_ctx.image_cache->aio_writesame(extent.first, extent.second,
std::move(m_data_bl), m_op_flags,
req_comp);
}
}
template <typename I>
ObjectDispatchSpec *ImageWriteSameRequest<I>::create_object_request(
const LightweightObjectExtent &object_extent, IOContext io_context,
@ -850,19 +777,6 @@ void ImageCompareAndWriteRequest<I>::assemble_extent(
}
}
template <typename I>
void ImageCompareAndWriteRequest<I>::send_image_cache_request() {
I &image_ctx = this->m_image_ctx;
ceph_assert(image_ctx.image_cache != nullptr);
AioCompletion *aio_comp = this->m_aio_comp;
aio_comp->set_request_count(1);
C_AioRequest *req_comp = new C_AioRequest(aio_comp);
image_ctx.image_cache->aio_compare_and_write(
std::move(this->m_image_extents), std::move(m_cmp_bl), std::move(m_bl),
m_mismatch_offset, m_op_flags, req_comp);
}
template <typename I>
ObjectDispatchSpec *ImageCompareAndWriteRequest<I>::create_object_request(
const LightweightObjectExtent &object_extent, IOContext io_context,

View File

@ -63,10 +63,6 @@ public:
void send();
void set_bypass_image_cache() {
m_bypass_image_cache = true;
}
inline const ZTracer::Trace &get_trace() const {
return m_trace;
}
@ -79,7 +75,6 @@ protected:
Extents m_image_extents;
IOContext m_io_context;
ZTracer::Trace m_trace;
bool m_bypass_image_cache = false;
ImageRequest(ImageCtxT &image_ctx, AioCompletion *aio_comp,
Extents &&image_extents, IOContext io_context,
@ -93,7 +88,6 @@ protected:
virtual void update_timestamp();
virtual void send_request() = 0;
virtual void send_image_cache_request() = 0;
virtual aio_type_t get_aio_type() const = 0;
virtual const char *get_request_type() const = 0;
@ -111,7 +105,6 @@ public:
protected:
void send_request() override;
void send_image_cache_request() override;
aio_type_t get_aio_type() const override {
return AIO_TYPE_READ;
@ -192,9 +185,6 @@ protected:
void assemble_extent(const LightweightObjectExtent &object_extent,
bufferlist *bl);
void send_image_cache_request() override;
ObjectDispatchSpec *create_object_request(
const LightweightObjectExtent &object_extent, IOContext io_context,
uint64_t journal_tid, bool single_extent, Context *on_finish) override;
@ -230,8 +220,6 @@ protected:
return "aio_discard";
}
void send_image_cache_request() override;
ObjectDispatchSpec *create_object_request(
const LightweightObjectExtent &object_extent, IOContext io_context,
uint64_t journal_tid, bool single_extent, Context *on_finish) override;
@ -263,7 +251,6 @@ protected:
void update_timestamp() override {
}
void send_request() override;
void send_image_cache_request() override;
aio_type_t get_aio_type() const override {
return AIO_TYPE_FLUSH;
@ -300,8 +287,6 @@ protected:
return "aio_writesame";
}
void send_image_cache_request() override;
ObjectDispatchSpec *create_object_request(
const LightweightObjectExtent &object_extent, IOContext io_context,
uint64_t journal_tid, bool single_extent, Context *on_finish) override;
@ -331,8 +316,6 @@ public:
}
protected:
void send_image_cache_request() override;
void assemble_extent(const LightweightObjectExtent &object_extent,
bufferlist *bl);

View File

@ -12,7 +12,6 @@
#include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
#include "test/librados_test_stub/MockTestMemRadosClient.h"
#include "librbd/cache/pwl/InitRequest.h"
#include "librbd/cache/pwl/ShutdownRequest.h"
#include "librbd/exclusive_lock/PostAcquireRequest.h"
#include "librbd/image/RefreshRequest.h"
@ -85,26 +84,6 @@ struct InitRequest<librbd::MockTestImageCtx> {
InitRequest<librbd::MockTestImageCtx> *InitRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
template<>
struct ShutdownRequest<librbd::MockTestImageCtx> {
static ShutdownRequest *s_instance;
Context *on_finish = nullptr;
static ShutdownRequest *create(librbd::MockTestImageCtx &image_ctx,
Context *on_finish) {
ceph_assert(s_instance != nullptr);
s_instance->on_finish = on_finish;
return s_instance;
}
ShutdownRequest() {
s_instance = this;
}
MOCK_METHOD0(send, void());
};
ShutdownRequest<librbd::MockTestImageCtx> *ShutdownRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
} // namespace pwl
} // namespace cache
} // namespace librbd
@ -139,7 +118,6 @@ public:
typedef PostAcquireRequest<MockTestImageCtx> MockPostAcquireRequest;
typedef librbd::image::RefreshRequest<MockTestImageCtx> MockRefreshRequest;
typedef librbd::cache::pwl::InitRequest<MockTestImageCtx> MockInitRequest;
typedef librbd::cache::pwl::ShutdownRequest<MockTestImageCtx> MockShutdownRequest;
void expect_test_features(MockTestImageCtx &mock_image_ctx, uint64_t features,
bool enabled) {
@ -230,12 +208,6 @@ public:
.WillOnce(FinishRequest(&mock_init_request, r, &mock_image_ctx));
}
void expect_close_image_cache(MockTestImageCtx &mock_image_ctx,
MockShutdownRequest &mock_shutdown_request, int r) {
EXPECT_CALL(mock_shutdown_request, send())
.WillOnce(FinishRequest(&mock_shutdown_request, r, &mock_image_ctx));
}
};
TEST_F(TestMockExclusiveLockPostAcquireRequest, Success) {
@ -552,11 +524,6 @@ TEST_F(TestMockExclusiveLockPostAcquireRequest, InitImageCacheError) {
MockInitRequest mock_init_request;
expect_init_image_cache(mock_image_ctx, mock_init_request, -ENOENT);
cache::MockImageCache mock_image_cache;
mock_image_ctx.image_cache = &mock_image_cache;
MockShutdownRequest mock_shutdown_request;
expect_close_image_cache(mock_image_ctx, mock_shutdown_request, 0);
expect_close_journal(mock_image_ctx, mock_journal);
expect_close_object_map(mock_image_ctx, mock_object_map);

View File

@ -1,7 +1,6 @@
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
#include "librbd/cache/pwl/ShutdownRequest.h"
#include "test/librbd/test_mock_fixture.h"
#include "test/librbd/test_support.h"
#include "test/librbd/mock/cache/MockImageCache.h"
@ -40,31 +39,6 @@ struct ImageDispatch<MockTestImageCtx> {
} // namespace exclusive_lock
namespace cache {
namespace pwl {
template<>
struct ShutdownRequest<librbd::MockTestImageCtx> {
static ShutdownRequest *s_instance;
Context *on_finish = nullptr;
static ShutdownRequest *create(librbd::MockTestImageCtx &image_ctx,
Context *on_finish) {
ceph_assert(s_instance != nullptr);
s_instance->on_finish = on_finish;
return s_instance;
}
ShutdownRequest() {
s_instance = this;
}
MOCK_METHOD0(send, void());
};
ShutdownRequest<librbd::MockTestImageCtx> *ShutdownRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
} // namespace pwl
} // namespace cache
namespace util {
inline ImageCtx* get_image_ctx(MockTestImageCtx* image_ctx) {
@ -102,7 +76,6 @@ class TestMockExclusiveLockPreReleaseRequest : public TestMockFixture {
public:
typedef ImageDispatch<MockTestImageCtx> MockImageDispatch;
typedef PreReleaseRequest<MockTestImageCtx> MockPreReleaseRequest;
typedef librbd::cache::pwl::ShutdownRequest<MockTestImageCtx> MockShutdownRequest;
void expect_complete_context(MockContext &mock_context, int r) {
EXPECT_CALL(mock_context, complete(r));
@ -159,10 +132,11 @@ public:
.WillOnce(CompleteContext(0, mock_image_ctx.image_ctx->op_work_queue));
}
void expect_close_image_cache(MockTestImageCtx &mock_image_ctx,
MockShutdownRequest &mock_shutdown_req, int r) {
EXPECT_CALL(mock_shutdown_req, send())
.WillOnce(FinishRequest(&mock_shutdown_req, r, &mock_image_ctx));
void expect_close_image_cache(MockTestImageCtx &mock_image_ctx, int r) {
EXPECT_CALL(*mock_image_ctx.io_image_dispatcher,
shut_down_dispatch(io::IMAGE_DISPATCH_LAYER_WRITEBACK_CACHE, _))
.WillOnce(WithArg<1>(
CompleteContext(0, mock_image_ctx.image_ctx->op_work_queue)));
}
void expect_invalidate_cache(MockTestImageCtx &mock_image_ctx,
@ -227,10 +201,7 @@ TEST_F(TestMockExclusiveLockPreReleaseRequest, Success) {
expect_prepare_lock(mock_image_ctx);
cache::MockImageCache mock_image_cache;
mock_image_ctx.image_cache = &mock_image_cache;
MockShutdownRequest mock_shutdown_request;
expect_close_image_cache(mock_image_ctx, mock_shutdown_request, 0);
expect_close_image_cache(mock_image_ctx, 0);
expect_invalidate_cache(mock_image_ctx, 0);
@ -271,10 +242,7 @@ TEST_F(TestMockExclusiveLockPreReleaseRequest, SuccessJournalDisabled) {
expect_cancel_op_requests(mock_image_ctx, 0);
expect_prepare_lock(mock_image_ctx);
cache::MockImageCache mock_image_cache;
mock_image_ctx.image_cache = &mock_image_cache;
MockShutdownRequest mock_shutdown_request;
expect_close_image_cache(mock_image_ctx, mock_shutdown_request, 0);
expect_close_image_cache(mock_image_ctx, 0);
expect_invalidate_cache(mock_image_ctx, 0);
@ -310,10 +278,7 @@ TEST_F(TestMockExclusiveLockPreReleaseRequest, SuccessObjectMapDisabled) {
InSequence seq;
expect_cancel_op_requests(mock_image_ctx, 0);
cache::MockImageCache mock_image_cache;
mock_image_ctx.image_cache = &mock_image_cache;
MockShutdownRequest mock_shutdown_request;
expect_close_image_cache(mock_image_ctx, mock_shutdown_request, 0);
expect_close_image_cache(mock_image_ctx, 0);
expect_invalidate_cache(mock_image_ctx, 0);
@ -345,10 +310,7 @@ TEST_F(TestMockExclusiveLockPreReleaseRequest, Blocklisted) {
-EBLOCKLISTED);
expect_prepare_lock(mock_image_ctx);
cache::MockImageCache mock_image_cache;
mock_image_ctx.image_cache = &mock_image_cache;
MockShutdownRequest mock_shutdown_request;
expect_close_image_cache(mock_image_ctx, mock_shutdown_request, 0);
expect_close_image_cache(mock_image_ctx, 0);
expect_invalidate_cache(mock_image_ctx, -EBLOCKLISTED);

View File

@ -26,7 +26,6 @@ class MockSafeTimer;
namespace librbd {
namespace cache { class MockImageCache; }
namespace operation {
template <typename> class ResizeRequest;
}
@ -295,8 +294,6 @@ struct MockImageCtx {
io::MockObjectDispatcher *io_object_dispatcher;
MockContextWQ *op_work_queue;
cache::MockImageCache *image_cache = nullptr;
MockReadahead readahead;
uint64_t readahead_max_bytes;