// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab #ifndef CEPH_LIBRBD_IO_OBJECT_DISPATCH_SPEC_H #define CEPH_LIBRBD_IO_OBJECT_DISPATCH_SPEC_H #include "include/int_types.h" #include "include/buffer.h" #include "include/Context.h" #include "include/rados/librados.hpp" #include "common/zipkin_trace.h" #include "librbd/Types.h" #include "librbd/io/Types.h" #include namespace librbd { namespace io { struct ObjectDispatcherInterface; struct ObjectDispatchSpec { private: // helper to avoid extra heap allocation per object IO struct C_Dispatcher : public Context { ObjectDispatchSpec* object_dispatch_spec; Context* on_finish; C_Dispatcher(ObjectDispatchSpec* object_dispatch_spec, Context* on_finish) : object_dispatch_spec(object_dispatch_spec), on_finish(on_finish) { } void complete(int r) override; void finish(int r) override; }; public: struct RequestBase { uint64_t object_no; RequestBase(uint64_t object_no) : object_no(object_no) { } }; struct ReadRequest : public RequestBase { ReadExtents* extents; int read_flags; uint64_t* version; ReadRequest(uint64_t object_no, ReadExtents* extents, int read_flags, uint64_t* version) : RequestBase(object_no), extents(extents), read_flags(read_flags), version(version) { } }; struct WriteRequestBase : public RequestBase { uint64_t object_off; uint64_t journal_tid; WriteRequestBase(uint64_t object_no, uint64_t object_off, uint64_t journal_tid) : RequestBase(object_no), object_off(object_off), journal_tid(journal_tid) { } }; struct DiscardRequest : public WriteRequestBase { uint64_t object_len; int discard_flags; DiscardRequest(uint64_t object_no, uint64_t object_off, uint64_t object_len, int discard_flags, uint64_t journal_tid) : WriteRequestBase(object_no, object_off, journal_tid), object_len(object_len), discard_flags(discard_flags) { } }; struct WriteRequest : public WriteRequestBase { ceph::bufferlist data; int write_flags; std::optional assert_version; WriteRequest(uint64_t object_no, uint64_t object_off, ceph::bufferlist&& data, int write_flags, std::optional assert_version, uint64_t journal_tid) : WriteRequestBase(object_no, object_off, journal_tid), data(std::move(data)), write_flags(write_flags), assert_version(assert_version) { } }; struct WriteSameRequest : public WriteRequestBase { uint64_t object_len; LightweightBufferExtents buffer_extents; ceph::bufferlist data; WriteSameRequest(uint64_t object_no, uint64_t object_off, uint64_t object_len, LightweightBufferExtents&& buffer_extents, ceph::bufferlist&& data, uint64_t journal_tid) : WriteRequestBase(object_no, object_off, journal_tid), object_len(object_len), buffer_extents(std::move(buffer_extents)), data(std::move(data)) { } }; struct CompareAndWriteRequest : public WriteRequestBase { ceph::bufferlist cmp_data; ceph::bufferlist data; uint64_t* mismatch_offset; CompareAndWriteRequest(uint64_t object_no, uint64_t object_off, ceph::bufferlist&& cmp_data, ceph::bufferlist&& data, uint64_t* mismatch_offset, uint64_t journal_tid) : WriteRequestBase(object_no, object_off, journal_tid), cmp_data(std::move(cmp_data)), data(std::move(data)), mismatch_offset(mismatch_offset) { } }; struct FlushRequest { FlushSource flush_source; uint64_t journal_tid; FlushRequest(FlushSource flush_source, uint64_t journal_tid) : flush_source(flush_source), journal_tid(journal_tid) { } }; struct ListSnapsRequest : public RequestBase { Extents extents; SnapIds snap_ids; int list_snaps_flags; SnapshotDelta* snapshot_delta; ListSnapsRequest(uint64_t object_no, Extents&& extents, SnapIds&& snap_ids, int list_snaps_flags, SnapshotDelta* snapshot_delta) : RequestBase(object_no), extents(std::move(extents)), snap_ids(std::move(snap_ids)),list_snaps_flags(list_snaps_flags), snapshot_delta(snapshot_delta) { } }; typedef boost::variant Request; C_Dispatcher dispatcher_ctx; ObjectDispatcherInterface* object_dispatcher; ObjectDispatchLayer dispatch_layer; int object_dispatch_flags = 0; DispatchResult dispatch_result = DISPATCH_RESULT_INVALID; Request request; IOContext io_context; int op_flags; ZTracer::Trace parent_trace; template static ObjectDispatchSpec* create_read( ImageCtxT* image_ctx, ObjectDispatchLayer object_dispatch_layer, uint64_t object_no, ReadExtents* extents, IOContext io_context, int op_flags, int read_flags, const ZTracer::Trace &parent_trace, uint64_t* version, Context* on_finish) { return new ObjectDispatchSpec(image_ctx->io_object_dispatcher, object_dispatch_layer, ReadRequest{object_no, extents, read_flags, version}, io_context, op_flags, parent_trace, on_finish); } template static ObjectDispatchSpec* create_discard( ImageCtxT* image_ctx, ObjectDispatchLayer object_dispatch_layer, uint64_t object_no, uint64_t object_off, uint64_t object_len, IOContext io_context, int discard_flags, uint64_t journal_tid, const ZTracer::Trace &parent_trace, Context *on_finish) { return new ObjectDispatchSpec(image_ctx->io_object_dispatcher, object_dispatch_layer, DiscardRequest{object_no, object_off, object_len, discard_flags, journal_tid}, io_context, 0, parent_trace, on_finish); } template static ObjectDispatchSpec* create_write( ImageCtxT* image_ctx, ObjectDispatchLayer object_dispatch_layer, uint64_t object_no, uint64_t object_off, ceph::bufferlist&& data, IOContext io_context, int op_flags, int write_flags, std::optional assert_version, uint64_t journal_tid, const ZTracer::Trace &parent_trace, Context *on_finish) { return new ObjectDispatchSpec(image_ctx->io_object_dispatcher, object_dispatch_layer, WriteRequest{object_no, object_off, std::move(data), write_flags, assert_version, journal_tid}, io_context, op_flags, parent_trace, on_finish); } template static ObjectDispatchSpec* create_write_same( ImageCtxT* image_ctx, ObjectDispatchLayer object_dispatch_layer, uint64_t object_no, uint64_t object_off, uint64_t object_len, LightweightBufferExtents&& buffer_extents, ceph::bufferlist&& data, IOContext io_context, int op_flags, uint64_t journal_tid, const ZTracer::Trace &parent_trace, Context *on_finish) { return new ObjectDispatchSpec(image_ctx->io_object_dispatcher, object_dispatch_layer, WriteSameRequest{object_no, object_off, object_len, std::move(buffer_extents), std::move(data), journal_tid}, io_context, op_flags, parent_trace, on_finish); } template static ObjectDispatchSpec* create_compare_and_write( ImageCtxT* image_ctx, ObjectDispatchLayer object_dispatch_layer, uint64_t object_no, uint64_t object_off, ceph::bufferlist&& cmp_data, ceph::bufferlist&& write_data, IOContext io_context, uint64_t *mismatch_offset, int op_flags, uint64_t journal_tid, const ZTracer::Trace &parent_trace, Context *on_finish) { return new ObjectDispatchSpec(image_ctx->io_object_dispatcher, object_dispatch_layer, CompareAndWriteRequest{object_no, object_off, std::move(cmp_data), std::move(write_data), mismatch_offset, journal_tid}, io_context, op_flags, parent_trace, on_finish); } template static ObjectDispatchSpec* create_flush( ImageCtxT* image_ctx, ObjectDispatchLayer object_dispatch_layer, FlushSource flush_source, uint64_t journal_tid, const ZTracer::Trace &parent_trace, Context *on_finish) { return new ObjectDispatchSpec(image_ctx->io_object_dispatcher, object_dispatch_layer, FlushRequest{flush_source, journal_tid}, {}, 0, parent_trace, on_finish); } template static ObjectDispatchSpec* create_list_snaps( ImageCtxT* image_ctx, ObjectDispatchLayer object_dispatch_layer, uint64_t object_no, Extents&& extents, SnapIds&& snap_ids, int list_snaps_flags, const ZTracer::Trace &parent_trace, SnapshotDelta* snapshot_delta, Context* on_finish) { return new ObjectDispatchSpec(image_ctx->io_object_dispatcher, object_dispatch_layer, ListSnapsRequest{object_no, std::move(extents), std::move(snap_ids), list_snaps_flags, snapshot_delta}, {}, 0, parent_trace, on_finish); } void send(); void fail(int r); private: template friend class ObjectDispatcher; ObjectDispatchSpec(ObjectDispatcherInterface* object_dispatcher, ObjectDispatchLayer object_dispatch_layer, Request&& request, IOContext io_context, int op_flags, const ZTracer::Trace& parent_trace, Context* on_finish) : dispatcher_ctx(this, on_finish), object_dispatcher(object_dispatcher), dispatch_layer(object_dispatch_layer), request(std::move(request)), io_context(io_context), op_flags(op_flags), parent_trace(parent_trace) { } }; } // namespace io } // namespace librbd #endif // CEPH_LIBRBD_IO_OBJECT_DISPATCH_SPEC_H