// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab #ifndef CEPH_LIBRBD_IO_IMAGE_REQUEST_H #define CEPH_LIBRBD_IO_IMAGE_REQUEST_H #include "include/int_types.h" #include "include/buffer_fwd.h" #include "common/snap_types.h" #include "common/zipkin_trace.h" #include "osd/osd_types.h" #include "librbd/Utils.h" #include "librbd/io/Types.h" #include #include #include namespace librbd { class ImageCtx; namespace io { class AioCompletion; class ObjectDispatchSpec; class ReadResult; template class ImageRequest { public: typedef std::vector > Extents; virtual ~ImageRequest() { m_trace.event("finish"); } static void aio_read(ImageCtxT *ictx, AioCompletion *c, Extents &&image_extents, ReadResult &&read_result, int op_flags, const ZTracer::Trace &parent_trace); static void aio_write(ImageCtxT *ictx, AioCompletion *c, Extents &&image_extents, bufferlist &&bl, int op_flags, const ZTracer::Trace &parent_trace); static void aio_discard(ImageCtxT *ictx, AioCompletion *c, Extents &&image_extents, uint32_t discard_granularity_bytes, const ZTracer::Trace &parent_trace); static void aio_flush(ImageCtxT *ictx, AioCompletion *c, FlushSource flush_source, const ZTracer::Trace &parent_trace); static void aio_writesame(ImageCtxT *ictx, AioCompletion *c, Extents &&image_extents, bufferlist &&bl, int op_flags, const ZTracer::Trace &parent_trace); static void aio_compare_and_write(ImageCtxT *ictx, AioCompletion *c, Extents &&image_extents, bufferlist &&cmp_bl, bufferlist &&bl, uint64_t *mismatch_offset, int op_flags, const ZTracer::Trace &parent_trace); void send(); void set_bypass_image_cache() { m_bypass_image_cache = true; } inline const ZTracer::Trace &get_trace() const { return m_trace; } protected: typedef std::list ObjectRequests; ImageCtxT &m_image_ctx; AioCompletion *m_aio_comp; Extents m_image_extents; ZTracer::Trace m_trace; bool m_bypass_image_cache = false; ImageRequest(ImageCtxT &image_ctx, AioCompletion *aio_comp, Extents &&image_extents, const char *trace_name, const ZTracer::Trace &parent_trace) : m_image_ctx(image_ctx), m_aio_comp(aio_comp), m_image_extents(std::move(image_extents)), m_trace(util::create_trace(image_ctx, trace_name, parent_trace)) { m_trace.event("start"); } virtual int clip_request(); 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; }; template class ImageReadRequest : public ImageRequest { public: using typename ImageRequest::Extents; ImageReadRequest(ImageCtxT &image_ctx, AioCompletion *aio_comp, Extents &&image_extents, ReadResult &&read_result, int op_flags, const ZTracer::Trace &parent_trace); protected: int clip_request() override; void send_request() override; void send_image_cache_request() override; aio_type_t get_aio_type() const override { return AIO_TYPE_READ; } const char *get_request_type() const override { return "aio_read"; } private: int m_op_flags; }; template class AbstractImageWriteRequest : public ImageRequest { public: inline void flag_synchronous() { m_synchronous = true; } protected: using typename ImageRequest::ObjectRequests; using typename ImageRequest::Extents; typedef std::vector ObjectExtents; AbstractImageWriteRequest(ImageCtxT &image_ctx, AioCompletion *aio_comp, Extents &&image_extents, const char *trace_name, const ZTracer::Trace &parent_trace) : ImageRequest(image_ctx, aio_comp, std::move(image_extents), trace_name, parent_trace), m_synchronous(false) { } void send_request() override; virtual int prune_object_extents(ObjectExtents* object_extents) const { return 0; } void send_object_requests(const ObjectExtents &object_extents, const ::SnapContext &snapc, uint64_t journal_tid); virtual ObjectDispatchSpec *create_object_request( const ObjectExtent &object_extent, const ::SnapContext &snapc, uint64_t journal_tid, Context *on_finish) = 0; virtual uint64_t append_journal_event(bool synchronous) = 0; virtual void update_stats(size_t length) = 0; private: bool m_synchronous; }; template class ImageWriteRequest : public AbstractImageWriteRequest { public: using typename ImageRequest::Extents; ImageWriteRequest(ImageCtxT &image_ctx, AioCompletion *aio_comp, Extents &&image_extents, bufferlist &&bl, int op_flags, const ZTracer::Trace &parent_trace) : AbstractImageWriteRequest( image_ctx, aio_comp, std::move(image_extents), "write", parent_trace), m_bl(std::move(bl)), m_op_flags(op_flags) { } protected: using typename ImageRequest::ObjectRequests; using typename AbstractImageWriteRequest::ObjectExtents; aio_type_t get_aio_type() const override { return AIO_TYPE_WRITE; } const char *get_request_type() const override { return "aio_write"; } void assemble_extent(const ObjectExtent &object_extent, bufferlist *bl); void send_image_cache_request() override; ObjectDispatchSpec *create_object_request( const ObjectExtent &object_extent, const ::SnapContext &snapc, uint64_t journal_tid, Context *on_finish) override; uint64_t append_journal_event(bool synchronous) override; void update_stats(size_t length) override; private: bufferlist m_bl; int m_op_flags; }; template class ImageDiscardRequest : public AbstractImageWriteRequest { public: ImageDiscardRequest(ImageCtxT &image_ctx, AioCompletion *aio_comp, Extents&& image_extents, uint32_t discard_granularity_bytes, const ZTracer::Trace &parent_trace) : AbstractImageWriteRequest( image_ctx, aio_comp, std::move(image_extents), "discard", parent_trace), m_discard_granularity_bytes(discard_granularity_bytes) { } protected: using typename ImageRequest::ObjectRequests; using typename AbstractImageWriteRequest::ObjectExtents; aio_type_t get_aio_type() const override { return AIO_TYPE_DISCARD; } const char *get_request_type() const override { return "aio_discard"; } void send_image_cache_request() override; ObjectDispatchSpec *create_object_request( const ObjectExtent &object_extent, const ::SnapContext &snapc, uint64_t journal_tid, Context *on_finish) override; uint64_t append_journal_event(bool synchronous) override; void update_stats(size_t length) override; int prune_object_extents(ObjectExtents* object_extents) const override; private: uint32_t m_discard_granularity_bytes; }; template class ImageFlushRequest : public ImageRequest { public: ImageFlushRequest(ImageCtxT &image_ctx, AioCompletion *aio_comp, FlushSource flush_source, const ZTracer::Trace &parent_trace) : ImageRequest(image_ctx, aio_comp, {}, "flush", parent_trace), m_flush_source(flush_source) { } protected: using typename ImageRequest::ObjectRequests; int clip_request() override { return 0; } 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; } const char *get_request_type() const override { return "aio_flush"; } private: FlushSource m_flush_source; }; template class ImageWriteSameRequest : public AbstractImageWriteRequest { public: ImageWriteSameRequest(ImageCtxT &image_ctx, AioCompletion *aio_comp, Extents&& image_extents, bufferlist &&bl, int op_flags, const ZTracer::Trace &parent_trace) : AbstractImageWriteRequest( image_ctx, aio_comp, std::move(image_extents), "writesame", parent_trace), m_data_bl(std::move(bl)), m_op_flags(op_flags) { } protected: using typename ImageRequest::ObjectRequests; using typename AbstractImageWriteRequest::ObjectExtents; aio_type_t get_aio_type() const override { return AIO_TYPE_WRITESAME; } const char *get_request_type() const override { return "aio_writesame"; } void send_image_cache_request() override; ObjectDispatchSpec *create_object_request( const ObjectExtent &object_extent, const ::SnapContext &snapc, uint64_t journal_tid, Context *on_finish) override; uint64_t append_journal_event(bool synchronous) override; void update_stats(size_t length) override; private: bufferlist m_data_bl; int m_op_flags; }; template class ImageCompareAndWriteRequest : public AbstractImageWriteRequest { public: using typename ImageRequest::ObjectRequests; using typename AbstractImageWriteRequest::ObjectExtents; ImageCompareAndWriteRequest(ImageCtxT &image_ctx, AioCompletion *aio_comp, Extents &&image_extents, bufferlist &&cmp_bl, bufferlist &&bl, uint64_t *mismatch_offset, int op_flags, const ZTracer::Trace &parent_trace) : AbstractImageWriteRequest( image_ctx, aio_comp, std::move(image_extents), "compare_and_write", parent_trace), m_cmp_bl(std::move(cmp_bl)), m_bl(std::move(bl)), m_mismatch_offset(mismatch_offset), m_op_flags(op_flags) { } protected: void send_image_cache_request() override; void assemble_extent(const ObjectExtent &object_extent, bufferlist *bl); ObjectDispatchSpec *create_object_request( const ObjectExtent &object_extent, const ::SnapContext &snapc, uint64_t journal_tid, Context *on_finish) override; uint64_t append_journal_event(bool synchronous) override; void update_stats(size_t length) override; aio_type_t get_aio_type() const override { return AIO_TYPE_COMPARE_AND_WRITE; } const char *get_request_type() const override { return "aio_compare_and_write"; } int prune_object_extents(ObjectExtents* object_extents) const override; private: bufferlist m_cmp_bl; bufferlist m_bl; uint64_t *m_mismatch_offset; int m_op_flags; }; } // namespace io } // namespace librbd extern template class librbd::io::ImageRequest; extern template class librbd::io::ImageReadRequest; extern template class librbd::io::AbstractImageWriteRequest; extern template class librbd::io::ImageWriteRequest; extern template class librbd::io::ImageDiscardRequest; extern template class librbd::io::ImageFlushRequest; extern template class librbd::io::ImageWriteSameRequest; extern template class librbd::io::ImageCompareAndWriteRequest; #endif // CEPH_LIBRBD_IO_IMAGE_REQUEST_H