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/zipkin_trace.h"
12 #include "common/RefCountedObj.h"
15 #include <type_traits>
26 void rados_callback(rados_completion_t c
, void *arg
) {
27 reinterpret_cast<T
*>(arg
)->complete(rados_aio_get_return_value(c
));
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
);
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
);
50 template <typename T
, void (T::*MF
)(int)>
51 class C_CallbackAdapter
: public Context
{
54 C_CallbackAdapter(T
*obj
) : obj(obj
) {
58 void finish(int r
) override
{
63 template <typename T
, void (T::*MF
)(int)>
64 class C_RefCallbackAdapter
: public Context
{
69 C_RefCallbackAdapter(T
*obj
, RefCountedPtr refptr
)
70 : refptr(std::move(refptr
)),
71 on_finish(new C_CallbackAdapter
<T
, MF
>(obj
)) {
75 void finish(int r
) override
{
76 on_finish
->complete(r
);
80 template <typename T
, Context
*(T::*MF
)(int*), bool destroy
>
81 class C_StateCallbackAdapter
: public Context
{
84 C_StateCallbackAdapter(T
*obj
) : obj(obj
){
88 void complete(int r
) override
{
89 Context
*on_finish
= (obj
->*MF
)(&r
);
90 if (on_finish
!= nullptr) {
91 on_finish
->complete(r
);
98 void finish(int r
) override
{
102 template <typename T
, Context
*(T::*MF
)(int*)>
103 class C_RefStateCallbackAdapter
: public Context
{
104 RefCountedPtr refptr
;
108 C_RefStateCallbackAdapter(T
*obj
, RefCountedPtr refptr
)
109 : refptr(std::move(refptr
)),
110 on_finish(new C_StateCallbackAdapter
<T
, MF
, true>(obj
)) {
114 void finish(int r
) override
{
115 on_finish
->complete(r
);
119 template <typename WQ
>
120 struct C_AsyncCallback
: public Context
{
124 C_AsyncCallback(WQ
*op_work_queue
, Context
*on_finish
)
125 : op_work_queue(op_work_queue
), on_finish(on_finish
) {
127 ~C_AsyncCallback() override
{
130 void finish(int r
) override
{
131 op_work_queue
->queue(on_finish
, r
);
136 } // namespace detail
138 std::string
generate_image_id(librados::IoCtx
&ioctx
);
140 template <typename T
>
141 inline std::string
generate_image_id(librados::IoCtx
&ioctx
) {
142 return generate_image_id(ioctx
);
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
);
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
);
159 oid
.reserve(RBD_MAX_OBJ_NAME_SIZE
);
160 oid
.append(buf
, length
);
164 librados::AioCompletion
*create_rados_callback(Context
*on_finish
);
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
>);
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
>);
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
>);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
232 // TODO: temporary until AioCompletion supports templated ImageCtx
233 inline ImageCtx
*get_image_ctx(ImageCtx
*image_ctx
) {
237 uint64_t get_rbd_default_features(CephContext
* cct
);
239 bool calc_sparse_extent(const bufferptr
&bp
,
242 size_t *write_offset
,
243 size_t *write_length
,
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
);
252 return ZTracer::Trace();
255 bool is_metadata_config_override(const std::string
& metadata_key
,
256 std::string
* config_key
);
258 int create_ioctx(librados::IoCtx
& src_io_ctx
, const std::string
& pool_desc
,
260 const std::optional
<std::string
>& pool_namespace
,
261 librados::IoCtx
* dst_io_ctx
);
264 } // namespace librbd
266 #endif // CEPH_LIBRBD_UTILS_H