1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #ifndef CEPH_LIBRBD_IO_OBJECT_DISPATCH_SPEC_H
5 #define CEPH_LIBRBD_IO_OBJECT_DISPATCH_SPEC_H
7 #include "include/int_types.h"
8 #include "include/buffer.h"
9 #include "include/Context.h"
10 #include "include/rados/librados.hpp"
11 #include "common/snap_types.h"
12 #include "common/zipkin_trace.h"
13 #include "librbd/io/Types.h"
14 #include <boost/variant/variant.hpp>
19 struct ObjectDispatcherInterface
;
21 struct ObjectDispatchSpec
{
23 // helper to avoid extra heap allocation per object IO
24 struct C_Dispatcher
: public Context
{
25 ObjectDispatchSpec
* object_dispatch_spec
;
28 C_Dispatcher(ObjectDispatchSpec
* object_dispatch_spec
, Context
* on_finish
)
29 : object_dispatch_spec(object_dispatch_spec
), on_finish(on_finish
) {
32 void complete(int r
) override
;
33 void finish(int r
) override
;
41 RequestBase(uint64_t object_no
, uint64_t object_off
)
42 : object_no(object_no
), object_off(object_off
) {
46 struct ReadRequest
: public RequestBase
{
48 librados::snap_t snap_id
;
49 ceph::bufferlist
* read_data
;
50 ExtentMap
* extent_map
;
52 ReadRequest(uint64_t object_no
, uint64_t object_off
, uint64_t object_len
,
53 librados::snap_t snap_id
, ceph::bufferlist
* read_data
,
54 ExtentMap
* extent_map
)
55 : RequestBase(object_no
, object_off
),
56 object_len(object_len
), snap_id(snap_id
), read_data(read_data
),
57 extent_map(extent_map
) {
61 struct WriteRequestBase
: public RequestBase
{
65 WriteRequestBase(uint64_t object_no
, uint64_t object_off
,
66 const ::SnapContext
& snapc
, uint64_t journal_tid
)
67 : RequestBase(object_no
, object_off
), snapc(snapc
),
68 journal_tid(journal_tid
) {
72 struct DiscardRequest
: public WriteRequestBase
{
76 DiscardRequest(uint64_t object_no
, uint64_t object_off
, uint64_t object_len
,
77 int discard_flags
, const ::SnapContext
& snapc
,
79 : WriteRequestBase(object_no
, object_off
, snapc
, journal_tid
),
80 object_len(object_len
), discard_flags(discard_flags
) {
84 struct WriteRequest
: public WriteRequestBase
{
85 ceph::bufferlist data
;
87 WriteRequest(uint64_t object_no
, uint64_t object_off
,
88 ceph::bufferlist
&& data
, const ::SnapContext
& snapc
,
90 : WriteRequestBase(object_no
, object_off
, snapc
, journal_tid
),
91 data(std::move(data
)) {
95 struct WriteSameRequest
: public WriteRequestBase
{
97 LightweightBufferExtents buffer_extents
;
98 ceph::bufferlist data
;
100 WriteSameRequest(uint64_t object_no
, uint64_t object_off
,
102 LightweightBufferExtents
&& buffer_extents
,
103 ceph::bufferlist
&& data
, const ::SnapContext
& snapc
,
104 uint64_t journal_tid
)
105 : WriteRequestBase(object_no
, object_off
, snapc
, journal_tid
),
106 object_len(object_len
), buffer_extents(std::move(buffer_extents
)),
107 data(std::move(data
)) {
111 struct CompareAndWriteRequest
: public WriteRequestBase
{
112 ceph::bufferlist cmp_data
;
113 ceph::bufferlist data
;
114 uint64_t* mismatch_offset
;
116 CompareAndWriteRequest(uint64_t object_no
, uint64_t object_off
,
117 ceph::bufferlist
&& cmp_data
, ceph::bufferlist
&& data
,
118 uint64_t* mismatch_offset
,
119 const ::SnapContext
& snapc
, uint64_t journal_tid
)
120 : WriteRequestBase(object_no
, object_off
, snapc
, journal_tid
),
121 cmp_data(std::move(cmp_data
)), data(std::move(data
)),
122 mismatch_offset(mismatch_offset
) {
126 struct FlushRequest
{
127 FlushSource flush_source
;
128 uint64_t journal_tid
;
130 FlushRequest(FlushSource flush_source
, uint64_t journal_tid
)
131 : flush_source(flush_source
), journal_tid(journal_tid
) {
135 typedef boost::variant
<ReadRequest
,
139 CompareAndWriteRequest
,
140 FlushRequest
> Request
;
142 C_Dispatcher dispatcher_ctx
;
144 ObjectDispatcherInterface
* object_dispatcher
;
145 ObjectDispatchLayer object_dispatch_layer
;
146 int object_dispatch_flags
= 0;
147 DispatchResult dispatch_result
= DISPATCH_RESULT_INVALID
;
151 ZTracer::Trace parent_trace
;
153 template <typename ImageCtxT
>
154 static ObjectDispatchSpec
* create_read(
155 ImageCtxT
* image_ctx
, ObjectDispatchLayer object_dispatch_layer
,
156 uint64_t object_no
, uint64_t object_off
, uint64_t object_len
,
157 librados::snap_t snap_id
, int op_flags
,
158 const ZTracer::Trace
&parent_trace
, ceph::bufferlist
* read_data
,
159 ExtentMap
* extent_map
, Context
* on_finish
) {
160 return new ObjectDispatchSpec(image_ctx
->io_object_dispatcher
,
161 object_dispatch_layer
,
162 ReadRequest
{object_no
, object_off
,
163 object_len
, snap_id
, read_data
,
165 op_flags
, parent_trace
, on_finish
);
168 template <typename ImageCtxT
>
169 static ObjectDispatchSpec
* create_discard(
170 ImageCtxT
* image_ctx
, ObjectDispatchLayer object_dispatch_layer
,
171 uint64_t object_no
, uint64_t object_off
, uint64_t object_len
,
172 const ::SnapContext
&snapc
, int discard_flags
, uint64_t journal_tid
,
173 const ZTracer::Trace
&parent_trace
, Context
*on_finish
) {
174 return new ObjectDispatchSpec(image_ctx
->io_object_dispatcher
,
175 object_dispatch_layer
,
176 DiscardRequest
{object_no
, object_off
,
177 object_len
, discard_flags
,
179 0, parent_trace
, on_finish
);
182 template <typename ImageCtxT
>
183 static ObjectDispatchSpec
* create_write(
184 ImageCtxT
* image_ctx
, ObjectDispatchLayer object_dispatch_layer
,
185 uint64_t object_no
, uint64_t object_off
, ceph::bufferlist
&& data
,
186 const ::SnapContext
&snapc
, int op_flags
, uint64_t journal_tid
,
187 const ZTracer::Trace
&parent_trace
, Context
*on_finish
) {
188 return new ObjectDispatchSpec(image_ctx
->io_object_dispatcher
,
189 object_dispatch_layer
,
190 WriteRequest
{object_no
, object_off
,
191 std::move(data
), snapc
,
193 op_flags
, parent_trace
, on_finish
);
196 template <typename ImageCtxT
>
197 static ObjectDispatchSpec
* create_write_same(
198 ImageCtxT
* image_ctx
, ObjectDispatchLayer object_dispatch_layer
,
199 uint64_t object_no
, uint64_t object_off
, uint64_t object_len
,
200 LightweightBufferExtents
&& buffer_extents
, ceph::bufferlist
&& data
,
201 const ::SnapContext
&snapc
, int op_flags
, uint64_t journal_tid
,
202 const ZTracer::Trace
&parent_trace
, Context
*on_finish
) {
203 return new ObjectDispatchSpec(image_ctx
->io_object_dispatcher
,
204 object_dispatch_layer
,
205 WriteSameRequest
{object_no
, object_off
,
207 std::move(buffer_extents
),
208 std::move(data
), snapc
,
210 op_flags
, parent_trace
, on_finish
);
213 template <typename ImageCtxT
>
214 static ObjectDispatchSpec
* create_compare_and_write(
215 ImageCtxT
* image_ctx
, ObjectDispatchLayer object_dispatch_layer
,
216 uint64_t object_no
, uint64_t object_off
, ceph::bufferlist
&& cmp_data
,
217 ceph::bufferlist
&& write_data
, const ::SnapContext
&snapc
,
218 uint64_t *mismatch_offset
, int op_flags
, uint64_t journal_tid
,
219 const ZTracer::Trace
&parent_trace
, Context
*on_finish
) {
220 return new ObjectDispatchSpec(image_ctx
->io_object_dispatcher
,
221 object_dispatch_layer
,
222 CompareAndWriteRequest
{object_no
,
225 std::move(write_data
),
228 op_flags
, parent_trace
, on_finish
);
231 template <typename ImageCtxT
>
232 static ObjectDispatchSpec
* create_flush(
233 ImageCtxT
* image_ctx
, ObjectDispatchLayer object_dispatch_layer
,
234 FlushSource flush_source
, uint64_t journal_tid
,
235 const ZTracer::Trace
&parent_trace
, Context
*on_finish
) {
236 return new ObjectDispatchSpec(image_ctx
->io_object_dispatcher
,
237 object_dispatch_layer
,
238 FlushRequest
{flush_source
, journal_tid
}, 0,
239 parent_trace
, on_finish
);
246 template <typename
> friend class ObjectDispatcher
;
248 ObjectDispatchSpec(ObjectDispatcherInterface
* object_dispatcher
,
249 ObjectDispatchLayer object_dispatch_layer
,
250 Request
&& request
, int op_flags
,
251 const ZTracer::Trace
& parent_trace
, Context
* on_finish
)
252 : dispatcher_ctx(this, on_finish
), object_dispatcher(object_dispatcher
),
253 object_dispatch_layer(object_dispatch_layer
), request(std::move(request
)),
254 op_flags(op_flags
), parent_trace(parent_trace
) {
260 } // namespace librbd
262 #endif // CEPH_LIBRBD_IO_OBJECT_DISPATCH_SPEC_H