]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | ||
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> | |
9 | ||
10 | namespace librbd { | |
11 | namespace io { | |
12 | ||
13 | template <typename I> | |
14 | struct ImageDispatchSpec<I>::SendVisitor | |
15 | : public boost::static_visitor<void> { | |
16 | ImageDispatchSpec* spec; | |
17 | ||
18 | explicit SendVisitor(ImageDispatchSpec* spec) | |
19 | : spec(spec) { | |
20 | } | |
21 | ||
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); | |
26 | } | |
27 | ||
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); | |
32 | } | |
33 | ||
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); | |
38 | } | |
39 | ||
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); | |
44 | } | |
45 | ||
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); | |
52 | } | |
53 | ||
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); | |
58 | } | |
59 | }; | |
60 | ||
61 | template <typename I> | |
62 | struct ImageDispatchSpec<I>::IsWriteOpVisitor | |
63 | : public boost::static_visitor<bool> { | |
64 | bool operator()(const Read&) const { | |
65 | return false; | |
66 | } | |
67 | ||
68 | template <typename T> | |
69 | bool operator()(const T&) const { | |
70 | return true; | |
71 | } | |
72 | }; | |
73 | ||
74 | template <typename I> | |
75 | struct ImageDispatchSpec<I>::TokenRequestedVisitor | |
76 | : public boost::static_visitor<uint64_t> { | |
77 | ImageDispatchSpec* spec; | |
78 | uint64_t flag; | |
79 | ||
80 | TokenRequestedVisitor(ImageDispatchSpec* spec, uint64_t _flag) | |
81 | : spec(spec), flag(_flag) { | |
82 | } | |
83 | ||
84 | uint64_t operator()(const Read&) const { | |
85 | if (flag & RBD_QOS_WRITE_MASK) { | |
86 | return 0; | |
87 | } | |
88 | ||
89 | if (flag & RBD_QOS_BPS_MASK) { | |
90 | return spec->extents_length(); | |
91 | } | |
92 | return 1; | |
93 | } | |
94 | ||
95 | uint64_t operator()(const Flush&) const { | |
96 | return 0; | |
97 | } | |
98 | ||
99 | template <typename T> | |
100 | uint64_t operator()(const T&) const { | |
101 | if (flag & RBD_QOS_READ_MASK) { | |
102 | return 0; | |
103 | } | |
104 | ||
105 | if (flag & RBD_QOS_BPS_MASK) { | |
106 | return spec->extents_length(); | |
107 | } | |
108 | return 1; | |
109 | } | |
110 | }; | |
111 | ||
112 | template <typename I> | |
113 | void ImageDispatchSpec<I>::send() { | |
114 | boost::apply_visitor(SendVisitor{this}, m_request); | |
115 | } | |
116 | ||
117 | template <typename I> | |
118 | void ImageDispatchSpec<I>::fail(int r) { | |
119 | m_aio_comp->get(); | |
120 | m_aio_comp->fail(r); | |
121 | } | |
122 | ||
123 | template <typename I> | |
124 | uint64_t ImageDispatchSpec<I>::extents_length() { | |
125 | uint64_t length = 0; | |
126 | auto &extents = this->m_image_extents; | |
127 | ||
128 | for (auto &extent : extents) { | |
129 | length += extent.second; | |
130 | } | |
131 | return length; | |
132 | } | |
133 | ||
134 | template <typename I> | |
135 | bool ImageDispatchSpec<I>::is_write_op() const { | |
136 | return boost::apply_visitor(IsWriteOpVisitor(), m_request); | |
137 | } | |
138 | ||
139 | template <typename I> | |
140 | uint64_t ImageDispatchSpec<I>::tokens_requested(uint64_t flag) { | |
141 | return boost::apply_visitor(TokenRequestedVisitor{this, flag}, m_request); | |
142 | } | |
143 | ||
144 | template <typename I> | |
145 | void ImageDispatchSpec<I>::start_op() { | |
146 | m_aio_comp->start_op(); | |
147 | } | |
148 | ||
149 | } // namespace io | |
150 | } // namespace librbd | |
151 | ||
152 | template class librbd::io::ImageDispatchSpec<librbd::ImageCtx>; |