]>
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; | |
81eedcae | 79 | uint64_t *tokens; |
11fdf7f2 | 80 | |
81eedcae TL |
81 | TokenRequestedVisitor(ImageDispatchSpec* spec, uint64_t _flag, |
82 | uint64_t *tokens) | |
83 | : spec(spec), flag(_flag), tokens(tokens) { | |
11fdf7f2 TL |
84 | } |
85 | ||
86 | uint64_t operator()(const Read&) const { | |
87 | if (flag & RBD_QOS_WRITE_MASK) { | |
81eedcae TL |
88 | *tokens = 0; |
89 | return false; | |
11fdf7f2 TL |
90 | } |
91 | ||
81eedcae TL |
92 | *tokens = (flag & RBD_QOS_BPS_MASK) ? spec->extents_length() : 1; |
93 | return true; | |
11fdf7f2 TL |
94 | } |
95 | ||
96 | uint64_t operator()(const Flush&) const { | |
81eedcae TL |
97 | *tokens = 0; |
98 | return true; | |
11fdf7f2 TL |
99 | } |
100 | ||
101 | template <typename T> | |
102 | uint64_t operator()(const T&) const { | |
103 | if (flag & RBD_QOS_READ_MASK) { | |
81eedcae TL |
104 | *tokens = 0; |
105 | return false; | |
11fdf7f2 TL |
106 | } |
107 | ||
81eedcae TL |
108 | *tokens = (flag & RBD_QOS_BPS_MASK) ? spec->extents_length() : 1; |
109 | return true; | |
11fdf7f2 TL |
110 | } |
111 | }; | |
112 | ||
113 | template <typename I> | |
114 | void ImageDispatchSpec<I>::send() { | |
115 | boost::apply_visitor(SendVisitor{this}, m_request); | |
116 | } | |
117 | ||
118 | template <typename I> | |
119 | void ImageDispatchSpec<I>::fail(int r) { | |
120 | m_aio_comp->get(); | |
121 | m_aio_comp->fail(r); | |
122 | } | |
123 | ||
124 | template <typename I> | |
125 | uint64_t ImageDispatchSpec<I>::extents_length() { | |
126 | uint64_t length = 0; | |
127 | auto &extents = this->m_image_extents; | |
128 | ||
129 | for (auto &extent : extents) { | |
130 | length += extent.second; | |
131 | } | |
132 | return length; | |
133 | } | |
134 | ||
135 | template <typename I> | |
136 | bool ImageDispatchSpec<I>::is_write_op() const { | |
137 | return boost::apply_visitor(IsWriteOpVisitor(), m_request); | |
138 | } | |
139 | ||
140 | template <typename I> | |
81eedcae TL |
141 | bool ImageDispatchSpec<I>::tokens_requested(uint64_t flag, uint64_t *tokens) { |
142 | return boost::apply_visitor(TokenRequestedVisitor{this, flag, tokens}, | |
143 | m_request); | |
11fdf7f2 TL |
144 | } |
145 | ||
146 | template <typename I> | |
147 | void ImageDispatchSpec<I>::start_op() { | |
148 | m_aio_comp->start_op(); | |
149 | } | |
150 | ||
151 | } // namespace io | |
152 | } // namespace librbd | |
153 | ||
154 | template class librbd::io::ImageDispatchSpec<librbd::ImageCtx>; |