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