#include "librbd/AioObjectRequest.h"
#include "librbd/CopyupRequest.h"
+#include "librbd/Utils.h"
#include <boost/bind.hpp>
#include <boost/optional.hpp>
return;
}
- librados::AioCompletion *rados_completion =
- librados::Rados::aio_create_completion(this, rados_req_cb, NULL);
- int r;
librados::ObjectReadOperation op;
int flags = m_ictx->get_read_flags(m_snap_id);
if (m_sparse) {
}
op.set_op_flags2(m_op_flags);
- r = m_ictx->data_ctx.aio_operate(m_oid, rados_completion, &op, flags, NULL);
+ librados::AioCompletion *rados_completion =
+ util::create_rados_ack_callback(this);
+ int r = m_ictx->data_ctx.aio_operate(m_oid, rados_completion, &op, flags,
+ NULL);
assert(r == 0);
rados_completion->release();
RWLock::WLocker object_map_locker(m_ictx->object_map_lock);
if (m_ictx->object_map[m_object_no] != new_state) {
- FunctionContext *ctx = new FunctionContext(
- boost::bind(&AioObjectRequest::complete, this, _1));
+ Context *ctx = util::create_context_callback<AioObjectRequest>(this);
bool updated = m_ictx->object_map.aio_update(m_object_no, new_state,
current_state, ctx);
assert(updated);
return true;
}
- FunctionContext *ctx = new FunctionContext(
- boost::bind(&AioObjectRequest::complete, this, _1));
+ Context *ctx = util::create_context_callback<AioObjectRequest>(this);
bool updated = m_ictx->object_map.aio_update(m_object_no,
OBJECT_NONEXISTENT,
OBJECT_PENDING, ctx);
assert(m_write.size() != 0);
librados::AioCompletion *rados_completion =
- librados::Rados::aio_create_completion(this, NULL, rados_req_cb);
+ util::create_rados_safe_callback(this);
int r = m_ictx->data_ctx.aio_operate(m_oid, rados_completion, &m_write,
m_snap_seq, m_snaps);
assert(r == 0);
#include "librbd/AsyncRequest.h"
#include "librbd/ImageCtx.h"
#include "librbd/internal.h"
+#include "librbd/Utils.h"
#include "common/WorkQueue.h"
#include <boost/bind.hpp>
template <typename T>
librados::AioCompletion *AsyncRequest<T>::create_callback_completion() {
- return librados::Rados::aio_create_completion(create_callback_context(),
- NULL, rados_ctx_cb);
+ return util::create_rados_safe_callback(this);
}
template <typename T>
Context *AsyncRequest<T>::create_callback_context() {
- return new FunctionContext(boost::bind(&AsyncRequest<T>::complete, this, _1));
+ return util::create_context_callback(this);
}
template <typename T>
Context *AsyncRequest<T>::create_async_callback_context() {
- return new FunctionContext(boost::bind(&AsyncRequest<T>::async_complete, this,
- _1));;
+ return util::create_context_callback<AsyncRequest<T>,
+ &AsyncRequest<T>::async_complete>(this);
}
template <typename T>
#include "librbd/ImageWatcher.h"
#include "librbd/internal.h"
#include "librbd/ObjectMap.h"
+#include "librbd/Utils.h"
#include <boost/bind.hpp>
#include <boost/lambda/bind.hpp>
ldout(m_ictx->cct, 20) << __func__ << " " << this << " copyup with "
<< "empty snapshot context" << dendl;
- librados::AioCompletion *comp =
- librados::Rados::aio_create_completion(create_callback_context(), NULL,
- rados_ctx_cb);
+ librados::AioCompletion *comp = util::create_rados_safe_callback(this);
r = m_ictx->md_ctx.aio_operate(m_oid, comp, ©up_op, 0, snaps);
assert(r == 0);
comp->release();
assert(write_op.size() != 0);
snaps.insert(snaps.end(), snapc.snaps.begin(), snapc.snaps.end());
- librados::AioCompletion *comp =
- librados::Rados::aio_create_completion(create_callback_context(), NULL,
- rados_ctx_cb);
+ librados::AioCompletion *comp = util::create_rados_safe_callback(this);
r = m_ictx->data_ctx.aio_operate(m_oid, comp, &write_op);
assert(r == 0);
comp->release();
{
m_state = STATE_READ_FROM_PARENT;
AioCompletion *comp = aio_create_completion_internal(
- create_callback_context(), rbd_ctx_cb);
+ util::create_context_callback(this), rbd_ctx_cb);
ldout(m_ictx->cct, 20) << __func__ << " " << this
<< ": completion " << comp
boost::lambda::_1, m_ictx, m_object_no, &m_snap_ids,
boost::lambda::_2));
AsyncObjectThrottle<> *throttle = new AsyncObjectThrottle<>(
- NULL, *m_ictx, context_factory, create_callback_context(), NULL, 0,
- m_snap_ids.size());
+ NULL, *m_ictx, context_factory, util::create_context_callback(this),
+ NULL, 0, m_snap_ids.size());
throttle->start_ops(m_ictx->concurrent_management_ops);
}
return false;
}
-
- Context *CopyupRequest::create_callback_context()
- {
- return new FunctionContext(boost::bind(&CopyupRequest::complete, this, _1));
- }
}
void send();
void queue_send();
+ void complete(int r);
+
private:
/**
* Copyup requests go through the following state machine to read from the
void complete_requests(int r);
- void complete(int r);
bool should_complete(int r);
void remove_from_list();
bool send_object_map();
bool send_copyup();
-
- Context *create_callback_context();
};
}
#include "librbd/DiffIterate.h"
#include "librbd/ImageCtx.h"
#include "librbd/internal.h"
+#include "librbd/Utils.h"
#include "include/rados/librados.hpp"
#include "include/interval_set.h"
#include "common/errno.h"
void send() {
C_OrderedThrottle *ctx = m_diff_context.throttle.start_op(this);
librados::AioCompletion *rados_completion =
- librados::Rados::aio_create_completion(ctx, NULL, rados_ctx_cb);
+ util::create_rados_safe_callback(ctx);
librados::ObjectReadOperation op;
op.list_snaps(&m_snap_set, &m_snap_ret);
#include "librbd/AioCompletion.h"
#include "librbd/ObjectMap.h"
#include "librbd/Journal.h"
+#include "librbd/Utils.h"
#include "include/assert.h"
}
}
- librados::AioCompletion *rados_completion =
- librados::Rados::aio_create_completion(req, context_cb, NULL);
librados::ObjectReadOperation op;
op.read(off, len, pbl, NULL);
op.set_op_flags2(op_flags);
int flags = m_ictx->get_read_flags(snapid);
+
+ librados::AioCompletion *rados_completion =
+ util::create_rados_ack_callback(req);
int r = m_ictx->data_ctx.aio_operate(oid.name, rados_completion, &op,
flags, NULL);
rados_completion->release();
librbd/parent_types.h \
librbd/SnapInfo.h \
librbd/TaskFinisher.h \
+ librbd/Utils.h \
librbd/WatchNotifyTypes.h \
librbd/object_map/InvalidateRequest.h \
librbd/object_map/Request.h \
#include "librbd/object_map/SnapshotRemoveRequest.h"
#include "librbd/object_map/SnapshotRollbackRequest.h"
#include "librbd/object_map/UpdateRequest.h"
+#include "librbd/Utils.h"
#include "common/dout.h"
#include "common/errno.h"
#include "include/stringify.h"
cls_client::object_map_save(&op, m_object_map);
std::string oid(object_map_name(m_image_ctx.id, m_snap_id));
- librados::AioCompletion *comp = librados::Rados::aio_create_completion(
- on_finish, NULL, rados_ctx_cb);
+ librados::AioCompletion *comp = util::create_rados_safe_callback(on_finish);
int r = m_image_ctx.md_ctx.aio_operate(oid, comp, &op);
assert(r == 0);
--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#ifndef CEPH_LIBRBD_UTILS_H
+#define CEPH_LIBRBD_UTILS_H
+
+#include "include/rados/librados.hpp"
+#include "include/Context.h"
+#include <type_traits>
+
+class Context;
+
+namespace librbd {
+
+class ImageCtx;
+
+namespace util {
+
+namespace detail {
+
+template <typename T>
+void rados_callback(rados_completion_t c, void *arg) {
+ reinterpret_cast<T*>(arg)->complete(rados_aio_get_return_value(c));
+}
+
+template <typename T, Context*(T::*MF)(int*), bool destroy>
+void rados_state_callback(rados_completion_t c, void *arg) {
+ T *obj = reinterpret_cast<T*>(arg);
+ int r = rados_aio_get_return_value(c);
+ Context *on_finish = (obj->*MF)(&r);
+ if (on_finish != nullptr) {
+ on_finish->complete(r);
+ if (destroy) {
+ delete obj;
+ }
+ }
+}
+
+template <typename T, void (T::*MF)(int)>
+class C_CallbackAdapter : public Context {
+ T *obj;
+public:
+ C_CallbackAdapter(T *obj) : obj(obj) {
+ }
+
+protected:
+ virtual void finish(int r) {
+ (obj->*MF)(r);
+ }
+};
+
+template <typename T, Context*(T::*MF)(int*), bool destroy>
+class C_StateCallbackAdapter : public Context {
+ T *obj;
+public:
+ C_StateCallbackAdapter(T *obj) : obj(obj){
+ }
+
+protected:
+ virtual void complete(int r) override {
+ Context *on_finish = (obj->*MF)(&r);
+ if (on_finish != nullptr) {
+ on_finish->complete(r);
+ if (destroy) {
+ delete obj;
+ }
+ }
+ Context::complete(r);
+ }
+ virtual void finish(int r) override {
+ }
+};
+
+template <typename WQ>
+struct C_AsyncCallback : public Context {
+ WQ *op_work_queue;
+ Context *on_finish;
+
+ C_AsyncCallback(WQ *op_work_queue, Context *on_finish)
+ : op_work_queue(op_work_queue), on_finish(on_finish) {
+ }
+ virtual void finish(int r) {
+ op_work_queue->queue(on_finish, r);
+ }
+};
+
+} // namespace detail
+
+template <typename T>
+librados::AioCompletion *create_rados_ack_callback(T *obj) {
+ return librados::Rados::aio_create_completion(
+ obj, &detail::rados_callback<T>, nullptr);
+}
+
+template <typename T, Context*(T::*MF)(int*), bool destroy=true>
+librados::AioCompletion *create_rados_ack_callback(T *obj) {
+ return librados::Rados::aio_create_completion(
+ obj, &detail::rados_state_callback<T, MF, destroy>, nullptr);
+}
+
+template <typename T>
+librados::AioCompletion *create_rados_safe_callback(T *obj) {
+ return librados::Rados::aio_create_completion(
+ obj, nullptr, &detail::rados_callback<T>);
+}
+
+template <typename T, Context*(T::*MF)(int*), bool destroy=true>
+librados::AioCompletion *create_rados_safe_callback(T *obj) {
+ return librados::Rados::aio_create_completion(
+ obj, nullptr, &detail::rados_state_callback<T, MF, destroy>);
+}
+
+template <typename T, void(T::*MF)(int) = &T::complete>
+Context *create_context_callback(T *obj) {
+ return new detail::C_CallbackAdapter<T, MF>(obj);
+}
+
+template <typename T, Context*(T::*MF)(int*), bool destroy=true>
+Context *create_context_callback(T *obj) {
+ return new detail::C_StateCallbackAdapter<T, MF, destroy>(obj);
+}
+
+template <typename I>
+Context *create_async_context_callback(I &image_ctx, Context *on_finish) {
+ // use async callback to acquire a clean lock context
+ return new detail::C_AsyncCallback<
+ typename std::decay<decltype(*image_ctx.op_work_queue)>::type>(
+ image_ctx.op_work_queue, on_finish);
+}
+
+} // namespace util
+} // namespace librbd
+
+#endif // CEPH_LIBRBD_UTILS_H
#include "librbd/operation/SnapshotRollbackRequest.h"
#include "librbd/operation/SnapshotUnprotectRequest.h"
#include "librbd/operation/TrimRequest.h"
+#include "librbd/Utils.h"
#include "include/util.h"
#include <boost/bind.hpp>
return r;
}
- void rados_req_cb(rados_completion_t c, void *arg)
- {
- AioObjectRequest *req = reinterpret_cast<AioObjectRequest *>(arg);
- req->complete(rados_aio_get_return_value(c));
- }
-
- void rados_ctx_cb(rados_completion_t c, void *arg)
- {
- Context *comp = reinterpret_cast<Context *>(arg);
- comp->complete(rados_aio_get_return_value(c));
- }
-
// validate extent against image size; clip to image size if necessary
int clip_io(ImageCtx *ictx, uint64_t off, uint64_t *len)
{
callback_t cb_complete);
// raw callbacks
- void rados_req_cb(rados_completion_t cb, void *arg);
- void rados_ctx_cb(rados_completion_t cb, void *arg);
void rbd_req_cb(completion_t cb, void *arg);
void rbd_ctx_cb(completion_t cb, void *arg);
}
#include "librbd/ObjectMap.h"
#include "librbd/operation/ResizeRequest.h"
#include "librbd/operation/TrimRequest.h"
+#include "librbd/Utils.h"
#include <boost/lambda/bind.hpp>
#include <boost/lambda/construct.hpp>
ldout(image_ctx.cct, 5) << m_oid << " C_VerifyObject::send_list_snaps"
<< dendl;
- librados::AioCompletion *comp = librados::Rados::aio_create_completion(
- this, NULL, rados_ctx_cb);
-
librados::ObjectReadOperation op;
op.list_snaps(&m_snap_set, &m_snap_list_ret);
+ librados::AioCompletion *comp = util::create_rados_safe_callback(this);
int r = m_io_ctx.aio_operate(m_oid, comp, &op, NULL);
assert(r == 0);
comp->release();
#include "librbd/AsyncObjectThrottle.h"
#include "librbd/ImageCtx.h"
#include "librbd/ObjectMap.h"
+#include "librbd/Utils.h"
#include "librbd/operation/ResizeRequest.h"
#include "osdc/Striper.h"
#include <boost/lambda/bind.hpp>
std::string oid = image_ctx.get_object_name(m_object_num);
- librados::AioCompletion *rados_completion =
- librados::Rados::aio_create_completion(this, NULL, rados_ctx_cb);
librados::ObjectWriteOperation op;
op.selfmanaged_snap_rollback(m_snap_id);
+
+ librados::AioCompletion *rados_completion =
+ util::create_rados_safe_callback(this);
image_ctx.data_ctx.aio_operate(oid, rados_completion, &op);
rados_completion->release();
return 0;
#include "librbd/ImageWatcher.h"
#include "librbd/internal.h"
#include "librbd/ObjectMap.h"
+#include "librbd/Utils.h"
#include "common/ContextCompletion.h"
#include "common/dout.h"
#include "common/errno.h"
ldout(image_ctx.cct, 10) << "removing " << oid << dendl;
librados::AioCompletion *rados_completion =
- librados::Rados::aio_create_completion(this, NULL, rados_ctx_cb);
+ util::create_rados_safe_callback(this);
int r = image_ctx.data_ctx.aio_remove(oid, rados_completion);
assert(r == 0);
rados_completion->release();