]> git.proxmox.com Git - ceph.git/blob - ceph/src/librbd/Utils.h
update sources to v12.1.3
[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/Context.h"
10 #include "common/zipkin_trace.h"
11
12 #include <atomic>
13 #include <type_traits>
14
15 namespace librbd {
16
17 class ImageCtx;
18
19 namespace util {
20
21 namespace detail {
22
23 template <typename T>
24 void rados_callback(rados_completion_t c, void *arg) {
25 reinterpret_cast<T*>(arg)->complete(rados_aio_get_return_value(c));
26 }
27
28 template <typename T, void(T::*MF)(int)>
29 void rados_callback(rados_completion_t c, void *arg) {
30 T *obj = reinterpret_cast<T*>(arg);
31 int r = rados_aio_get_return_value(c);
32 (obj->*MF)(r);
33 }
34
35 template <typename T, Context*(T::*MF)(int*), bool destroy>
36 void rados_state_callback(rados_completion_t c, void *arg) {
37 T *obj = reinterpret_cast<T*>(arg);
38 int r = rados_aio_get_return_value(c);
39 Context *on_finish = (obj->*MF)(&r);
40 if (on_finish != nullptr) {
41 on_finish->complete(r);
42 if (destroy) {
43 delete obj;
44 }
45 }
46 }
47
48 template <typename T, void (T::*MF)(int)>
49 class C_CallbackAdapter : public Context {
50 T *obj;
51 public:
52 C_CallbackAdapter(T *obj) : obj(obj) {
53 }
54
55 protected:
56 void finish(int r) override {
57 (obj->*MF)(r);
58 }
59 };
60
61 template <typename T, Context*(T::*MF)(int*), bool destroy>
62 class C_StateCallbackAdapter : public Context {
63 T *obj;
64 public:
65 C_StateCallbackAdapter(T *obj) : obj(obj){
66 }
67
68 protected:
69 void complete(int r) override {
70 Context *on_finish = (obj->*MF)(&r);
71 if (on_finish != nullptr) {
72 on_finish->complete(r);
73 if (destroy) {
74 delete obj;
75 }
76 }
77 Context::complete(r);
78 }
79 void finish(int r) override {
80 }
81 };
82
83 template <typename WQ>
84 struct C_AsyncCallback : public Context {
85 WQ *op_work_queue;
86 Context *on_finish;
87
88 C_AsyncCallback(WQ *op_work_queue, Context *on_finish)
89 : op_work_queue(op_work_queue), on_finish(on_finish) {
90 }
91 void finish(int r) override {
92 op_work_queue->queue(on_finish, r);
93 }
94 };
95
96 } // namespace detail
97
98 std::string generate_image_id(librados::IoCtx &ioctx);
99
100 template <typename T>
101 inline std::string generate_image_id(librados::IoCtx &ioctx) {
102 return generate_image_id(ioctx);
103 }
104
105 const std::string group_header_name(const std::string &group_id);
106 const std::string id_obj_name(const std::string &name);
107 const std::string header_name(const std::string &image_id);
108 const std::string old_header_name(const std::string &image_name);
109 std::string unique_lock_name(const std::string &name, void *address);
110
111 librados::AioCompletion *create_rados_callback(Context *on_finish);
112
113 template <typename T>
114 librados::AioCompletion *create_rados_callback(T *obj) {
115 return librados::Rados::aio_create_completion(
116 obj, &detail::rados_callback<T>, nullptr);
117 }
118
119 template <typename T, void(T::*MF)(int)>
120 librados::AioCompletion *create_rados_callback(T *obj) {
121 return librados::Rados::aio_create_completion(
122 obj, &detail::rados_callback<T, MF>, nullptr);
123 }
124
125 template <typename T, Context*(T::*MF)(int*), bool destroy=true>
126 librados::AioCompletion *create_rados_callback(T *obj) {
127 return librados::Rados::aio_create_completion(
128 obj, &detail::rados_state_callback<T, MF, destroy>, nullptr);
129 }
130
131 template <typename T, void(T::*MF)(int) = &T::complete>
132 Context *create_context_callback(T *obj) {
133 return new detail::C_CallbackAdapter<T, MF>(obj);
134 }
135
136 template <typename T, Context*(T::*MF)(int*), bool destroy=true>
137 Context *create_context_callback(T *obj) {
138 return new detail::C_StateCallbackAdapter<T, MF, destroy>(obj);
139 }
140
141 template <typename I>
142 Context *create_async_context_callback(I &image_ctx, Context *on_finish) {
143 // use async callback to acquire a clean lock context
144 return new detail::C_AsyncCallback<
145 typename std::decay<decltype(*image_ctx.op_work_queue)>::type>(
146 image_ctx.op_work_queue, on_finish);
147 }
148
149 template <typename WQ>
150 Context *create_async_context_callback(WQ *work_queue, Context *on_finish) {
151 // use async callback to acquire a clean lock context
152 return new detail::C_AsyncCallback<WQ>(work_queue, on_finish);
153 }
154
155 // TODO: temporary until AioCompletion supports templated ImageCtx
156 inline ImageCtx *get_image_ctx(ImageCtx *image_ctx) {
157 return image_ctx;
158 }
159
160 /// helper for tracking in-flight async ops when coordinating
161 /// a shut down of the invoking class instance
162 class AsyncOpTracker {
163 public:
164 void start_op() {
165 m_refs++;
166 }
167
168 void finish_op() {
169 if (--m_refs == 0 && m_on_finish != nullptr) {
170 Context *on_finish = nullptr;
171 std::swap(on_finish, m_on_finish);
172 on_finish->complete(0);
173 }
174 }
175
176 template <typename I>
177 void wait(I &image_ctx, Context *on_finish) {
178 assert(m_on_finish == nullptr);
179
180 on_finish = create_async_context_callback(image_ctx, on_finish);
181 if (m_refs == 0) {
182 on_finish->complete(0);
183 return;
184 }
185 m_on_finish = on_finish;
186 }
187
188 private:
189 std::atomic<uint64_t> m_refs = { 0 };
190 Context *m_on_finish = nullptr;
191 };
192
193 uint64_t get_rbd_default_features(CephContext* cct);
194
195 bool calc_sparse_extent(const bufferptr &bp,
196 size_t sparse_size,
197 uint64_t length,
198 size_t *write_offset,
199 size_t *write_length,
200 size_t *offset);
201
202 template <typename I>
203 inline ZTracer::Trace create_trace(const I &image_ctx, const char *trace_name,
204 const ZTracer::Trace &parent_trace) {
205 if (parent_trace.valid()) {
206 return ZTracer::Trace(trace_name, &image_ctx.trace_endpoint, &parent_trace);
207 }
208 return ZTracer::Trace();
209 }
210
211 } // namespace util
212
213 } // namespace librbd
214
215 #endif // CEPH_LIBRBD_UTILS_H