]> git.proxmox.com Git - ceph.git/blob - ceph/src/librbd/Utils.h
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / librbd / Utils.h
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 #ifndef CEPH_LIBRBD_UTILS_H
5 #define CEPH_LIBRBD_UTILS_H
6
7 #include "include/rados/librados.hpp"
8 #include "include/rbd_types.h"
9 #include "include/ceph_assert.h"
10 #include "include/Context.h"
11 #include "common/snap_types.h"
12 #include "common/zipkin_trace.h"
13 #include "common/RefCountedObj.h"
14
15 #include <atomic>
16 #include <optional>
17 #include <type_traits>
18 #include <utility>
19 #include <vector>
20 #include <stdio.h>
21
22 namespace librbd {
23
24 class ImageCtx;
25
26 namespace util {
27 namespace detail {
28
29 template <typename T>
30 void rados_callback(rados_completion_t c, void *arg) {
31 reinterpret_cast<T*>(arg)->complete(rados_aio_get_return_value(c));
32 }
33
34 template <typename T, void(T::*MF)(int)>
35 void rados_callback(rados_completion_t c, void *arg) {
36 T *obj = reinterpret_cast<T*>(arg);
37 int r = rados_aio_get_return_value(c);
38 (obj->*MF)(r);
39 }
40
41 template <typename T, Context*(T::*MF)(int*), bool destroy>
42 void rados_state_callback(rados_completion_t c, void *arg) {
43 T *obj = reinterpret_cast<T*>(arg);
44 int r = rados_aio_get_return_value(c);
45 Context *on_finish = (obj->*MF)(&r);
46 if (on_finish != nullptr) {
47 on_finish->complete(r);
48 if (destroy) {
49 delete obj;
50 }
51 }
52 }
53
54 template <typename T, void (T::*MF)(int)>
55 class C_CallbackAdapter : public Context {
56 T *obj;
57 public:
58 C_CallbackAdapter(T *obj) : obj(obj) {
59 }
60
61 protected:
62 void finish(int r) override {
63 (obj->*MF)(r);
64 }
65 };
66
67 template <typename T, void (T::*MF)(int)>
68 class C_RefCallbackAdapter : public Context {
69 RefCountedPtr refptr;
70 Context *on_finish;
71
72 public:
73 C_RefCallbackAdapter(T *obj, RefCountedPtr refptr)
74 : refptr(std::move(refptr)),
75 on_finish(new C_CallbackAdapter<T, MF>(obj)) {
76 }
77
78 protected:
79 void finish(int r) override {
80 on_finish->complete(r);
81 }
82 };
83
84 template <typename T, Context*(T::*MF)(int*), bool destroy>
85 class C_StateCallbackAdapter : public Context {
86 T *obj;
87 public:
88 C_StateCallbackAdapter(T *obj) : obj(obj){
89 }
90
91 protected:
92 void complete(int r) override {
93 Context *on_finish = (obj->*MF)(&r);
94 if (on_finish != nullptr) {
95 on_finish->complete(r);
96 if (destroy) {
97 delete obj;
98 }
99 }
100 Context::complete(r);
101 }
102 void finish(int r) override {
103 }
104 };
105
106 template <typename T, Context*(T::*MF)(int*)>
107 class C_RefStateCallbackAdapter : public Context {
108 RefCountedPtr refptr;
109 Context *on_finish;
110
111 public:
112 C_RefStateCallbackAdapter(T *obj, RefCountedPtr refptr)
113 : refptr(std::move(refptr)),
114 on_finish(new C_StateCallbackAdapter<T, MF, true>(obj)) {
115 }
116
117 protected:
118 void finish(int r) override {
119 on_finish->complete(r);
120 }
121 };
122
123 template <typename WQ>
124 struct C_AsyncCallback : public Context {
125 WQ *op_work_queue;
126 Context *on_finish;
127
128 C_AsyncCallback(WQ *op_work_queue, Context *on_finish)
129 : op_work_queue(op_work_queue), on_finish(on_finish) {
130 }
131 ~C_AsyncCallback() override {
132 delete on_finish;
133 }
134 void finish(int r) override {
135 op_work_queue->queue(on_finish, r);
136 on_finish = nullptr;
137 }
138 };
139
140 } // namespace detail
141
142 std::string generate_image_id(librados::IoCtx &ioctx);
143
144 template <typename T>
145 inline std::string generate_image_id(librados::IoCtx &ioctx) {
146 return generate_image_id(ioctx);
147 }
148
149 const std::string group_header_name(const std::string &group_id);
150 const std::string id_obj_name(const std::string &name);
151 const std::string header_name(const std::string &image_id);
152 const std::string old_header_name(const std::string &image_name);
153 std::string unique_lock_name(const std::string &name, void *address);
154
155 template <typename I>
156 std::string data_object_name(I* image_ctx, uint64_t object_no) {
157 char buf[RBD_MAX_OBJ_NAME_SIZE];
158 size_t length = snprintf(buf, RBD_MAX_OBJ_NAME_SIZE,
159 image_ctx->format_string, object_no);
160 ceph_assert(length < RBD_MAX_OBJ_NAME_SIZE);
161
162 std::string oid;
163 oid.reserve(RBD_MAX_OBJ_NAME_SIZE);
164 oid.append(buf, length);
165 return oid;
166 }
167
168 librados::AioCompletion *create_rados_callback(Context *on_finish);
169
170 template <typename T>
171 librados::AioCompletion *create_rados_callback(T *obj) {
172 return librados::Rados::aio_create_completion(
173 obj, &detail::rados_callback<T>);
174 }
175
176 template <typename T, void(T::*MF)(int)>
177 librados::AioCompletion *create_rados_callback(T *obj) {
178 return librados::Rados::aio_create_completion(
179 obj, &detail::rados_callback<T, MF>);
180 }
181
182 template <typename T, Context*(T::*MF)(int*), bool destroy=true>
183 librados::AioCompletion *create_rados_callback(T *obj) {
184 return librados::Rados::aio_create_completion(
185 obj, &detail::rados_state_callback<T, MF, destroy>);
186 }
187
188 template <typename T, void(T::*MF)(int) = &T::complete>
189 Context *create_context_callback(T *obj) {
190 return new detail::C_CallbackAdapter<T, MF>(obj);
191 }
192
193 template <typename T, Context*(T::*MF)(int*), bool destroy=true>
194 Context *create_context_callback(T *obj) {
195 return new detail::C_StateCallbackAdapter<T, MF, destroy>(obj);
196 }
197
198 //for reference counting objects
199 template <typename T, void(T::*MF)(int) = &T::complete>
200 Context *create_context_callback(T *obj, RefCountedPtr refptr) {
201 return new detail::C_RefCallbackAdapter<T, MF>(obj, refptr);
202 }
203
204 template <typename T, Context*(T::*MF)(int*)>
205 Context *create_context_callback(T *obj, RefCountedPtr refptr) {
206 return new detail::C_RefStateCallbackAdapter<T, MF>(obj, refptr);
207 }
208
209 //for objects that don't inherit from RefCountedObj, to handle unit tests
210 template <typename T, void(T::*MF)(int) = &T::complete, typename R>
211 typename std::enable_if<not std::is_base_of<RefCountedPtr, R>::value, Context*>::type
212 create_context_callback(T *obj, R *refptr) {
213 return new detail::C_CallbackAdapter<T, MF>(obj);
214 }
215
216 template <typename T, Context*(T::*MF)(int*), typename R, bool destroy=true>
217 typename std::enable_if<not std::is_base_of<RefCountedPtr, R>::value, Context*>::type
218 create_context_callback(T *obj, R *refptr) {
219 return new detail::C_StateCallbackAdapter<T, MF, destroy>(obj);
220 }
221
222 template <typename I>
223 Context *create_async_context_callback(I &image_ctx, Context *on_finish) {
224 // use async callback to acquire a clean lock context
225 return new detail::C_AsyncCallback<
226 typename std::decay<decltype(*image_ctx.op_work_queue)>::type>(
227 image_ctx.op_work_queue, on_finish);
228 }
229
230 template <typename WQ>
231 Context *create_async_context_callback(WQ *work_queue, Context *on_finish) {
232 // use async callback to acquire a clean lock context
233 return new detail::C_AsyncCallback<WQ>(work_queue, on_finish);
234 }
235
236 // TODO: temporary until AioCompletion supports templated ImageCtx
237 inline ImageCtx *get_image_ctx(ImageCtx *image_ctx) {
238 return image_ctx;
239 }
240
241 uint64_t get_rbd_default_features(CephContext* cct);
242
243 bool calc_sparse_extent(const bufferptr &bp,
244 size_t sparse_size,
245 uint64_t length,
246 size_t *write_offset,
247 size_t *write_length,
248 size_t *offset);
249
250 template <typename I>
251 inline ZTracer::Trace create_trace(const I &image_ctx, const char *trace_name,
252 const ZTracer::Trace &parent_trace) {
253 if (parent_trace.valid()) {
254 return ZTracer::Trace(trace_name, &image_ctx.trace_endpoint, &parent_trace);
255 }
256 return ZTracer::Trace();
257 }
258
259 bool is_metadata_config_override(const std::string& metadata_key,
260 std::string* config_key);
261
262 int create_ioctx(librados::IoCtx& src_io_ctx, const std::string& pool_desc,
263 int64_t pool_id,
264 const std::optional<std::string>& pool_namespace,
265 librados::IoCtx* dst_io_ctx);
266
267 int snap_create_flags_api_to_internal(CephContext *cct, uint32_t api_flags,
268 uint64_t *internal_flags);
269
270 uint32_t get_default_snap_create_flags(ImageCtx *ictx);
271
272 SnapContext get_snap_context(
273 const std::optional<
274 std::pair<std::uint64_t,
275 std::vector<std::uint64_t>>>& write_snap_context);
276
277 uint64_t reserve_async_request_id();
278
279 bool is_config_key_uri(const std::string& uri);
280 int get_config_key(librados::Rados& rados, const std::string& uri,
281 std::string* value);
282
283 } // namespace util
284 } // namespace librbd
285
286 #endif // CEPH_LIBRBD_UTILS_H