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