Add invalidate_cache in ImageDispatch and ImageDispatcher.
Signed-off-by: Li, Xiaoyan <xiaoyan.li@intel.com>
return false;
}
-
template <typename I>
bool WriteLogImageDispatch<I>::preprocess_length(
io::AioCompletion* aio_comp, io::Extents &image_extents) const {
return false;
}
+template <typename I>
+bool WriteLogImageDispatch<I>::invalidate_cache(Context* on_finish) {
+ m_image_cache->invalidate(on_finish);
+ return true;
+}
+
} // namespace io
} // namespace librbd
io::DispatchResult* dispatch_result, Context** on_finish,
Context* on_dispatched) override;
+ bool invalidate_cache(Context* on_finish) override;
+
private:
ImageCtxT* m_image_ctx;
pwl::AbstractWriteLog<ImageCtx> *m_image_cache;
return false;
}
+ bool invalidate_cache(Context* on_finish) override {
+ return false;
+ }
+
private:
typedef std::list<Context*> Contexts;
typedef std::unordered_set<uint64_t> Tids;
#include "common/dout.h"
#include "common/AsyncOpTracker.h"
#include "librbd/Utils.h"
+#include "librbd/io/DispatcherInterface.h"
#include "librbd/io/Types.h"
#include <map>
: m_image_ctx(image_ctx),
m_lock(ceph::make_shared_mutex(
librbd::util::unique_lock_name("librbd::io::Dispatcher::lock",
- this))) {
+ this))) {
}
virtual ~Dispatcher() {
virtual bool send_dispatch(Dispatch* dispatch,
DispatchSpec* dispatch_spec) = 0;
+protected:
+ struct C_LayerIterator : public Context {
+ Dispatcher* dispatcher;
+ Context* on_finish;
+ DispatchLayer dispatch_layer;
+
+ C_LayerIterator(Dispatcher* dispatcher,
+ DispatchLayer start_layer,
+ Context* on_finish)
+ : dispatcher(dispatcher), on_finish(on_finish), dispatch_layer(start_layer) {
+ }
+
+ void complete(int r) override {
+ while (true) {
+ dispatcher->m_lock.lock_shared();
+ auto it = dispatcher->m_dispatches.upper_bound(dispatch_layer);
+ if (it == dispatcher->m_dispatches.end()) {
+ dispatcher->m_lock.unlock_shared();
+ Context::complete(r);
+ return;
+ }
+
+ auto& dispatch_meta = it->second;
+ auto dispatch = dispatch_meta.dispatch;
+
+ // prevent recursive locking back into the dispatcher while handling IO
+ dispatch_meta.async_op_tracker->start_op();
+ dispatcher->m_lock.unlock_shared();
+
+ // next loop should start after current layer
+ dispatch_layer = dispatch->get_dispatch_layer();
+
+ auto handled = execute(dispatch, this);
+ dispatch_meta.async_op_tracker->finish_op();
+
+ if (handled) {
+ break;
+ }
+ }
+ }
+
+ void finish(int r) override {
+ on_finish->complete(0);
+ }
+ virtual bool execute(Dispatch* dispatch,
+ Context* on_finish) = 0;
+ };
+
+ struct C_InvalidateCache : public C_LayerIterator {
+ C_InvalidateCache(Dispatcher* dispatcher, DispatchLayer start_layer, Context* on_finish)
+ : C_LayerIterator(dispatcher, start_layer, on_finish) {
+ }
+
+ bool execute(Dispatch* dispatch,
+ Context* on_finish) override {
+ return dispatch->invalidate_cache(on_finish);
+ }
+ };
+
private:
void shut_down_dispatch(DispatchMeta& dispatch_meta,
Context** on_finish) {
#include "librbd/ImageCtx.h"
#include "librbd/io/AioCompletion.h"
#include "librbd/io/ImageRequest.h"
+#include "librbd/io/ObjectDispatcherInterface.h"
#define dout_subsys ceph_subsys_rbd
#undef dout_prefix
return true;
}
+template <typename I>
+bool ImageDispatch<I>::invalidate_cache(Context* on_finish) {
+ auto cct = m_image_ctx->cct;
+ ldout(cct, 20) << dendl;
+
+ std::shared_lock owner_lock{m_image_ctx->owner_lock};
+ m_image_ctx->io_object_dispatcher->invalidate_cache(on_finish);
+ return true;
+}
+
} // namespace io
} // namespace librbd
DispatchResult* dispatch_result, Context** on_finish,
Context* on_dispatched) override;
+ bool invalidate_cache(Context* on_finish) override;
+
private:
ImageCtxT* m_image_ctx;
DispatchResult* dispatch_result, Context** on_finish,
Context* on_dispatched) = 0;
+ virtual bool invalidate_cache(Context* on_finish) = 0;
};
} // namespace io
#include "common/AsyncOpTracker.h"
#include "common/dout.h"
#include "librbd/ImageCtx.h"
-#include "librbd/Utils.h"
-#include "librbd/io/AsyncOperation.h"
#include "librbd/io/ImageDispatch.h"
#include "librbd/io/ImageDispatchInterface.h"
#include "librbd/io/ImageDispatchSpec.h"
this->register_dispatch(m_write_block_dispatch);
}
+template <typename I>
+void ImageDispatcher<I>::invalidate_cache(Context* on_finish) {
+ auto image_ctx = this->m_image_ctx;
+ auto cct = image_ctx->cct;
+ ldout(cct, 5) << dendl;
+
+ auto ctx = new C_InvalidateCache(
+ this, IMAGE_DISPATCH_LAYER_NONE, on_finish);
+ ctx->complete(0);
+}
+
template <typename I>
void ImageDispatcher<I>::shut_down(Context* on_finish) {
// TODO ensure all IOs are executed via a dispatcher
public:
ImageDispatcher(ImageCtxT* image_ctx);
+ void invalidate_cache(Context* on_finish) override;
+
void shut_down(Context* on_finish) override;
void apply_qos_schedule_tick_min(uint64_t tick) override;
struct SendVisitor;
struct PreprocessVisitor;
+ using typename Dispatcher<ImageCtxT, ImageDispatcherInterface>::C_InvalidateCache;
+
std::atomic<uint64_t> m_next_tid{0};
QosImageDispatch<ImageCtxT>* m_qos_image_dispatch = nullptr;
virtual void unblock_writes() = 0;
virtual void wait_on_writes_unblocked(Context *on_unblocked) = 0;
+
+ virtual void invalidate_cache(Context* on_finish) = 0;
};
} // namespace io
namespace librbd {
namespace io {
-template <typename I>
-struct ObjectDispatcher<I>::C_LayerIterator : public Context {
- ObjectDispatcher* object_dispatcher;
- Context* on_finish;
-
- ObjectDispatchLayer object_dispatch_layer = OBJECT_DISPATCH_LAYER_NONE;
-
- C_LayerIterator(ObjectDispatcher* object_dispatcher,
- Context* on_finish)
- : object_dispatcher(object_dispatcher), on_finish(on_finish) {
- }
-
- void complete(int r) override {
- while (true) {
- object_dispatcher->m_lock.lock_shared();
- auto it = object_dispatcher->m_dispatches.upper_bound(
- object_dispatch_layer);
- if (it == object_dispatcher->m_dispatches.end()) {
- object_dispatcher->m_lock.unlock_shared();
- Context::complete(r);
- return;
- }
-
- auto& object_dispatch_meta = it->second;
- auto object_dispatch = object_dispatch_meta.dispatch;
-
- // prevent recursive locking back into the dispatcher while handling IO
- object_dispatch_meta.async_op_tracker->start_op();
- object_dispatcher->m_lock.unlock_shared();
-
- // next loop should start after current layer
- object_dispatch_layer = object_dispatch->get_dispatch_layer();
-
- auto handled = execute(object_dispatch, this);
- object_dispatch_meta.async_op_tracker->finish_op();
-
- if (handled) {
- break;
- }
- }
- }
-
- void finish(int r) override {
- on_finish->complete(0);
- }
-
- virtual bool execute(ObjectDispatchInterface* object_dispatch,
- Context* on_finish) = 0;
-};
-
-template <typename I>
-struct ObjectDispatcher<I>::C_InvalidateCache : public C_LayerIterator {
- C_InvalidateCache(ObjectDispatcher* object_dispatcher, Context* on_finish)
- : C_LayerIterator(object_dispatcher, on_finish) {
- }
-
- bool execute(ObjectDispatchInterface* object_dispatch,
- Context* on_finish) override {
- return object_dispatch->invalidate_cache(on_finish);
- }
-};
-
template <typename I>
struct ObjectDispatcher<I>::C_ResetExistenceCache : public C_LayerIterator {
C_ResetExistenceCache(ObjectDispatcher* object_dispatcher, Context* on_finish)
- : C_LayerIterator(object_dispatcher, on_finish) {
+ : C_LayerIterator(object_dispatcher, OBJECT_DISPATCH_LAYER_NONE, on_finish) {
}
bool execute(ObjectDispatchInterface* object_dispatch,
ldout(cct, 5) << dendl;
on_finish = util::create_async_context_callback(*image_ctx, on_finish);
- auto ctx = new C_InvalidateCache(this, on_finish);
+ auto ctx = new C_InvalidateCache(
+ this, OBJECT_DISPATCH_LAYER_NONE, on_finish);
ctx->complete(0);
}
uint64_t object_no,
SnapshotSparseBufferlist* snapshot_sparse_bufferlist) override;
+ using typename Dispatcher<ImageCtxT, ObjectDispatcherInterface>::C_LayerIterator;
+
+ using typename Dispatcher<ImageCtxT, ObjectDispatcherInterface>::C_InvalidateCache;
+
protected:
bool send_dispatch(ObjectDispatchInterface* object_dispatch,
ObjectDispatchSpec* object_dispatch_spec) override;
private:
- struct C_LayerIterator;
- struct C_InvalidateCache;
struct C_ResetExistenceCache;
struct SendVisitor;
return false;
}
+ bool invalidate_cache(Context* on_finish) override {
+ return false;
+ }
+
private:
ImageCtxT* m_image_ctx;
return false;
}
+ bool invalidate_cache(Context* on_finish) override {
+ return false;
+ }
+
private:
ImageCtxT* m_image_ctx;
return false;
}
+ bool invalidate_cache(Context* on_finish) override {
+ return false;
+ }
+
private:
ImageCtxT* m_image_ctx;
Context** on_finish, Context* on_dispatched);
void flush_io(Context* on_finish);
+ bool invalidate_cache(Context* on_finish) override {
+ return false;
+ }
+
void handle_blocked_writes(int r);
};
io::DispatchResult* dispatch_result, Context** on_finish,
Context* on_dispatched) override;
+ bool invalidate_cache(Context* on_finish) override {
+ return false;
+ }
+
private:
ImageCtxT* m_image_ctx;
std::unique_ptr<FormatInterface> m_format;
return false;
}
+ bool invalidate_cache(Context* on_finish) override {
+ return false;
+ }
+
};
} // namespace io
MOCK_METHOD1(register_dispatch, void(ImageDispatchInterface*));
MOCK_METHOD2(shut_down_dispatch, void(ImageDispatchLayer, Context*));
+ MOCK_METHOD1(invalidate_cache, void(Context *));
MOCK_METHOD1(send, void(ImageDispatchSpec*));
MOCK_METHOD3(finish, void(int r, ImageDispatchLayer, uint64_t));