std::unique_lock image_locker{m_dst_image_ctx->image_lock};
std::swap(m_dst_image_ctx->object_map, m_object_map);
}
- delete m_object_map;
+ m_object_map->put();
send_copy_metadata();
}
namespace librbd {
using namespace exclusive_lock;
+using librbd::util::create_context_callback;
template <typename I>
using ML = ManagedLock<I>;
template <typename I>
ExclusiveLock<I>::ExclusiveLock(I &image_ctx)
- : ML<I>(image_ctx.md_ctx, image_ctx.op_work_queue, image_ctx.header_oid,
+ : RefCountedObject(image_ctx.cct),
+ ML<I>(image_ctx.md_ctx, image_ctx.op_work_queue, image_ctx.header_oid,
image_ctx.image_watcher, managed_lock::EXCLUSIVE,
image_ctx.config.template get_val<bool>("rbd_blacklist_on_break_lock"),
image_ctx.config.template get_val<uint64_t>("rbd_blacklist_expire_seconds")),
template <typename I>
void ExclusiveLock<I>::init(uint64_t features, Context *on_init) {
ceph_assert(ceph_mutex_is_locked(m_image_ctx.owner_lock));
+
+ on_init = create_context_callback<Context>(on_init, this);
+
ldout(m_image_ctx.cct, 10) << dendl;
{
void ExclusiveLock<I>::shut_down(Context *on_shut_down) {
ldout(m_image_ctx.cct, 10) << dendl;
+ on_shut_down = create_context_callback<Context>(on_shut_down, this);
+
ML<I>::shut_down(on_shut_down);
// if stalled in request state machine -- abort
#include "common/AsyncOpTracker.h"
#include "librbd/ManagedLock.h"
#include "librbd/exclusive_lock/Policy.h"
+#include "common/RefCountedObj.h"
namespace librbd {
template <typename ImageCtxT = ImageCtx>
-class ExclusiveLock : public ManagedLock<ImageCtxT> {
+class ExclusiveLock : public RefCountedObject,
+ public ManagedLock<ImageCtxT> {
public:
static ExclusiveLock *create(ImageCtxT &image_ctx) {
return new ExclusiveLock<ImageCtxT>(image_ctx);
template <typename I>
Journal<I>::Journal(I &image_ctx)
- : m_image_ctx(image_ctx), m_journaler(NULL),
+ : RefCountedObject(image_ctx.cct),
+ m_image_ctx(image_ctx), m_journaler(NULL),
m_state(STATE_UNINITIALIZED),
m_error_result(0), m_replay_handler(this), m_close_pending(false),
m_event_tid(0),
CephContext *cct = m_image_ctx.cct;
ldout(cct, 20) << this << " " << __func__ << dendl;
+ on_finish = create_context_callback<Context>(on_finish, this);
+
on_finish = create_async_context_callback(m_image_ctx, on_finish);
// inject our handler into the object dispatcher chain
CephContext *cct = m_image_ctx.cct;
ldout(cct, 20) << this << " " << __func__ << dendl;
+ on_finish = create_context_callback<Context>(on_finish, this);
+
on_finish = new LambdaContext([this, on_finish](int r) {
// remove our handler from object dispatcher chain - preserve error
auto ctx = new LambdaContext([on_finish, r](int _) {
ldout(cct, 20) << this << " " << __func__ << ": tid=" << tid << ", "
<< "on_safe=" << on_safe << dendl;
+ on_safe = create_context_callback<Context>(on_safe, this);
+
Future future;
{
std::lock_guard event_locker{m_event_lock};
ldout(cct, 20) << this << " " << __func__ << ": tid=" << tid << ", "
<< "on_safe=" << on_safe << dendl;
+ on_safe = create_context_callback<Context>(on_safe, this);
+
std::lock_guard event_locker{m_event_lock};
wait_event(m_lock, tid, on_safe);
}
#include "include/rados/librados_fwd.hpp"
#include "common/AsyncOpTracker.h"
#include "common/Cond.h"
+#include "common/RefCountedObj.h"
#include "common/WorkQueue.h"
#include "journal/Future.h"
#include "journal/JournalMetadataListener.h"
namespace journal { template <typename> class Replay; }
template <typename ImageCtxT = ImageCtx>
-class Journal {
+class Journal : public RefCountedObject {
public:
/**
* @verbatim
namespace librbd {
+using librbd::util::create_context_callback;
+
template <typename I>
ObjectMap<I>::ObjectMap(I &image_ctx, uint64_t snap_id)
- : m_image_ctx(image_ctx), m_snap_id(snap_id),
+ : RefCountedObject(image_ctx.cct),
+ m_image_ctx(image_ctx), m_snap_id(snap_id),
m_lock(ceph::make_shared_mutex(util::unique_lock_name("librbd::ObjectMap::lock", this))),
m_update_guard(new UpdateGuard(m_image_ctx.cct)) {
}
template <typename I>
void ObjectMap<I>::open(Context *on_finish) {
+ Context *ctx = create_context_callback<Context>(on_finish, this);
+
auto req = object_map::RefreshRequest<I>::create(
- m_image_ctx, &m_lock, &m_object_map, m_snap_id, on_finish);
+ m_image_ctx, &m_lock, &m_object_map, m_snap_id, ctx);
req->send();
}
template <typename I>
void ObjectMap<I>::close(Context *on_finish) {
+ Context *ctx = create_context_callback<Context>(on_finish, this);
+
if (m_snap_id != CEPH_NOSNAP) {
- m_image_ctx.op_work_queue->queue(on_finish, 0);
+ m_image_ctx.op_work_queue->queue(ctx, 0);
return;
}
- auto req = object_map::UnlockRequest<I>::create(m_image_ctx, on_finish);
+ auto req = object_map::UnlockRequest<I>::create(m_image_ctx, ctx);
req->send();
}
ceph_assert(ceph_mutex_is_locked(m_image_ctx.image_lock));
std::unique_lock locker{m_lock};
+ Context *ctx = create_context_callback<Context>(on_finish, this);
+
object_map::SnapshotRollbackRequest *req =
- new object_map::SnapshotRollbackRequest(m_image_ctx, snap_id, on_finish);
+ new object_map::SnapshotRollbackRequest(m_image_ctx, snap_id, ctx);
req->send();
}
ceph_assert((m_image_ctx.features & RBD_FEATURE_OBJECT_MAP) != 0);
ceph_assert(snap_id != CEPH_NOSNAP);
+ Context *ctx = create_context_callback<Context>(on_finish, this);
+
object_map::SnapshotCreateRequest *req =
new object_map::SnapshotCreateRequest(m_image_ctx, &m_lock, &m_object_map,
- snap_id, on_finish);
+ snap_id, ctx);
req->send();
}
ceph_assert((m_image_ctx.features & RBD_FEATURE_OBJECT_MAP) != 0);
ceph_assert(snap_id != CEPH_NOSNAP);
+ Context *ctx = create_context_callback<Context>(on_finish, this);
+
object_map::SnapshotRemoveRequest *req =
new object_map::SnapshotRemoveRequest(m_image_ctx, &m_lock, &m_object_map,
- snap_id, on_finish);
+ snap_id, ctx);
req->send();
}
}
cls_client::object_map_save(&op, m_object_map);
+ Context *ctx = create_context_callback<Context>(on_finish, this);
+
std::string oid(object_map_name(m_image_ctx.id, m_snap_id));
- librados::AioCompletion *comp = util::create_rados_callback(on_finish);
+ librados::AioCompletion *comp = util::create_rados_callback(ctx);
int r = m_image_ctx.md_ctx.aio_operate(oid, comp, &op);
ceph_assert(r == 0);
ceph_assert(m_image_ctx.exclusive_lock == nullptr ||
m_image_ctx.exclusive_lock->is_lock_owner());
+ Context *ctx = create_context_callback<Context>(on_finish, this);
+
object_map::ResizeRequest *req = new object_map::ResizeRequest(
m_image_ctx, &m_lock, &m_object_map, m_snap_id, new_size,
- default_object_state, on_finish);
+ default_object_state, ctx);
req->send();
}
#include "include/rbd/object_map_types.h"
#include "common/bit_vector.hpp"
#include "common/RWLock.h"
+#include "common/RefCountedObj.h"
#include "librbd/Utils.h"
#include <boost/optional.hpp>
class ImageCtx;
template <typename ImageCtxT = ImageCtx>
-class ObjectMap {
+class ObjectMap : public RefCountedObject {
public:
static ObjectMap *create(ImageCtxT &image_ctx, uint64_t snap_id) {
return new ObjectMap(image_ctx, snap_id);
Context *ctx = util::create_async_context_callback(
image_ctx, util::create_context_callback<
- C_InvokeAsyncRequest<I>,
- &C_InvokeAsyncRequest<I>::handle_acquire_exclusive_lock>(this));
+ C_InvokeAsyncRequest<I>,
+ &C_InvokeAsyncRequest<I>::handle_acquire_exclusive_lock>(
+ this, image_ctx.exclusive_lock));
if (request_lock) {
// current lock owner doesn't support op -- try to perform
std::shared_lock image_locker{m_image_ctx.image_lock};
using klass = PostAcquireRequest<I>;
Context *ctx = create_context_callback<
- klass, &klass::handle_allocate_journal_tag>(this);
+ klass, &klass::handle_allocate_journal_tag>(this, m_journal);
m_image_ctx.get_journal_policy()->allocate_tag_on_lock(ctx);
}
if (r < 0) {
lderr(cct) << "failed to open object map: " << cpp_strerror(r) << dendl;
- delete m_object_map;
+ m_object_map->put();
m_object_map = nullptr;
if (r != -EFBIG) {
m_image_ctx.object_map = nullptr;
m_image_ctx.journal = nullptr;
- delete m_object_map;
- delete m_journal;
+ if (m_object_map) {
+ m_object_map->put();
+ }
+ if (m_journal) {
+ m_journal->put();
+ }
ceph_assert(m_error_result < 0);
}
lderr(cct) << "failed to close journal: " << cpp_strerror(r) << dendl;
}
- delete m_journal;
+ m_journal->put();
+ m_journal = nullptr;
send_close_object_map();
}
using klass = PreReleaseRequest<I>;
Context *ctx = create_context_callback<
- klass, &klass::handle_close_object_map>(this);
+ klass, &klass::handle_close_object_map>(this, m_object_map);
m_object_map->close(ctx);
}
if (r < 0) {
lderr(cct) << "failed to close object map: " << cpp_strerror(r) << dendl;
}
+ m_object_map->put();
- delete m_object_map;
send_unlock();
}
// if reading a snapshot -- possible object map is open
std::unique_lock image_locker{m_image_ctx->image_lock};
- if (m_exclusive_lock == nullptr) {
- delete m_image_ctx->object_map;
+ if (m_exclusive_lock == nullptr && m_image_ctx->object_map) {
+ m_image_ctx->object_map->put();
m_image_ctx->object_map = nullptr;
}
}
ceph_assert(m_image_ctx->object_map == nullptr);
}
- delete m_exclusive_lock;
+ m_exclusive_lock->put();
m_exclusive_lock = nullptr;
save_result(r);
m_image_ctx->set_journal_policy(new journal::DisabledPolicy());
}
+ m_exclusive_lock = m_image_ctx->exclusive_lock;
+
auto ctx = create_context_callback<
- PreRemoveRequest<I>, &PreRemoveRequest<I>::handle_exclusive_lock>(this);
+ PreRemoveRequest<I>, &PreRemoveRequest<I>::handle_exclusive_lock>(this, m_exclusive_lock);
- m_image_ctx->exclusive_lock->try_acquire_lock(ctx);
+ m_exclusive_lock->try_acquire_lock(ctx);
}
template <typename I>
auto cct = m_image_ctx->cct;
ldout(cct, 5) << "r=" << r << dendl;
- delete m_exclusive_lock;
+ m_exclusive_lock->put();
m_exclusive_lock = nullptr;
if (r < 0) {
if (*result < 0) {
lderr(cct) << "failed to open object map: " << cpp_strerror(*result)
<< dendl;
- delete m_object_map;
+ m_object_map->put();
m_object_map = nullptr;
if (*result != -EFBIG) {
}
ceph_assert(m_exclusive_lock != nullptr);
- delete m_exclusive_lock;
+ m_exclusive_lock->put();
m_exclusive_lock = nullptr;
return send_v2_close_journal();
}
ceph_assert(m_journal != nullptr);
- delete m_journal;
+ m_journal->put();
m_journal = nullptr;
ceph_assert(m_blocked_writes);
}
ceph_assert(m_object_map != nullptr);
- delete m_object_map;
+
+ m_object_map->put();
m_object_map = nullptr;
return send_flush_aio();
SetSnapRequest<I>::~SetSnapRequest() {
ceph_assert(!m_writes_blocked);
delete m_refresh_parent;
- delete m_object_map;
- delete m_exclusive_lock;
+ if (m_object_map) {
+ m_object_map->put();
+ }
+ if (m_exclusive_lock) {
+ m_exclusive_lock->put();
+ }
}
template <typename I>
if (*result < 0) {
lderr(cct) << "failed to open object map: " << cpp_strerror(*result)
<< dendl;
- delete m_object_map;
+ m_object_map->put();
m_object_map = nullptr;
}
<< " " << __func__ << ": "
namespace librbd {
+
+using util::create_context_callback;
+
namespace io {
namespace {
} else {
// stall IO until the acquire completes
++m_io_blockers;
- m_image_ctx.exclusive_lock->acquire_lock(new C_AcquireLock(this, item));
+ Context *ctx = new C_AcquireLock(this, item);
+ ctx = create_context_callback<
+ Context, &Context::complete>(
+ ctx, m_image_ctx.exclusive_lock);
+ m_image_ctx.exclusive_lock->acquire_lock(ctx);
}
} else {
// raced with the exclusive lock being disabled
namespace journal {
using librbd::util::data_object_name;
+using util::create_context_callback;
namespace {
*on_finish = new C_CommitIOEvent<I>(m_image_ctx, m_journal, object_no,
object_off, object_len, *journal_tid,
*object_dispatch_flags, *on_finish);
+ *on_finish = create_context_callback<
+ Context, &Context::complete>(*on_finish, m_journal);
*dispatch_result = io::DISPATCH_RESULT_CONTINUE;
wait_or_flush_event(*journal_tid, *object_dispatch_flags, on_dispatched);
*on_finish = new C_CommitIOEvent<I>(m_image_ctx, m_journal, object_no,
object_off, data.length(), *journal_tid,
*object_dispatch_flags, *on_finish);
+ *on_finish = create_context_callback<
+ Context, &Context::complete>(*on_finish, m_journal);
*dispatch_result = io::DISPATCH_RESULT_CONTINUE;
wait_or_flush_event(*journal_tid, *object_dispatch_flags, on_dispatched);
*on_finish = new C_CommitIOEvent<I>(m_image_ctx, m_journal, object_no,
object_off, object_len, *journal_tid,
*object_dispatch_flags, *on_finish);
+ *on_finish = create_context_callback<
+ Context, &Context::complete>(*on_finish, m_journal);
*dispatch_result = io::DISPATCH_RESULT_CONTINUE;
wait_or_flush_event(*journal_tid, *object_dispatch_flags, on_dispatched);
object_off, write_data.length(),
*journal_tid, *object_dispatch_flags,
*on_finish);
+ *on_finish = create_context_callback<
+ Context, &Context::complete>(*on_finish, m_journal);
*dispatch_result = io::DISPATCH_RESULT_CONTINUE;
wait_or_flush_event(*journal_tid, *object_dispatch_flags, on_dispatched);
ldout(cct, 20) << object_no << " " << object_off << "~" << object_len
<< dendl;
- auto ctx = new C_CommitIOEvent<I>(m_image_ctx, m_journal, object_no,
- object_off, object_len, journal_tid, false,
- nullptr);
+ Context *ctx = new C_CommitIOEvent<I>(m_image_ctx, m_journal, object_no,
+ object_off, object_len, journal_tid, false,
+ nullptr);
if (new_journal_tid != 0) {
// ensure new journal event is safely committed to disk before
// committing old event
m_journal->flush_event(new_journal_tid, ctx);
} else {
+ ctx = create_context_callback<
+ Context, &Context::complete>(ctx, m_journal);
ctx->complete(0);
}
}
template <typename I>
Replay<I>::~Replay() {
+ std::lock_guard locker{m_lock};
ceph_assert(m_in_flight_aio_flush == 0);
ceph_assert(m_in_flight_aio_modify == 0);
ceph_assert(m_aio_modify_unsafe_contexts.empty());
ldout(cct, 20) << dendl;
auto ctx = create_context_callback<
- DemoteRequest<I>, &DemoteRequest<I>::handle_acquire_lock>(this);
+ DemoteRequest<I>,
+ &DemoteRequest<I>::handle_acquire_lock>(this, m_image_ctx.exclusive_lock);
m_image_ctx.exclusive_lock->acquire_lock(ctx);
m_image_ctx.owner_lock.unlock_shared();
}
}
auto ctx = create_context_callback<
- DemoteRequest<I>, &DemoteRequest<I>::handle_release_lock>(this);
+ DemoteRequest<I>,
+ &DemoteRequest<I>::handle_release_lock>(this, m_image_ctx.exclusive_lock);
m_image_ctx.exclusive_lock->release_lock(ctx);
m_image_ctx.owner_lock.unlock_shared();
}
}
}
- send_acquire_exclusive_lock();
- return nullptr;
+ return send_acquire_exclusive_lock(result);
}
template <typename I>
-void DisableFeaturesRequest<I>::send_acquire_exclusive_lock() {
+Context *DisableFeaturesRequest<I>::send_acquire_exclusive_lock(int *result) {
I &image_ctx = this->m_image_ctx;
CephContext *cct = image_ctx.cct;
ldout(cct, 20) << this << " " << __func__ << dendl;
- Context *ctx = create_context_callback<
- DisableFeaturesRequest<I>,
- &DisableFeaturesRequest<I>::handle_acquire_exclusive_lock>(this);
-
{
std::unique_lock locker{image_ctx.owner_lock};
// if disabling features w/ exclusive lock supported, we need to
// acquire the lock to temporarily block IO against the image
if (image_ctx.exclusive_lock != nullptr &&
- !image_ctx.exclusive_lock->is_lock_owner()) {
+ !image_ctx.exclusive_lock->is_lock_owner()) {
m_acquired_lock = true;
+ Context *ctx = create_context_callback<
+ DisableFeaturesRequest<I>,
+ &DisableFeaturesRequest<I>::handle_acquire_exclusive_lock>(
+ this, image_ctx.exclusive_lock);
image_ctx.exclusive_lock->acquire_lock(ctx);
- return;
+ return nullptr;
}
}
- ctx->complete(0);
+ return handle_acquire_exclusive_lock(result);
}
template <typename I>
}
ceph_assert(m_journal != nullptr);
- delete m_journal;
+ m_journal->put();
m_journal = nullptr;
send_remove_journal();
Context *ctx = create_context_callback<
DisableFeaturesRequest<I>,
- &DisableFeaturesRequest<I>::handle_release_exclusive_lock>(this);
+ &DisableFeaturesRequest<I>::handle_release_exclusive_lock>(
+ this, image_ctx.exclusive_lock);
image_ctx.exclusive_lock->release_lock(ctx);
}
void send_block_writes();
Context *handle_block_writes(int *result);
- void send_acquire_exclusive_lock();
+ Context *send_acquire_exclusive_lock(int *result);
Context *handle_acquire_exclusive_lock(int *result);
void send_get_mirror_mode();
namespace librbd {
namespace operation {
+using util::create_context_callback;
+
template <typename I>
void RebuildObjectMapRequest<I>::send() {
send_resize_object_map();
if (m_blocking_writes) {
image_ctx.io_work_queue->unblock_writes();
}
- delete m_object_map;
- delete m_snap_object_map;
+ if (m_object_map) {
+ m_object_map->put();
+ m_object_map = nullptr;
+ }
+ if (m_snap_object_map) {
+ m_snap_object_map->put();
+ m_snap_object_map = nullptr;
+ }
}
template <typename I>
if (*result < 0) {
lderr(cct) << this << " " << __func__ << ": failed to open object map: "
<< cpp_strerror(*result) << dendl;
- delete m_snap_object_map;
+ m_snap_object_map->put();
m_snap_object_map = nullptr;
}
if (*result < 0) {
lderr(cct) << this << " " << __func__ << ": failed to open object map: "
<< cpp_strerror(*result) << dendl;
- delete m_object_map;
+ m_object_map->put();
m_object_map = nullptr;
apply();
ldout(cct, 5) << this << " " << __func__ << dendl;
std::shared_lock owner_lock{image_ctx.owner_lock};
- Context *ctx = create_context_callback<
- SnapshotRollbackRequest<I>,
- &SnapshotRollbackRequest<I>::handle_invalidate_cache>(this);
- image_ctx.io_object_dispatcher->invalidate_cache(ctx);
+ if(m_object_map != nullptr) {
+ Context *ctx = create_context_callback<
+ SnapshotRollbackRequest<I>,
+ &SnapshotRollbackRequest<I>::handle_invalidate_cache>(this, m_object_map);
+ image_ctx.io_object_dispatcher->invalidate_cache(ctx);
+ }
+ else {
+ Context *ctx = create_context_callback<
+ SnapshotRollbackRequest<I>,
+ &SnapshotRollbackRequest<I>::handle_invalidate_cache>(this);
+ image_ctx.io_object_dispatcher->invalidate_cache(ctx);
+ }
return nullptr;
}