1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include "librbd/io/ImageDispatchSpec.h"
5 #include "librbd/ImageCtx.h"
6 #include "librbd/io/AioCompletion.h"
7 #include "librbd/io/ImageRequest.h"
8 #include <boost/variant.hpp>
14 struct ImageDispatchSpec
<I
>::SendVisitor
15 : public boost::static_visitor
<void> {
16 ImageDispatchSpec
* spec
;
18 explicit SendVisitor(ImageDispatchSpec
* spec
)
22 void operator()(Read
& read
) const {
23 ImageRequest
<I
>::aio_read(
24 &spec
->m_image_ctx
, spec
->m_aio_comp
, std::move(spec
->m_image_extents
),
25 std::move(read
.read_result
), spec
->m_op_flags
, spec
->m_parent_trace
);
28 void operator()(Discard
& discard
) const {
29 ImageRequest
<I
>::aio_discard(
30 &spec
->m_image_ctx
, spec
->m_aio_comp
, std::move(spec
->m_image_extents
),
31 discard
.discard_granularity_bytes
, spec
->m_parent_trace
);
34 void operator()(Write
& write
) const {
35 ImageRequest
<I
>::aio_write(
36 &spec
->m_image_ctx
, spec
->m_aio_comp
, std::move(spec
->m_image_extents
),
37 std::move(write
.bl
), spec
->m_op_flags
, spec
->m_parent_trace
);
40 void operator()(WriteSame
& write_same
) const {
41 ImageRequest
<I
>::aio_writesame(
42 &spec
->m_image_ctx
, spec
->m_aio_comp
, std::move(spec
->m_image_extents
),
43 std::move(write_same
.bl
), spec
->m_op_flags
, spec
->m_parent_trace
);
46 void operator()(CompareAndWrite
& compare_and_write
) const {
47 ImageRequest
<I
>::aio_compare_and_write(
48 &spec
->m_image_ctx
, spec
->m_aio_comp
, std::move(spec
->m_image_extents
),
49 std::move(compare_and_write
.cmp_bl
), std::move(compare_and_write
.bl
),
50 compare_and_write
.mismatch_offset
, spec
->m_op_flags
,
51 spec
->m_parent_trace
);
54 void operator()(Flush
& flush
) const {
55 ImageRequest
<I
>::aio_flush(
56 &spec
->m_image_ctx
, spec
->m_aio_comp
, flush
.flush_source
,
57 spec
->m_parent_trace
);
62 struct ImageDispatchSpec
<I
>::IsWriteOpVisitor
63 : public boost::static_visitor
<bool> {
64 bool operator()(const Read
&) const {
69 bool operator()(const T
&) const {
75 struct ImageDispatchSpec
<I
>::TokenRequestedVisitor
76 : public boost::static_visitor
<uint64_t> {
77 ImageDispatchSpec
* spec
;
81 TokenRequestedVisitor(ImageDispatchSpec
* spec
, uint64_t _flag
,
83 : spec(spec
), flag(_flag
), tokens(tokens
) {
86 uint64_t operator()(const Read
&) const {
87 if (flag
& RBD_QOS_WRITE_MASK
) {
92 *tokens
= (flag
& RBD_QOS_BPS_MASK
) ? spec
->extents_length() : 1;
96 uint64_t operator()(const Flush
&) const {
101 template <typename T
>
102 uint64_t operator()(const T
&) const {
103 if (flag
& RBD_QOS_READ_MASK
) {
108 *tokens
= (flag
& RBD_QOS_BPS_MASK
) ? spec
->extents_length() : 1;
113 template <typename I
>
114 void ImageDispatchSpec
<I
>::send() {
115 boost::apply_visitor(SendVisitor
{this}, m_request
);
118 template <typename I
>
119 void ImageDispatchSpec
<I
>::fail(int r
) {
124 template <typename I
>
125 uint64_t ImageDispatchSpec
<I
>::extents_length() {
127 auto &extents
= this->m_image_extents
;
129 for (auto &extent
: extents
) {
130 length
+= extent
.second
;
135 template <typename I
>
136 bool ImageDispatchSpec
<I
>::is_write_op() const {
137 return boost::apply_visitor(IsWriteOpVisitor(), m_request
);
140 template <typename I
>
141 bool ImageDispatchSpec
<I
>::tokens_requested(uint64_t flag
, uint64_t *tokens
) {
142 return boost::apply_visitor(TokenRequestedVisitor
{this, flag
, tokens
},
146 template <typename I
>
147 void ImageDispatchSpec
<I
>::start_op() {
148 m_aio_comp
->start_op();
152 } // namespace librbd
154 template class librbd::io::ImageDispatchSpec
<librbd::ImageCtx
>;