// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab #include "librbd/io/ImageDispatchSpec.h" #include "librbd/ImageCtx.h" #include "librbd/io/AioCompletion.h" #include "librbd/io/ImageRequest.h" #include namespace librbd { namespace io { template struct ImageDispatchSpec::SendVisitor : public boost::static_visitor { ImageDispatchSpec* spec; explicit SendVisitor(ImageDispatchSpec* spec) : spec(spec) { } void operator()(Read& read) const { ImageRequest::aio_read( &spec->m_image_ctx, spec->m_aio_comp, std::move(spec->m_image_extents), std::move(read.read_result), spec->m_op_flags, spec->m_parent_trace); } void operator()(Discard& discard) const { ImageRequest::aio_discard( &spec->m_image_ctx, spec->m_aio_comp, std::move(spec->m_image_extents), discard.discard_granularity_bytes, spec->m_parent_trace); } void operator()(Write& write) const { ImageRequest::aio_write( &spec->m_image_ctx, spec->m_aio_comp, std::move(spec->m_image_extents), std::move(write.bl), spec->m_op_flags, spec->m_parent_trace); } void operator()(WriteSame& write_same) const { ImageRequest::aio_writesame( &spec->m_image_ctx, spec->m_aio_comp, std::move(spec->m_image_extents), std::move(write_same.bl), spec->m_op_flags, spec->m_parent_trace); } void operator()(CompareAndWrite& compare_and_write) const { ImageRequest::aio_compare_and_write( &spec->m_image_ctx, spec->m_aio_comp, std::move(spec->m_image_extents), std::move(compare_and_write.cmp_bl), std::move(compare_and_write.bl), compare_and_write.mismatch_offset, spec->m_op_flags, spec->m_parent_trace); } void operator()(Flush& flush) const { ImageRequest::aio_flush( &spec->m_image_ctx, spec->m_aio_comp, flush.flush_source, spec->m_parent_trace); } }; template struct ImageDispatchSpec::IsWriteOpVisitor : public boost::static_visitor { bool operator()(const Read&) const { return false; } template bool operator()(const T&) const { return true; } }; template struct ImageDispatchSpec::TokenRequestedVisitor : public boost::static_visitor { ImageDispatchSpec* spec; uint64_t flag; uint64_t *tokens; TokenRequestedVisitor(ImageDispatchSpec* spec, uint64_t _flag, uint64_t *tokens) : spec(spec), flag(_flag), tokens(tokens) { } uint64_t operator()(const Read&) const { if (flag & RBD_QOS_WRITE_MASK) { *tokens = 0; return false; } *tokens = (flag & RBD_QOS_BPS_MASK) ? spec->extents_length() : 1; return true; } uint64_t operator()(const Flush&) const { *tokens = 0; return true; } template uint64_t operator()(const T&) const { if (flag & RBD_QOS_READ_MASK) { *tokens = 0; return false; } *tokens = (flag & RBD_QOS_BPS_MASK) ? spec->extents_length() : 1; return true; } }; template void ImageDispatchSpec::send() { boost::apply_visitor(SendVisitor{this}, m_request); } template void ImageDispatchSpec::fail(int r) { m_aio_comp->get(); m_aio_comp->fail(r); } template uint64_t ImageDispatchSpec::extents_length() { uint64_t length = 0; auto &extents = this->m_image_extents; for (auto &extent : extents) { length += extent.second; } return length; } template bool ImageDispatchSpec::is_write_op() const { return boost::apply_visitor(IsWriteOpVisitor(), m_request); } template bool ImageDispatchSpec::tokens_requested(uint64_t flag, uint64_t *tokens) { return boost::apply_visitor(TokenRequestedVisitor{this, flag, tokens}, m_request); } template void ImageDispatchSpec::start_op() { m_aio_comp->start_op(); } } // namespace io } // namespace librbd template class librbd::io::ImageDispatchSpec;