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_UTILS_H
5 #define CEPH_LIBRBD_UTILS_H
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"
17 #include <type_traits>
30 void rados_callback(rados_completion_t c
, void *arg
) {
31 reinterpret_cast<T
*>(arg
)->complete(rados_aio_get_return_value(c
));
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
);
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
);
54 template <typename T
, void (T::*MF
)(int)>
55 class C_CallbackAdapter
: public Context
{
58 C_CallbackAdapter(T
*obj
) : obj(obj
) {
62 void finish(int r
) override
{
67 template <typename T
, void (T::*MF
)(int)>
68 class C_RefCallbackAdapter
: public Context
{
73 C_RefCallbackAdapter(T
*obj
, RefCountedPtr refptr
)
74 : refptr(std::move(refptr
)),
75 on_finish(new C_CallbackAdapter
<T
, MF
>(obj
)) {
79 void finish(int r
) override
{
80 on_finish
->complete(r
);
84 template <typename T
, Context
*(T::*MF
)(int*), bool destroy
>
85 class C_StateCallbackAdapter
: public Context
{
88 C_StateCallbackAdapter(T
*obj
) : obj(obj
){
92 void complete(int r
) override
{
93 Context
*on_finish
= (obj
->*MF
)(&r
);
94 if (on_finish
!= nullptr) {
95 on_finish
->complete(r
);
100 Context::complete(r
);
102 void finish(int r
) override
{
106 template <typename T
, Context
*(T::*MF
)(int*)>
107 class C_RefStateCallbackAdapter
: public Context
{
108 RefCountedPtr refptr
;
112 C_RefStateCallbackAdapter(T
*obj
, RefCountedPtr refptr
)
113 : refptr(std::move(refptr
)),
114 on_finish(new C_StateCallbackAdapter
<T
, MF
, true>(obj
)) {
118 void finish(int r
) override
{
119 on_finish
->complete(r
);
123 template <typename WQ
>
124 struct C_AsyncCallback
: public Context
{
128 C_AsyncCallback(WQ
*op_work_queue
, Context
*on_finish
)
129 : op_work_queue(op_work_queue
), on_finish(on_finish
) {
131 ~C_AsyncCallback() override
{
134 void finish(int r
) override
{
135 op_work_queue
->queue(on_finish
, r
);
140 } // namespace detail
142 std::string
generate_image_id(librados::IoCtx
&ioctx
);
144 template <typename T
>
145 inline std::string
generate_image_id(librados::IoCtx
&ioctx
) {
146 return generate_image_id(ioctx
);
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
);
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
);
163 oid
.reserve(RBD_MAX_OBJ_NAME_SIZE
);
164 oid
.append(buf
, length
);
168 librados::AioCompletion
*create_rados_callback(Context
*on_finish
);
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
>);
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
>);
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
>);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
236 // TODO: temporary until AioCompletion supports templated ImageCtx
237 inline ImageCtx
*get_image_ctx(ImageCtx
*image_ctx
) {
241 uint64_t get_rbd_default_features(CephContext
* cct
);
243 bool calc_sparse_extent(const bufferptr
&bp
,
246 size_t *write_offset
,
247 size_t *write_length
,
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
);
256 return ZTracer::Trace();
259 bool is_metadata_config_override(const std::string
& metadata_key
,
260 std::string
* config_key
);
262 int create_ioctx(librados::IoCtx
& src_io_ctx
, const std::string
& pool_desc
,
264 const std::optional
<std::string
>& pool_namespace
,
265 librados::IoCtx
* dst_io_ctx
);
267 int snap_create_flags_api_to_internal(CephContext
*cct
, uint32_t api_flags
,
268 uint64_t *internal_flags
);
270 uint32_t get_default_snap_create_flags(ImageCtx
*ictx
);
272 SnapContext
get_snap_context(
274 std::pair
<std::uint64_t,
275 std::vector
<std::uint64_t>>>& write_snap_context
);
277 uint64_t reserve_async_request_id();
279 bool is_config_key_uri(const std::string
& uri
);
280 int get_config_key(librados::Rados
& rados
, const std::string
& uri
,
284 } // namespace librbd
286 #endif // CEPH_LIBRBD_UTILS_H