]> git.proxmox.com Git - ceph.git/blob - ceph/src/librbd/io/ImageDispatchSpec.cc
import ceph nautilus 14.2.2
[ceph.git] / ceph / src / librbd / io / ImageDispatchSpec.cc
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 uint64_t *tokens;
80
81 TokenRequestedVisitor(ImageDispatchSpec* spec, uint64_t _flag,
82 uint64_t *tokens)
83 : spec(spec), flag(_flag), tokens(tokens) {
84 }
85
86 uint64_t operator()(const Read&) const {
87 if (flag & RBD_QOS_WRITE_MASK) {
88 *tokens = 0;
89 return false;
90 }
91
92 *tokens = (flag & RBD_QOS_BPS_MASK) ? spec->extents_length() : 1;
93 return true;
94 }
95
96 uint64_t operator()(const Flush&) const {
97 *tokens = 0;
98 return true;
99 }
100
101 template <typename T>
102 uint64_t operator()(const T&) const {
103 if (flag & RBD_QOS_READ_MASK) {
104 *tokens = 0;
105 return false;
106 }
107
108 *tokens = (flag & RBD_QOS_BPS_MASK) ? spec->extents_length() : 1;
109 return true;
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>
141 bool ImageDispatchSpec<I>::tokens_requested(uint64_t flag, uint64_t *tokens) {
142 return boost::apply_visitor(TokenRequestedVisitor{this, flag, tokens},
143 m_request);
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>;