From 835989c71e873c4f3f7bf93cf474e0faab3ed043 Mon Sep 17 00:00:00 2001 From: Jason Dillaman Date: Wed, 19 Aug 2015 13:10:57 -0400 Subject: [PATCH] librbd: convert op state machines to templates Using templates allows the creation of mocked test cases to verify non-librados expectations. Signed-off-by: Jason Dillaman --- src/librbd/ImageCtx.h | 4 +- src/librbd/internal.cc | 40 ++-- src/librbd/operation/FlattenRequest.cc | 100 +++++---- src/librbd/operation/FlattenRequest.h | 13 +- .../operation/RebuildObjectMapRequest.cc | 102 +++++---- .../operation/RebuildObjectMapRequest.h | 11 +- src/librbd/operation/RenameRequest.cc | 87 +++++--- src/librbd/operation/RenameRequest.h | 7 +- src/librbd/operation/Request.cc | 47 ++-- src/librbd/operation/Request.h | 10 +- src/librbd/operation/ResizeRequest.cc | 200 +++++++++-------- src/librbd/operation/ResizeRequest.h | 12 +- src/librbd/operation/SnapshotCreateRequest.cc | 177 ++++++++------- src/librbd/operation/SnapshotCreateRequest.h | 7 +- .../operation/SnapshotProtectRequest.cc | 55 +++-- src/librbd/operation/SnapshotProtectRequest.h | 7 +- src/librbd/operation/SnapshotRemoveRequest.cc | 133 ++++++----- src/librbd/operation/SnapshotRemoveRequest.h | 7 +- src/librbd/operation/SnapshotRenameRequest.cc | 50 +++-- src/librbd/operation/SnapshotRenameRequest.h | 7 +- .../operation/SnapshotRollbackRequest.cc | 124 ++++++----- .../operation/SnapshotRollbackRequest.h | 7 +- .../operation/SnapshotUnprotectRequest.cc | 140 +++++++----- .../operation/SnapshotUnprotectRequest.h | 7 +- src/librbd/operation/TrimRequest.cc | 206 ++++++++++-------- src/librbd/operation/TrimRequest.h | 11 +- 26 files changed, 909 insertions(+), 662 deletions(-) diff --git a/src/librbd/ImageCtx.h b/src/librbd/ImageCtx.h index fdebf8943eb6b..4e00fe5a45969 100644 --- a/src/librbd/ImageCtx.h +++ b/src/librbd/ImageCtx.h @@ -49,7 +49,7 @@ namespace librbd { class AioCompletion; namespace operation { - class ResizeRequest; + template class ResizeRequest; } struct ImageCtx { @@ -140,7 +140,7 @@ namespace librbd { atomic_t async_request_seq; - xlist resize_reqs; + xlist*> resize_reqs; AioImageRequestWQ *aio_work_queue; xlist completed_reqs; diff --git a/src/librbd/internal.cc b/src/librbd/internal.cc index 260effcb2c5ae..1c7617459b54f 100644 --- a/src/librbd/internal.cc +++ b/src/librbd/internal.cc @@ -332,7 +332,7 @@ int invoke_async_request(ImageCtx *ictx, const std::string& request_type, C_SaferCond ctx; ictx->snap_lock.get_read(); - operation::TrimRequest *req = new operation::TrimRequest( + operation::TrimRequest<> *req = new operation::TrimRequest<>( *ictx, &ctx, ictx->size, newsize, prog_ctx); ictx->snap_lock.put_read(); req->send(); @@ -732,8 +732,8 @@ int invoke_async_request(ImageCtx *ictx, const std::string& request_type, return; } - operation::SnapshotCreateRequest *req = - new operation::SnapshotCreateRequest(*ictx, ctx, snap_name); + operation::SnapshotCreateRequest<> *req = + new operation::SnapshotCreateRequest<>(*ictx, ctx, snap_name); req->send(); } @@ -825,8 +825,8 @@ int invoke_async_request(ImageCtx *ictx, const std::string& request_type, } } - operation::SnapshotRemoveRequest *req = - new operation::SnapshotRemoveRequest(*ictx, ctx, snap_name, snap_id); + operation::SnapshotRemoveRequest<> *req = + new operation::SnapshotRemoveRequest<>(*ictx, ctx, snap_name, snap_id); req->send(); } @@ -896,8 +896,8 @@ int invoke_async_request(ImageCtx *ictx, const std::string& request_type, return; } - operation::SnapshotRenameRequest *req = - new operation::SnapshotRenameRequest(*ictx, ctx, src_snap_id, dst_name); + operation::SnapshotRenameRequest<> *req = + new operation::SnapshotRenameRequest<>(*ictx, ctx, src_snap_id, dst_name); req->send(); } @@ -969,8 +969,8 @@ int invoke_async_request(ImageCtx *ictx, const std::string& request_type, return; } - operation::SnapshotProtectRequest *request = - new operation::SnapshotProtectRequest(*ictx, ctx, snap_name); + operation::SnapshotProtectRequest<> *request = + new operation::SnapshotProtectRequest<>(*ictx, ctx, snap_name); request->send(); } @@ -1044,8 +1044,8 @@ int invoke_async_request(ImageCtx *ictx, const std::string& request_type, return; } - operation::SnapshotUnprotectRequest *request = - new operation::SnapshotUnprotectRequest(*ictx, ctx, snap_name); + operation::SnapshotUnprotectRequest<> *request = + new operation::SnapshotUnprotectRequest<>(*ictx, ctx, snap_name); request->send(); } @@ -1635,8 +1635,8 @@ int invoke_async_request(ImageCtx *ictx, const std::string& request_type, return; } - operation::RenameRequest *req = - new operation::RenameRequest(*ictx, ctx, dstname); + operation::RenameRequest<> *req = + new operation::RenameRequest<>(*ictx, ctx, dstname); req->send(); } @@ -2197,7 +2197,7 @@ int invoke_async_request(ImageCtx *ictx, const std::string& request_type, } } - operation::ResizeRequest *req = new operation::ResizeRequest( + operation::ResizeRequest<> *req = new operation::ResizeRequest<>( *ictx, ctx, size, prog_ctx); req->send(); } @@ -2563,9 +2563,9 @@ int invoke_async_request(ImageCtx *ictx, const std::string& request_type, // TODO need to wait for journal replay to complete (if enabled) C_SaferCond cond_ctx; - operation::SnapshotRollbackRequest *request = - new operation::SnapshotRollbackRequest(*ictx, &cond_ctx, snap_name, - snap_id, new_size, prog_ctx); + operation::SnapshotRollbackRequest<> *request = + new operation::SnapshotRollbackRequest<>(*ictx, &cond_ctx, snap_name, + snap_id, new_size, prog_ctx); request->send(); r = cond_ctx.wait(); if (r < 0) { @@ -3061,7 +3061,7 @@ int invoke_async_request(ImageCtx *ictx, const std::string& request_type, overlap_objects = Striper::get_num_objects(ictx->layout, overlap); } - operation::FlattenRequest *req = new operation::FlattenRequest( + operation::FlattenRequest<> *req = new operation::FlattenRequest<>( *ictx, ctx, object_size, overlap_objects, snapc, prog_ctx); req->send(); } @@ -3114,8 +3114,8 @@ int invoke_async_request(ImageCtx *ictx, const std::string& request_type, return; } - operation::RebuildObjectMapRequest *req = - new operation::RebuildObjectMapRequest(*ictx, ctx, prog_ctx); + operation::RebuildObjectMapRequest<> *req = + new operation::RebuildObjectMapRequest<>(*ictx, ctx, prog_ctx); req->send(); } diff --git a/src/librbd/operation/FlattenRequest.cc b/src/librbd/operation/FlattenRequest.cc index 2a08e4562dc27..4b089b4c806de 100644 --- a/src/librbd/operation/FlattenRequest.cc +++ b/src/librbd/operation/FlattenRequest.cc @@ -19,28 +19,30 @@ namespace librbd { namespace operation { -class C_FlattenObject : public C_AsyncObjectThrottle<> { +template +class C_FlattenObject : public C_AsyncObjectThrottle { public: - C_FlattenObject(AsyncObjectThrottle<> &throttle, ImageCtx *image_ctx, + C_FlattenObject(AsyncObjectThrottle &throttle, I *image_ctx, uint64_t object_size, ::SnapContext snapc, uint64_t object_no) - : C_AsyncObjectThrottle(throttle, *image_ctx), m_object_size(object_size), + : C_AsyncObjectThrottle(throttle, *image_ctx), m_object_size(object_size), m_snapc(snapc), m_object_no(object_no) { } virtual int send() { - assert(m_image_ctx.owner_lock.is_locked()); - CephContext *cct = m_image_ctx.cct; + I &image_ctx = this->m_image_ctx; + assert(image_ctx.owner_lock.is_locked()); + CephContext *cct = image_ctx.cct; - if (m_image_ctx.image_watcher->is_lock_supported() && - !m_image_ctx.image_watcher->is_lock_owner()) { + if (image_ctx.image_watcher->is_lock_supported() && + !image_ctx.image_watcher->is_lock_owner()) { ldout(cct, 1) << "lost exclusive lock during flatten" << dendl; return -ERESTART; } bufferlist bl; - string oid = m_image_ctx.get_object_name(m_object_no); - AioObjectWrite *req = new AioObjectWrite(&m_image_ctx, oid, m_object_no, 0, + string oid = image_ctx.get_object_name(m_object_no); + AioObjectWrite *req = new AioObjectWrite(&image_ctx, oid, m_object_no, 0, bl, m_snapc, this); if (!req->has_parent()) { // stop early if the parent went away - it just means @@ -59,15 +61,17 @@ private: uint64_t m_object_no; }; -bool FlattenRequest::should_complete(int r) { - CephContext *cct = m_image_ctx.cct; +template +bool FlattenRequest::should_complete(int r) { + I &image_ctx = this->m_image_ctx; + CephContext *cct = image_ctx.cct; ldout(cct, 5) << this << " should_complete: " << " r=" << r << dendl; if (r < 0 && !(r == -ENOENT && m_ignore_enoent) ) { lderr(cct) << "flatten encountered an error: " << cpp_strerror(r) << dendl; return true; } - RWLock::RLocker owner_locker(m_image_ctx.owner_lock); + RWLock::RLocker owner_locker(image_ctx.owner_lock); switch (m_state) { case STATE_FLATTEN_OBJECTS: ldout(cct, 5) << "FLATTEN_OBJECTS" << dendl; @@ -89,74 +93,80 @@ bool FlattenRequest::should_complete(int r) { return false; } -void FlattenRequest::send_op() { - assert(m_image_ctx.owner_lock.is_locked()); - CephContext *cct = m_image_ctx.cct; +template +void FlattenRequest::send_op() { + I &image_ctx = this->m_image_ctx; + assert(image_ctx.owner_lock.is_locked()); + CephContext *cct = image_ctx.cct; ldout(cct, 5) << this << " send" << dendl; m_state = STATE_FLATTEN_OBJECTS; - AsyncObjectThrottle<>::ContextFactory context_factory( - boost::lambda::bind(boost::lambda::new_ptr(), - boost::lambda::_1, &m_image_ctx, m_object_size, m_snapc, + typename AsyncObjectThrottle::ContextFactory context_factory( + boost::lambda::bind(boost::lambda::new_ptr >(), + boost::lambda::_1, &image_ctx, m_object_size, m_snapc, boost::lambda::_2)); - AsyncObjectThrottle<> *throttle = new AsyncObjectThrottle<>( - this, m_image_ctx, context_factory, create_callback_context(), &m_prog_ctx, + AsyncObjectThrottle *throttle = new AsyncObjectThrottle( + this, image_ctx, context_factory, this->create_callback_context(), &m_prog_ctx, 0, m_overlap_objects); - throttle->start_ops(m_image_ctx.concurrent_management_ops); + throttle->start_ops(image_ctx.concurrent_management_ops); } -bool FlattenRequest::send_update_header() { - assert(m_image_ctx.owner_lock.is_locked()); - CephContext *cct = m_image_ctx.cct; +template +bool FlattenRequest::send_update_header() { + I &image_ctx = this->m_image_ctx; + assert(image_ctx.owner_lock.is_locked()); + CephContext *cct = image_ctx.cct; ldout(cct, 5) << this << " send_update_header" << dendl; m_state = STATE_UPDATE_HEADER; // should have been canceled prior to releasing lock - assert(!m_image_ctx.image_watcher->is_lock_supported() || - m_image_ctx.image_watcher->is_lock_owner()); + assert(!image_ctx.image_watcher->is_lock_supported() || + image_ctx.image_watcher->is_lock_owner()); { - RWLock::RLocker parent_locker(m_image_ctx.parent_lock); + RWLock::RLocker parent_locker(image_ctx.parent_lock); // stop early if the parent went away - it just means // another flatten finished first, so this one is useless. - if (!m_image_ctx.parent) { + if (!image_ctx.parent) { ldout(cct, 5) << "image already flattened" << dendl; return true; } - m_parent_spec = m_image_ctx.parent_md.spec; + m_parent_spec = image_ctx.parent_md.spec; } m_ignore_enoent = true; // remove parent from this (base) image librados::ObjectWriteOperation op; - if (m_image_ctx.image_watcher->is_lock_supported()) { - m_image_ctx.image_watcher->assert_header_locked(&op); + if (image_ctx.image_watcher->is_lock_supported()) { + image_ctx.image_watcher->assert_header_locked(&op); } cls_client::remove_parent(&op); - librados::AioCompletion *rados_completion = create_callback_completion(); - int r = m_image_ctx.md_ctx.aio_operate(m_image_ctx.header_oid, + librados::AioCompletion *rados_completion = this->create_callback_completion(); + int r = image_ctx.md_ctx.aio_operate(image_ctx.header_oid, rados_completion, &op); assert(r == 0); rados_completion->release(); return false; } -bool FlattenRequest::send_update_children() { - assert(m_image_ctx.owner_lock.is_locked()); - CephContext *cct = m_image_ctx.cct; +template +bool FlattenRequest::send_update_children() { + I &image_ctx = this->m_image_ctx; + assert(image_ctx.owner_lock.is_locked()); + CephContext *cct = image_ctx.cct; // should have been canceled prior to releasing lock - assert(!m_image_ctx.image_watcher->is_lock_supported() || - m_image_ctx.image_watcher->is_lock_owner()); + assert(!image_ctx.image_watcher->is_lock_supported() || + image_ctx.image_watcher->is_lock_owner()); // if there are no snaps, remove from the children object as well // (if snapshots remain, they have their own parent info, and the child // will be removed when the last snap goes away) - RWLock::RLocker snap_locker(m_image_ctx.snap_lock); - if ((m_image_ctx.features & RBD_FEATURE_DEEP_FLATTEN) == 0 && - !m_image_ctx.snaps.empty()) { + RWLock::RLocker snap_locker(image_ctx.snap_lock); + if ((image_ctx.features & RBD_FEATURE_DEEP_FLATTEN) == 0 && + !image_ctx.snaps.empty()) { return true; } @@ -164,10 +174,10 @@ bool FlattenRequest::send_update_children() { m_state = STATE_UPDATE_CHILDREN; librados::ObjectWriteOperation op; - cls_client::remove_child(&op, m_parent_spec, m_image_ctx.id); + cls_client::remove_child(&op, m_parent_spec, image_ctx.id); - librados::AioCompletion *rados_completion = create_callback_completion(); - int r = m_image_ctx.md_ctx.aio_operate(RBD_CHILDREN, rados_completion, + librados::AioCompletion *rados_completion = this->create_callback_completion(); + int r = image_ctx.md_ctx.aio_operate(RBD_CHILDREN, rados_completion, &op); assert(r == 0); rados_completion->release(); @@ -176,3 +186,5 @@ bool FlattenRequest::send_update_children() { } // namespace operation } // namespace librbd + +template class librbd::operation::FlattenRequest; diff --git a/src/librbd/operation/FlattenRequest.h b/src/librbd/operation/FlattenRequest.h index 7a2b86e35df6b..693b051e14cf8 100644 --- a/src/librbd/operation/FlattenRequest.h +++ b/src/librbd/operation/FlattenRequest.h @@ -14,13 +14,14 @@ class ProgressContext; namespace operation { -class FlattenRequest : public Request +template +class FlattenRequest : public Request { public: - FlattenRequest(ImageCtx &image_ctx, Context *on_finish, - uint64_t object_size, uint64_t overlap_objects, - const ::SnapContext &snapc, ProgressContext &prog_ctx) - : Request(image_ctx, on_finish), m_object_size(object_size), + FlattenRequest(ImageCtxT &image_ctx, Context *on_finish, + uint64_t object_size, uint64_t overlap_objects, + const ::SnapContext &snapc, ProgressContext &prog_ctx) + : Request(image_ctx, on_finish), m_object_size(object_size), m_overlap_objects(overlap_objects), m_snapc(snapc), m_prog_ctx(prog_ctx), m_ignore_enoent(false) { @@ -84,4 +85,6 @@ private: } // namespace operation } // namespace librbd +extern template class librbd::operation::FlattenRequest; + #endif // CEPH_LIBRBD_OPERATION_FLATTEN_REQUEST_H diff --git a/src/librbd/operation/RebuildObjectMapRequest.cc b/src/librbd/operation/RebuildObjectMapRequest.cc index 803083c848c5c..2ed0cbecf9f5d 100644 --- a/src/librbd/operation/RebuildObjectMapRequest.cc +++ b/src/librbd/operation/RebuildObjectMapRequest.cc @@ -23,22 +23,25 @@ namespace operation { namespace { -class C_VerifyObject : public C_AsyncObjectThrottle<> { +template +class C_VerifyObject : public C_AsyncObjectThrottle { public: - C_VerifyObject(AsyncObjectThrottle<> &throttle, ImageCtx *image_ctx, + C_VerifyObject(AsyncObjectThrottle &throttle, I *image_ctx, uint64_t snap_id, uint64_t object_no) - : C_AsyncObjectThrottle(throttle, *image_ctx), m_snap_id(snap_id), - m_object_no(object_no), m_oid(m_image_ctx.get_object_name(m_object_no)) + : C_AsyncObjectThrottle(throttle, *image_ctx), m_snap_id(snap_id), + m_object_no(object_no), + m_oid(image_ctx->get_object_name(m_object_no)) { - m_io_ctx.dup(m_image_ctx.md_ctx); + m_io_ctx.dup(image_ctx->md_ctx); m_io_ctx.snap_set_read(CEPH_SNAPDIR); } virtual void complete(int r) { + I &image_ctx = this->m_image_ctx; if (should_complete(r)) { - ldout(m_image_ctx.cct, 20) << m_oid << " C_VerifyObject completed " + ldout(image_ctx.cct, 20) << m_oid << " C_VerifyObject completed " << dendl; - finish(r); + this->finish(r); delete this; } } @@ -58,7 +61,8 @@ private: int m_snap_list_ret; bool should_complete(int r) { - CephContext *cct = m_image_ctx.cct; + I &image_ctx = this->m_image_ctx; + CephContext *cct = image_ctx.cct; if (r == 0) { r = m_snap_list_ret; } @@ -74,9 +78,10 @@ private: } void send_list_snaps() { - assert(m_image_ctx.owner_lock.is_locked()); - ldout(m_image_ctx.cct, 5) << m_oid << " C_VerifyObject::send_list_snaps" - << dendl; + I &image_ctx = this->m_image_ctx; + assert(image_ctx.owner_lock.is_locked()); + 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); @@ -90,7 +95,8 @@ private: } uint8_t get_object_state() { - RWLock::RLocker snap_locker(m_image_ctx.snap_lock); + I &image_ctx = this->m_image_ctx; + RWLock::RLocker snap_locker(image_ctx.snap_lock); for (std::vector::const_iterator r = m_snap_set.clones.begin(); r != m_snap_set.clones.end(); ++r) { librados::snap_t from_snap_id; @@ -109,7 +115,7 @@ private: break; } - if ((m_image_ctx.features & RBD_FEATURE_FAST_DIFF) != 0 && + if ((image_ctx.features & RBD_FEATURE_FAST_DIFF) != 0 && from_snap_id != m_snap_id) { return OBJECT_EXISTS_CLEAN; } @@ -119,26 +125,28 @@ private: } uint64_t next_valid_snap_id(uint64_t snap_id) { - assert(m_image_ctx.snap_lock.is_locked()); + I &image_ctx = this->m_image_ctx; + assert(image_ctx.snap_lock.is_locked()); std::map::iterator it = - m_image_ctx.snap_info.lower_bound(snap_id); - if (it == m_image_ctx.snap_info.end()) { + image_ctx.snap_info.lower_bound(snap_id); + if (it == image_ctx.snap_info.end()) { return CEPH_NOSNAP; } return it->first; } bool update_object_map(uint8_t new_state) { - RWLock::RLocker owner_locker(m_image_ctx.owner_lock); - CephContext *cct = m_image_ctx.cct; + I &image_ctx = this->m_image_ctx; + RWLock::RLocker owner_locker(image_ctx.owner_lock); + CephContext *cct = image_ctx.cct; // should have been canceled prior to releasing lock - assert(!m_image_ctx.image_watcher->is_lock_supported() || - m_image_ctx.image_watcher->is_lock_owner()); + assert(!image_ctx.image_watcher->is_lock_supported() || + image_ctx.image_watcher->is_lock_owner()); - RWLock::WLocker l(m_image_ctx.object_map_lock); - uint8_t state = m_image_ctx.object_map[m_object_no]; + RWLock::WLocker l(image_ctx.object_map_lock); + uint8_t state = image_ctx.object_map[m_object_no]; if (state == OBJECT_EXISTS && new_state == OBJECT_NONEXISTENT && m_snap_id == CEPH_NOSNAP) { // might be writing object to OSD concurrently @@ -149,7 +157,7 @@ private: ldout(cct, 15) << m_oid << " C_VerifyObject::update_object_map " << static_cast(state) << "->" << static_cast(new_state) << dendl; - m_image_ctx.object_map[m_object_no] = new_state; + image_ctx.object_map[m_object_no] = new_state; } return true; } @@ -157,12 +165,13 @@ private: } // anonymous namespace - -void RebuildObjectMapRequest::send() { +template +void RebuildObjectMapRequest::send() { send_resize_object_map(); } -bool RebuildObjectMapRequest::should_complete(int r) { +template +bool RebuildObjectMapRequest::should_complete(int r) { CephContext *cct = m_image_ctx.cct; ldout(cct, 5) << this << " should_complete: " << " r=" << r << dendl; @@ -220,7 +229,8 @@ bool RebuildObjectMapRequest::should_complete(int r) { return false; } -void RebuildObjectMapRequest::send_resize_object_map() { +template +void RebuildObjectMapRequest::send_resize_object_map() { assert(m_image_ctx.owner_lock.is_locked()); CephContext *cct = m_image_ctx.cct; @@ -244,10 +254,11 @@ void RebuildObjectMapRequest::send_resize_object_map() { assert(!m_image_ctx.image_watcher->is_lock_supported() || m_image_ctx.image_watcher->is_lock_owner()); m_image_ctx.object_map.aio_resize(size, OBJECT_NONEXISTENT, - create_callback_context()); + this->create_callback_context()); } -void RebuildObjectMapRequest::send_trim_image() { +template +void RebuildObjectMapRequest::send_trim_image() { CephContext *cct = m_image_ctx.cct; RWLock::RLocker l(m_image_ctx.owner_lock); @@ -266,12 +277,14 @@ void RebuildObjectMapRequest::send_trim_image() { orig_size = m_image_ctx.get_object_size() * m_image_ctx.object_map.size(); } - TrimRequest *req = new TrimRequest(m_image_ctx, create_callback_context(), - orig_size, new_size, m_prog_ctx); + TrimRequest *req = new TrimRequest(m_image_ctx, + this->create_callback_context(), + orig_size, new_size, m_prog_ctx); req->send(); } -void RebuildObjectMapRequest::send_verify_objects() { +template +void RebuildObjectMapRequest::send_verify_objects() { assert(m_image_ctx.owner_lock.is_locked()); CephContext *cct = m_image_ctx.cct; @@ -292,16 +305,17 @@ void RebuildObjectMapRequest::send_verify_objects() { m_state = STATE_VERIFY_OBJECTS; ldout(cct, 5) << this << " send_verify_objects" << dendl; - AsyncObjectThrottle<>::ContextFactory context_factory( - boost::lambda::bind(boost::lambda::new_ptr(), + typename AsyncObjectThrottle::ContextFactory context_factory( + boost::lambda::bind(boost::lambda::new_ptr >(), boost::lambda::_1, &m_image_ctx, snap_id, boost::lambda::_2)); - AsyncObjectThrottle<> *throttle = new AsyncObjectThrottle<>( - this, m_image_ctx, context_factory, create_callback_context(), &m_prog_ctx, - 0, num_objects); + AsyncObjectThrottle *throttle = new AsyncObjectThrottle( + this, m_image_ctx, context_factory, this->create_callback_context(), + &m_prog_ctx, 0, num_objects); throttle->start_ops(cct->_conf->rbd_concurrent_management_ops); } -void RebuildObjectMapRequest::send_save_object_map() { +template +void RebuildObjectMapRequest::send_save_object_map() { assert(m_image_ctx.owner_lock.is_locked()); CephContext *cct = m_image_ctx.cct; @@ -311,10 +325,11 @@ void RebuildObjectMapRequest::send_save_object_map() { // should have been canceled prior to releasing lock assert(!m_image_ctx.image_watcher->is_lock_supported() || m_image_ctx.image_watcher->is_lock_owner()); - m_image_ctx.object_map.aio_save(create_callback_context()); + m_image_ctx.object_map.aio_save(this->create_callback_context()); } -void RebuildObjectMapRequest::send_update_header() { +template +void RebuildObjectMapRequest::send_update_header() { assert(m_image_ctx.owner_lock.is_locked()); // should have been canceled prior to releasing lock @@ -332,7 +347,7 @@ void RebuildObjectMapRequest::send_update_header() { uint64_t flags = RBD_FLAG_OBJECT_MAP_INVALID | RBD_FLAG_FAST_DIFF_INVALID; cls_client::set_flags(&op, m_image_ctx.snap_id, 0, flags); - librados::AioCompletion *comp = create_callback_completion(); + librados::AioCompletion *comp = this->create_callback_completion(); int r = m_image_ctx.md_ctx.aio_operate(m_image_ctx.header_oid, comp, &op); assert(r == 0); comp->release(); @@ -341,7 +356,8 @@ void RebuildObjectMapRequest::send_update_header() { m_image_ctx.update_flags(m_image_ctx.snap_id, flags, false); } -uint64_t RebuildObjectMapRequest::get_image_size() const { +template +uint64_t RebuildObjectMapRequest::get_image_size() const { assert(m_image_ctx.snap_lock.is_locked()); if (m_image_ctx.snap_id == CEPH_NOSNAP) { if (!m_image_ctx.resize_reqs.empty()) { @@ -355,3 +371,5 @@ uint64_t RebuildObjectMapRequest::get_image_size() const { } // namespace operation } // namespace librbd + +template class librbd::operation::RebuildObjectMapRequest; diff --git a/src/librbd/operation/RebuildObjectMapRequest.h b/src/librbd/operation/RebuildObjectMapRequest.h index 3ed49ba5d7f63..28361872ce331 100644 --- a/src/librbd/operation/RebuildObjectMapRequest.h +++ b/src/librbd/operation/RebuildObjectMapRequest.h @@ -13,12 +13,13 @@ class ProgressContext; namespace operation { -class RebuildObjectMapRequest : public AsyncRequest<> { +template +class RebuildObjectMapRequest : public AsyncRequest { public: - RebuildObjectMapRequest(ImageCtx &image_ctx, Context *on_finish, + RebuildObjectMapRequest(ImageCtxT &image_ctx, Context *on_finish, ProgressContext &prog_ctx) - : AsyncRequest(image_ctx, on_finish), m_image_ctx(image_ctx), + : AsyncRequest(image_ctx, on_finish), m_image_ctx(image_ctx), m_prog_ctx(prog_ctx), m_attempted_trim(false) { } @@ -60,7 +61,7 @@ private: STATE_UPDATE_HEADER }; - ImageCtx &m_image_ctx; + ImageCtxT &m_image_ctx; ProgressContext &m_prog_ctx; State m_state; bool m_attempted_trim; @@ -78,4 +79,6 @@ private: } // namespace operation } // namespace librbd +extern template class librbd::operation::RebuildObjectMapRequest; + #endif // CEPH_LIBRBD_OPERATION_REBUILD_OBJECT_MAP_REQUEST_H diff --git a/src/librbd/operation/RenameRequest.cc b/src/librbd/operation/RenameRequest.cc index 1a9c82da7bd1e..316229c66c7dc 100644 --- a/src/librbd/operation/RenameRequest.cc +++ b/src/librbd/operation/RenameRequest.cc @@ -17,19 +17,20 @@ namespace operation { namespace { +template std::ostream& operator<<(std::ostream& os, - const RenameRequest::State& state) { + const typename RenameRequest::State& state) { switch(state) { - case RenameRequest::STATE_READ_SOURCE_HEADER: + case RenameRequest::STATE_READ_SOURCE_HEADER: os << "READ_SOURCE_HEADER"; break; - case RenameRequest::STATE_WRITE_DEST_HEADER: + case RenameRequest::STATE_WRITE_DEST_HEADER: os << "WRITE_DEST_HEADER"; break; - case RenameRequest::STATE_UPDATE_DIRECTORY: + case RenameRequest::STATE_UPDATE_DIRECTORY: os << "UPDATE_DIRECTORY"; break; - case RenameRequest::STATE_REMOVE_SOURCE_HEADER: + case RenameRequest::STATE_REMOVE_SOURCE_HEADER: os << "REMOVE_SOURCE_HEADER"; break; default: @@ -41,21 +42,25 @@ std::ostream& operator<<(std::ostream& os, } // anonymous namespace -RenameRequest::RenameRequest(ImageCtx &image_ctx, Context *on_finish, - const std::string &dest_name) - : Request(image_ctx, on_finish), m_dest_name(dest_name), +template +RenameRequest::RenameRequest(I &image_ctx, Context *on_finish, + const std::string &dest_name) + : Request(image_ctx, on_finish), m_dest_name(dest_name), m_source_oid(image_ctx.old_format ? old_header_name(image_ctx.name) : id_obj_name(image_ctx.name)), m_dest_oid(image_ctx.old_format ? old_header_name(dest_name) : id_obj_name(dest_name)) { } -void RenameRequest::send_op() { +template +void RenameRequest::send_op() { send_read_source_header(); } -bool RenameRequest::should_complete(int r) { - CephContext *cct = m_image_ctx.cct; +template +bool RenameRequest::should_complete(int r) { + I &image_ctx = this->m_image_ctx; + CephContext *cct = image_ctx.cct; ldout(cct, 5) << this << " " << __func__ << ": state=" << m_state << ", " << "r=" << r << dendl; r = filter_state_return_code(r); @@ -64,7 +69,7 @@ bool RenameRequest::should_complete(int r) { return true; } - RWLock::RLocker owner_lock(m_image_ctx.owner_lock); + RWLock::RLocker owner_lock(image_ctx.owner_lock); bool finished = false; switch (m_state) { case STATE_READ_SOURCE_HEADER: @@ -86,8 +91,10 @@ bool RenameRequest::should_complete(int r) { return finished; } -int RenameRequest::filter_state_return_code(int r) { - CephContext *cct = m_image_ctx.cct; +template +int RenameRequest::filter_state_return_code(int r) { + I &image_ctx = this->m_image_ctx; + CephContext *cct = image_ctx.cct; if (m_state == STATE_REMOVE_SOURCE_HEADER && r < 0) { if (r != -ENOENT) { @@ -99,8 +106,10 @@ int RenameRequest::filter_state_return_code(int r) { return r; } -void RenameRequest::send_read_source_header() { - CephContext *cct = m_image_ctx.cct; +template +void RenameRequest::send_read_source_header() { + I &image_ctx = this->m_image_ctx; + CephContext *cct = image_ctx.cct; ldout(cct, 5) << this << " " << __func__ << dendl; m_state = STATE_READ_SOURCE_HEADER; @@ -109,15 +118,17 @@ void RenameRequest::send_read_source_header() { // TODO: old code read omap values but there are no omap values on the // old format header nor the new format id object - librados::AioCompletion *rados_completion = create_callback_completion(); - int r = m_image_ctx.md_ctx.aio_operate(m_source_oid, rados_completion, &op, - &m_header_bl); + librados::AioCompletion *rados_completion = this->create_callback_completion(); + int r = image_ctx.md_ctx.aio_operate(m_source_oid, rados_completion, &op, + &m_header_bl); assert(r == 0); rados_completion->release(); } -void RenameRequest::send_write_destination_header() { - CephContext *cct = m_image_ctx.cct; +template +void RenameRequest::send_write_destination_header() { + I &image_ctx = this->m_image_ctx; + CephContext *cct = image_ctx.cct; ldout(cct, 5) << this << " " << __func__ << dendl; m_state = STATE_WRITE_DEST_HEADER; @@ -125,51 +136,57 @@ void RenameRequest::send_write_destination_header() { op.create(true); op.write_full(m_header_bl); - librados::AioCompletion *rados_completion = create_callback_completion(); - int r = m_image_ctx.md_ctx.aio_operate(m_dest_oid, rados_completion, &op); + librados::AioCompletion *rados_completion = this->create_callback_completion(); + int r = image_ctx.md_ctx.aio_operate(m_dest_oid, rados_completion, &op); assert(r == 0); rados_completion->release(); } -void RenameRequest::send_update_directory() { - CephContext *cct = m_image_ctx.cct; +template +void RenameRequest::send_update_directory() { + I &image_ctx = this->m_image_ctx; + CephContext *cct = image_ctx.cct; ldout(cct, 5) << this << " " << __func__ << dendl; m_state = STATE_UPDATE_DIRECTORY; librados::ObjectWriteOperation op; - if (m_image_ctx.old_format) { + if (image_ctx.old_format) { bufferlist cmd_bl; bufferlist empty_bl; ::encode(static_cast<__u8>(CEPH_OSD_TMAP_SET), cmd_bl); ::encode(m_dest_name, cmd_bl); ::encode(empty_bl, cmd_bl); ::encode(static_cast<__u8>(CEPH_OSD_TMAP_RM), cmd_bl); - ::encode(m_image_ctx.name, cmd_bl); + ::encode(image_ctx.name, cmd_bl); op.tmap_update(cmd_bl); } else { - cls_client::dir_rename_image(&op, m_image_ctx.name, m_dest_name, - m_image_ctx.id); + cls_client::dir_rename_image(&op, image_ctx.name, m_dest_name, + image_ctx.id); } - librados::AioCompletion *rados_completion = create_callback_completion(); - int r = m_image_ctx.md_ctx.aio_operate(RBD_DIRECTORY, rados_completion, &op); + librados::AioCompletion *rados_completion = this->create_callback_completion(); + int r = image_ctx.md_ctx.aio_operate(RBD_DIRECTORY, rados_completion, &op); assert(r == 0); rados_completion->release(); } -void RenameRequest::send_remove_source_header() { - CephContext *cct = m_image_ctx.cct; +template +void RenameRequest::send_remove_source_header() { + I &image_ctx = this->m_image_ctx; + CephContext *cct = image_ctx.cct; ldout(cct, 5) << this << " " << __func__ << dendl; m_state = STATE_REMOVE_SOURCE_HEADER; librados::ObjectWriteOperation op; op.remove(); - librados::AioCompletion *rados_completion = create_callback_completion(); - int r = m_image_ctx.md_ctx.aio_operate(m_source_oid, rados_completion, &op); + librados::AioCompletion *rados_completion = this->create_callback_completion(); + int r = image_ctx.md_ctx.aio_operate(m_source_oid, rados_completion, &op); assert(r == 0); rados_completion->release(); } } // namespace operation } // namespace librbd + +template class librbd::operation::RenameRequest; diff --git a/src/librbd/operation/RenameRequest.h b/src/librbd/operation/RenameRequest.h index ab7a87b8c168e..e67f75c241492 100644 --- a/src/librbd/operation/RenameRequest.h +++ b/src/librbd/operation/RenameRequest.h @@ -16,7 +16,8 @@ class ImageCtx; namespace operation { -class RenameRequest : public Request +template +class RenameRequest : public Request { public: /** @@ -51,7 +52,7 @@ public: STATE_REMOVE_SOURCE_HEADER }; - RenameRequest(ImageCtx &image_ctx, Context *on_finish, + RenameRequest(ImageCtxT &image_ctx, Context *on_finish, const std::string &dest_name); protected: @@ -84,4 +85,6 @@ private: } // namespace operation } // namespace librbd +extern template class librbd::operation::RenameRequest; + #endif // CEPH_LIBRBD_RENAME_REQUEST_H diff --git a/src/librbd/operation/Request.cc b/src/librbd/operation/Request.cc index a1fe76003cf22..ce036842d753e 100644 --- a/src/librbd/operation/Request.cc +++ b/src/librbd/operation/Request.cc @@ -8,50 +8,59 @@ namespace librbd { namespace operation { -Request::Request(ImageCtx &image_ctx, Context *on_finish) - : AsyncRequest(image_ctx, on_finish), m_tid(0) { +template +Request::Request(I &image_ctx, Context *on_finish) + : AsyncRequest(image_ctx, on_finish), m_tid(0) { } -void Request::send() { - assert(m_image_ctx.owner_lock.is_locked()); +template +void Request::send() { + I &image_ctx = this->m_image_ctx; + assert(image_ctx.owner_lock.is_locked()); { - RWLock::RLocker snap_locker(m_image_ctx.snap_lock); - if (m_image_ctx.journal != NULL && - !m_image_ctx.journal->is_journal_replaying()) { + RWLock::RLocker snap_locker(image_ctx.snap_lock); + if (image_ctx.journal != NULL && + !image_ctx.journal->is_journal_replaying()) { // journal might be replaying -- wait for it to complete - if (!m_image_ctx.journal->is_journal_ready()) { - m_image_ctx.journal->wait_for_journal_ready( + if (!image_ctx.journal->is_journal_ready()) { + image_ctx.journal->wait_for_journal_ready( new C_WaitForJournalReady(this)); return; } journal::EventEntry event_entry(create_event()); - m_tid = m_image_ctx.journal->append_op_event(event_entry); + m_tid = image_ctx.journal->append_op_event(event_entry); } } send_op(); } -void Request::finish(int r) { - AsyncRequest::finish(r); +template +void Request::finish(int r) { + AsyncRequest::finish(r); - RWLock::RLocker snap_locker(m_image_ctx.snap_lock); + I &image_ctx = this->m_image_ctx; + RWLock::RLocker snap_locker(image_ctx.snap_lock); if (m_tid != 0 && - m_image_ctx.journal != NULL && - !m_image_ctx.journal->is_journal_replaying()) { + image_ctx.journal != NULL && + !image_ctx.journal->is_journal_replaying()) { // ops will be canceled / completed before closing journal - assert(m_image_ctx.journal->is_journal_ready()); + assert(image_ctx.journal->is_journal_ready()); - m_image_ctx.journal->commit_op_event(m_tid, r); + image_ctx.journal->commit_op_event(m_tid, r); } } -void Request::handle_journal_ready() { - RWLock::RLocker owner_locker(m_image_ctx.owner_lock); +template +void Request::handle_journal_ready() { + I &image_ctx = this->m_image_ctx; + RWLock::RLocker owner_locker(image_ctx.owner_lock); send(); } } // namespace operation } // namespace librbd + +template class librbd::operation::Request; diff --git a/src/librbd/operation/Request.h b/src/librbd/operation/Request.h index 705c4115d8ef1..c0dd3cbbcadb3 100644 --- a/src/librbd/operation/Request.h +++ b/src/librbd/operation/Request.h @@ -9,11 +9,15 @@ #include "librbd/JournalTypes.h" namespace librbd { + +class ImageCtx; + namespace operation { -class Request : public AsyncRequest<> { +template +class Request : public AsyncRequest { public: - Request(ImageCtx &image_ctx, Context *on_finish); + Request(ImageCtxT &image_ctx, Context *on_finish); virtual void send(); @@ -43,4 +47,6 @@ private: } // namespace operation } // namespace librbd +extern template class librbd::operation::Request; + #endif // CEPH_LIBRBD_OPERATION_REQUEST_H diff --git a/src/librbd/operation/ResizeRequest.cc b/src/librbd/operation/ResizeRequest.cc index cb5699f5a35c7..282572e967eec 100644 --- a/src/librbd/operation/ResizeRequest.cc +++ b/src/librbd/operation/ResizeRequest.cc @@ -17,34 +17,37 @@ namespace librbd { namespace operation { -ResizeRequest::ResizeRequest(ImageCtx &image_ctx, Context *on_finish, - uint64_t new_size, - ProgressContext &prog_ctx) - : Request(image_ctx, on_finish), - m_original_size(0), m_new_size(new_size), - m_prog_ctx(prog_ctx), m_new_parent_overlap(0), - m_xlist_item(this) +template +ResizeRequest::ResizeRequest(I &image_ctx, Context *on_finish, + uint64_t new_size, ProgressContext &prog_ctx) + : Request(image_ctx, on_finish), + m_original_size(0), m_new_size(new_size), m_prog_ctx(prog_ctx), + m_new_parent_overlap(0), m_xlist_item(this) { } -ResizeRequest::~ResizeRequest() { +template +ResizeRequest::~ResizeRequest() { + I &image_ctx = this->m_image_ctx; ResizeRequest *next_req = NULL; { - RWLock::WLocker snap_locker(m_image_ctx.snap_lock); + RWLock::WLocker snap_locker(image_ctx.snap_lock); assert(m_xlist_item.remove_myself()); - if (!m_image_ctx.resize_reqs.empty()) { - next_req = m_image_ctx.resize_reqs.front(); + if (!image_ctx.resize_reqs.empty()) { + next_req = image_ctx.resize_reqs.front(); } } if (next_req != NULL) { - RWLock::RLocker owner_locker(m_image_ctx.owner_lock); + RWLock::RLocker owner_locker(image_ctx.owner_lock); next_req->send(); } } -bool ResizeRequest::should_complete(int r) { - CephContext *cct = m_image_ctx.cct; +template +bool ResizeRequest::should_complete(int r) { + I &image_ctx = this->m_image_ctx; + CephContext *cct = image_ctx.cct; ldout(cct, 5) << this << " should_complete: " << " r=" << r << dendl; if (r < 0) { @@ -56,7 +59,7 @@ bool ResizeRequest::should_complete(int r) { return true; } - RWLock::RLocker owner_lock(m_image_ctx.owner_lock); + RWLock::RLocker owner_lock(image_ctx.owner_lock); switch (m_state) { case STATE_FLUSH: ldout(cct, 5) << "FLUSH" << dendl; @@ -99,37 +102,41 @@ bool ResizeRequest::should_complete(int r) { return false; } -void ResizeRequest::send() { - assert(m_image_ctx.owner_lock.is_locked()); +template +void ResizeRequest::send() { + I &image_ctx = this->m_image_ctx; + assert(image_ctx.owner_lock.is_locked()); { - RWLock::WLocker snap_locker(m_image_ctx.snap_lock); + RWLock::WLocker snap_locker(image_ctx.snap_lock); if (!m_xlist_item.is_on_list()) { - m_image_ctx.resize_reqs.push_back(&m_xlist_item); - if (m_image_ctx.resize_reqs.front() != this) { + image_ctx.resize_reqs.push_back(&m_xlist_item); + if (image_ctx.resize_reqs.front() != this) { return; } } - assert(m_image_ctx.resize_reqs.front() == this); - m_original_size = m_image_ctx.size; + assert(image_ctx.resize_reqs.front() == this); + m_original_size = image_ctx.size; compute_parent_overlap(); } - Request::send(); + Request::send(); } -void ResizeRequest::send_op() { - assert(m_image_ctx.owner_lock.is_locked()); +template +void ResizeRequest::send_op() { + I &image_ctx = this->m_image_ctx; + assert(image_ctx.owner_lock.is_locked()); - CephContext *cct = m_image_ctx.cct; - if (is_canceled()) { - async_complete(-ERESTART); + CephContext *cct = image_ctx.cct; + if (this->is_canceled()) { + this->async_complete(-ERESTART); } else if (m_original_size == m_new_size) { ldout(cct, 2) << this << " no change in size (" << m_original_size << " -> " << m_new_size << ")" << dendl; m_state = STATE_FINISHED; - async_complete(0); + this->async_complete(0); } else if (m_new_size > m_original_size) { ldout(cct, 2) << this << " expanding image (" << m_original_size << " -> " << m_new_size << ")" << dendl; @@ -141,133 +148,154 @@ void ResizeRequest::send_op() { } } -void ResizeRequest::send_flush() { - ldout(m_image_ctx.cct, 5) << this << " send_flush: " - << " original_size=" << m_original_size - << " new_size=" << m_new_size << dendl; +template +void ResizeRequest::send_flush() { + I &image_ctx = this->m_image_ctx; + ldout(image_ctx.cct, 5) << this << " send_flush: " + << " original_size=" << m_original_size + << " new_size=" << m_new_size << dendl; m_state = STATE_FLUSH; // with clipping adjusted, ensure that write / copy-on-read operations won't // (re-)create objects that we just removed. need async callback to ensure // we don't have cache_lock already held - m_image_ctx.flush_async_operations(create_async_callback_context()); + image_ctx.flush_async_operations(this->create_async_callback_context()); } -void ResizeRequest::send_invalidate_cache() { - assert(m_image_ctx.owner_lock.is_locked()); - ldout(m_image_ctx.cct, 5) << this << " send_invalidate_cache: " - << " original_size=" << m_original_size - << " new_size=" << m_new_size << dendl; +template +void ResizeRequest::send_invalidate_cache() { + I &image_ctx = this->m_image_ctx; + assert(image_ctx.owner_lock.is_locked()); + ldout(image_ctx.cct, 5) << this << " send_invalidate_cache: " + << " original_size=" << m_original_size + << " new_size=" << m_new_size << dendl; m_state = STATE_INVALIDATE_CACHE; // need to invalidate since we're deleting objects, and // ObjectCacher doesn't track non-existent objects - m_image_ctx.invalidate_cache(create_callback_context()); + image_ctx.invalidate_cache(this->create_callback_context()); } -void ResizeRequest::send_trim_image() { - assert(m_image_ctx.owner_lock.is_locked()); - ldout(m_image_ctx.cct, 5) << this << " send_trim_image: " - << " original_size=" << m_original_size - << " new_size=" << m_new_size << dendl; +template +void ResizeRequest::send_trim_image() { + I &image_ctx = this->m_image_ctx; + assert(image_ctx.owner_lock.is_locked()); + ldout(image_ctx.cct, 5) << this << " send_trim_image: " + << " original_size=" << m_original_size + << " new_size=" << m_new_size << dendl; m_state = STATE_TRIM_IMAGE; - TrimRequest *req = new TrimRequest(m_image_ctx, create_callback_context(), - m_original_size, m_new_size, m_prog_ctx); + TrimRequest *req = new TrimRequest(image_ctx, + this->create_callback_context(), + m_original_size, m_new_size, + m_prog_ctx); req->send(); } -void ResizeRequest::send_grow_object_map() { - assert(m_image_ctx.owner_lock.is_locked()); - if (!m_image_ctx.object_map.enabled()) { +template +void ResizeRequest::send_grow_object_map() { + I &image_ctx = this->m_image_ctx; + assert(image_ctx.owner_lock.is_locked()); + if (!image_ctx.object_map.enabled()) { send_update_header(); return; } - ldout(m_image_ctx.cct, 5) << this << " send_grow_object_map: " - << " original_size=" << m_original_size - << " new_size=" << m_new_size << dendl; + ldout(image_ctx.cct, 5) << this << " send_grow_object_map: " + << " original_size=" << m_original_size + << " new_size=" << m_new_size << dendl; m_state = STATE_GROW_OBJECT_MAP; // should have been canceled prior to releasing lock - assert(!m_image_ctx.image_watcher->is_lock_supported() || - m_image_ctx.image_watcher->is_lock_owner()); + assert(!image_ctx.image_watcher->is_lock_supported() || + image_ctx.image_watcher->is_lock_owner()); - m_image_ctx.object_map.aio_resize(m_new_size, OBJECT_NONEXISTENT, - create_callback_context()); + image_ctx.object_map.aio_resize(m_new_size, OBJECT_NONEXISTENT, + this->create_callback_context()); } -bool ResizeRequest::send_shrink_object_map() { - assert(m_image_ctx.owner_lock.is_locked()); - if (!m_image_ctx.object_map.enabled() || m_new_size > m_original_size) { +template +bool ResizeRequest::send_shrink_object_map() { + I &image_ctx = this->m_image_ctx; + assert(image_ctx.owner_lock.is_locked()); + if (!image_ctx.object_map.enabled() || m_new_size > m_original_size) { return true; } - ldout(m_image_ctx.cct, 5) << this << " send_shrink_object_map: " + ldout(image_ctx.cct, 5) << this << " send_shrink_object_map: " << " original_size=" << m_original_size << " new_size=" << m_new_size << dendl; m_state = STATE_SHRINK_OBJECT_MAP; // should have been canceled prior to releasing lock - assert(!m_image_ctx.image_watcher->is_lock_supported() || - m_image_ctx.image_watcher->is_lock_owner()); + assert(!image_ctx.image_watcher->is_lock_supported() || + image_ctx.image_watcher->is_lock_owner()); - m_image_ctx.object_map.aio_resize(m_new_size, OBJECT_NONEXISTENT, - create_callback_context()); + image_ctx.object_map.aio_resize(m_new_size, OBJECT_NONEXISTENT, + this->create_callback_context()); return false; } -void ResizeRequest::send_update_header() { - assert(m_image_ctx.owner_lock.is_locked()); +template +void ResizeRequest::send_update_header() { + I &image_ctx = this->m_image_ctx; + assert(image_ctx.owner_lock.is_locked()); - ldout(m_image_ctx.cct, 5) << this << " send_update_header: " + ldout(image_ctx.cct, 5) << this << " send_update_header: " << " original_size=" << m_original_size << " new_size=" << m_new_size << dendl; m_state = STATE_UPDATE_HEADER; // should have been canceled prior to releasing lock - assert(!m_image_ctx.image_watcher->is_lock_supported() || - m_image_ctx.image_watcher->is_lock_owner()); + assert(!image_ctx.image_watcher->is_lock_supported() || + image_ctx.image_watcher->is_lock_owner()); librados::ObjectWriteOperation op; - if (m_image_ctx.old_format) { + if (image_ctx.old_format) { // rewrite only the size field of the header // NOTE: format 1 image headers are not stored in fixed endian format bufferlist bl; bl.append(reinterpret_cast(&m_new_size), sizeof(m_new_size)); op.write(offsetof(rbd_obj_header_ondisk, image_size), bl); } else { - if (m_image_ctx.image_watcher->is_lock_supported()) { - m_image_ctx.image_watcher->assert_header_locked(&op); + if (image_ctx.image_watcher->is_lock_supported()) { + image_ctx.image_watcher->assert_header_locked(&op); } cls_client::set_size(&op, m_new_size); } - librados::AioCompletion *rados_completion = create_callback_completion(); - int r = m_image_ctx.md_ctx.aio_operate(m_image_ctx.header_oid, - rados_completion, &op); + librados::AioCompletion *rados_completion = + this->create_callback_completion(); + int r = image_ctx.md_ctx.aio_operate(image_ctx.header_oid, + rados_completion, &op); assert(r == 0); rados_completion->release(); } -void ResizeRequest::compute_parent_overlap() { - RWLock::RLocker l2(m_image_ctx.parent_lock); - if (m_image_ctx.parent == NULL) { +template +void ResizeRequest::compute_parent_overlap() { + I &image_ctx = this->m_image_ctx; + RWLock::RLocker l2(image_ctx.parent_lock); + if (image_ctx.parent == NULL) { m_new_parent_overlap = 0; } else { - m_new_parent_overlap = MIN(m_new_size, m_image_ctx.parent_md.overlap); + m_new_parent_overlap = MIN(m_new_size, image_ctx.parent_md.overlap); } } -void ResizeRequest::update_size_and_overlap() { - RWLock::WLocker snap_locker(m_image_ctx.snap_lock); - m_image_ctx.size = m_new_size; +template +void ResizeRequest::update_size_and_overlap() { + I &image_ctx = this->m_image_ctx; + RWLock::WLocker snap_locker(image_ctx.snap_lock); + image_ctx.size = m_new_size; - RWLock::WLocker parent_locker(m_image_ctx.parent_lock); - if (m_image_ctx.parent != NULL && m_new_size < m_original_size) { - m_image_ctx.parent_md.overlap = m_new_parent_overlap; + RWLock::WLocker parent_locker(image_ctx.parent_lock); + if (image_ctx.parent != NULL && m_new_size < m_original_size) { + image_ctx.parent_md.overlap = m_new_parent_overlap; } } } // namespace operation } // namespace librbd + +template class librbd::operation::ResizeRequest; diff --git a/src/librbd/operation/ResizeRequest.h b/src/librbd/operation/ResizeRequest.h index 242a8d68be7a8..dc36ae399a368 100644 --- a/src/librbd/operation/ResizeRequest.h +++ b/src/librbd/operation/ResizeRequest.h @@ -14,11 +14,11 @@ class ProgressContext; namespace operation { -class ResizeRequest : public Request -{ +template +class ResizeRequest : public Request { public: - ResizeRequest(ImageCtx &image_ctx, Context *on_finish, uint64_t new_size, - ProgressContext &prog_ctx); + ResizeRequest(ImageCtxT &image_ctx, Context *on_finish, uint64_t new_size, + ProgressContext &prog_ctx); virtual ~ResizeRequest(); inline bool shrinking() const { @@ -90,7 +90,7 @@ private: ProgressContext &m_prog_ctx; uint64_t m_new_parent_overlap; - xlist::item m_xlist_item; + typename xlist*>::item m_xlist_item; void send_flush(); void send_invalidate_cache(); @@ -107,4 +107,6 @@ private: } // namespace operation } // namespace librbd +extern template class librbd::operation::ResizeRequest; + #endif // CEPH_LIBRBD_OPERATION_RESIZE_REQUEST_H diff --git a/src/librbd/operation/SnapshotCreateRequest.cc b/src/librbd/operation/SnapshotCreateRequest.cc index 26aaadaf62d2b..5caad14680326 100644 --- a/src/librbd/operation/SnapshotCreateRequest.cc +++ b/src/librbd/operation/SnapshotCreateRequest.cc @@ -18,25 +18,26 @@ namespace operation { namespace { +template std::ostream& operator<<(std::ostream& os, - const SnapshotCreateRequest::State& state) { + const typename SnapshotCreateRequest::State& state) { switch(state) { - case SnapshotCreateRequest::STATE_SUSPEND_REQUESTS: + case SnapshotCreateRequest::STATE_SUSPEND_REQUESTS: os << "SUSPEND_REQUESTS"; break; - case SnapshotCreateRequest::STATE_SUSPEND_AIO: + case SnapshotCreateRequest::STATE_SUSPEND_AIO: os << "SUSPEND_AIO"; break; - case SnapshotCreateRequest::STATE_ALLOCATE_SNAP_ID: + case SnapshotCreateRequest::STATE_ALLOCATE_SNAP_ID: os << "ALLOCATE_SNAP_ID"; break; - case SnapshotCreateRequest::STATE_CREATE_SNAP: + case SnapshotCreateRequest::STATE_CREATE_SNAP: os << "CREATE_SNAP"; break; - case SnapshotCreateRequest::STATE_CREATE_OBJECT_MAP: + case SnapshotCreateRequest::STATE_CREATE_OBJECT_MAP: os << "CREATE_OBJECT_MAP"; break; - case SnapshotCreateRequest::STATE_RELEASE_SNAP_ID: + case SnapshotCreateRequest::STATE_RELEASE_SNAP_ID: os << "RELEASE_SNAP_ID"; break; default: @@ -48,20 +49,24 @@ std::ostream& operator<<(std::ostream& os, } // anonymous namespace -SnapshotCreateRequest::SnapshotCreateRequest(ImageCtx &image_ctx, - Context *on_finish, - const std::string &snap_name) - : Request(image_ctx, on_finish), m_snap_name(snap_name), m_ret_val(0), +template +SnapshotCreateRequest::SnapshotCreateRequest(I &image_ctx, + Context *on_finish, + const std::string &snap_name) + : Request(image_ctx, on_finish), m_snap_name(snap_name), m_ret_val(0), m_aio_suspended(false), m_requests_suspended(false), m_snap_id(CEPH_NOSNAP), m_snap_created(false) { } -void SnapshotCreateRequest::send_op() { +template +void SnapshotCreateRequest::send_op() { send_suspend_requests(); } -bool SnapshotCreateRequest::should_complete(int r) { - CephContext *cct = m_image_ctx.cct; +template +bool SnapshotCreateRequest::should_complete(int r) { + I &image_ctx = this->m_image_ctx; + CephContext *cct = image_ctx.cct; ldout(cct, 5) << this << " " << __func__ << ": state=" << m_state << ", " << "r=" << r << dendl; r = filter_state_return_code(r); @@ -76,7 +81,7 @@ bool SnapshotCreateRequest::should_complete(int r) { return should_complete_error(); } - RWLock::RLocker owner_lock(m_image_ctx.owner_lock); + RWLock::RLocker owner_lock(image_ctx.owner_lock); bool finished = false; switch (m_state) { case STATE_SUSPEND_REQUESTS: @@ -112,8 +117,10 @@ bool SnapshotCreateRequest::should_complete(int r) { return finished; } -bool SnapshotCreateRequest::should_complete_error() { - CephContext *cct = m_image_ctx.cct; +template +bool SnapshotCreateRequest::should_complete_error() { + I &image_ctx = this->m_image_ctx; + CephContext *cct = image_ctx.cct; lderr(cct) << this << " " << __func__ << ": " << "ret_val=" << m_ret_val << dendl; @@ -130,120 +137,138 @@ bool SnapshotCreateRequest::should_complete_error() { return finished; } -void SnapshotCreateRequest::send_suspend_requests() { - assert(m_image_ctx.owner_lock.is_locked()); +template +void SnapshotCreateRequest::send_suspend_requests() { + I &image_ctx = this->m_image_ctx; + assert(image_ctx.owner_lock.is_locked()); // TODO suspend (shrink) resize to ensure consistent RBD mirror send_suspend_aio(); } -void SnapshotCreateRequest::send_suspend_aio() { - assert(m_image_ctx.owner_lock.is_locked()); +template +void SnapshotCreateRequest::send_suspend_aio() { + I &image_ctx = this->m_image_ctx; + assert(image_ctx.owner_lock.is_locked()); - CephContext *cct = m_image_ctx.cct; + CephContext *cct = image_ctx.cct; ldout(cct, 5) << this << " " << __func__ << dendl; m_state = STATE_SUSPEND_AIO; m_aio_suspended = true; // can issue a re-entrant callback if no IO in-progress - m_image_ctx.aio_work_queue->block_writes(create_async_callback_context()); + image_ctx.aio_work_queue->block_writes(this->create_async_callback_context()); } -void SnapshotCreateRequest::send_allocate_snap_id() { - assert(m_image_ctx.owner_lock.is_locked()); +template +void SnapshotCreateRequest::send_allocate_snap_id() { + I &image_ctx = this->m_image_ctx; + assert(image_ctx.owner_lock.is_locked()); - CephContext *cct = m_image_ctx.cct; + CephContext *cct = image_ctx.cct; ldout(cct, 5) << this << " " << __func__ << dendl; m_state = STATE_ALLOCATE_SNAP_ID; // TODO create an async version of selfmanaged_snap_create - int r = m_image_ctx.md_ctx.selfmanaged_snap_create(&m_snap_id); - async_complete(r); + int r = image_ctx.md_ctx.selfmanaged_snap_create(&m_snap_id); + this->async_complete(r); } -void SnapshotCreateRequest::send_create_snap() { - assert(m_image_ctx.owner_lock.is_locked()); - RWLock::RLocker snap_locker(m_image_ctx.snap_lock); - RWLock::RLocker parent_locker(m_image_ctx.parent_lock); +template +void SnapshotCreateRequest::send_create_snap() { + I &image_ctx = this->m_image_ctx; + assert(image_ctx.owner_lock.is_locked()); + RWLock::RLocker snap_locker(image_ctx.snap_lock); + RWLock::RLocker parent_locker(image_ctx.parent_lock); - CephContext *cct = m_image_ctx.cct; + CephContext *cct = image_ctx.cct; ldout(cct, 5) << this << " " << __func__ << dendl; m_state = STATE_CREATE_SNAP; // should have been canceled prior to releasing lock - assert(!m_image_ctx.image_watcher->is_lock_supported(m_image_ctx.snap_lock) || - m_image_ctx.image_watcher->is_lock_owner()); + assert(!image_ctx.image_watcher->is_lock_supported(image_ctx.snap_lock) || + image_ctx.image_watcher->is_lock_owner()); // save current size / parent info for creating snapshot record in ImageCtx - m_size = m_image_ctx.size; - m_parent_info = m_image_ctx.parent_md; + m_size = image_ctx.size; + m_parent_info = image_ctx.parent_md; librados::ObjectWriteOperation op; - if (m_image_ctx.old_format) { + if (image_ctx.old_format) { cls_client::old_snapshot_add(&op, m_snap_id, m_snap_name); } else { - if (m_image_ctx.image_watcher->is_lock_owner()) { - m_image_ctx.image_watcher->assert_header_locked(&op); + if (image_ctx.image_watcher->is_lock_owner()) { + image_ctx.image_watcher->assert_header_locked(&op); } cls_client::snapshot_add(&op, m_snap_id, m_snap_name); } - librados::AioCompletion *rados_completion = create_callback_completion(); - int r = m_image_ctx.md_ctx.aio_operate(m_image_ctx.header_oid, + librados::AioCompletion *rados_completion = + this->create_callback_completion(); + int r = image_ctx.md_ctx.aio_operate(image_ctx.header_oid, rados_completion, &op); assert(r == 0); rados_completion->release(); } -bool SnapshotCreateRequest::send_create_object_map() { - assert(m_image_ctx.owner_lock.is_locked()); +template +bool SnapshotCreateRequest::send_create_object_map() { + I &image_ctx = this->m_image_ctx; + assert(image_ctx.owner_lock.is_locked()); { - RWLock::RLocker snap_locker(m_image_ctx.snap_lock); - RWLock::RLocker object_map_lock(m_image_ctx.object_map_lock); - if (m_image_ctx.object_map.enabled(m_image_ctx.object_map_lock)) { - CephContext *cct = m_image_ctx.cct; + RWLock::RLocker snap_locker(image_ctx.snap_lock); + RWLock::RLocker object_map_lock(image_ctx.object_map_lock); + if (image_ctx.object_map.enabled(image_ctx.object_map_lock)) { + CephContext *cct = image_ctx.cct; ldout(cct, 5) << this << " " << __func__ << dendl; m_state = STATE_CREATE_OBJECT_MAP; - m_image_ctx.object_map.snapshot_add(m_snap_id, create_callback_context()); + image_ctx.object_map.snapshot_add(m_snap_id, + this->create_callback_context()); return false; } } return true; } -bool SnapshotCreateRequest::send_release_snap_id() { +template +bool SnapshotCreateRequest::send_release_snap_id() { + I &image_ctx = this->m_image_ctx; if (m_snap_id != CEPH_NOSNAP && !m_snap_created) { - CephContext *cct = m_image_ctx.cct; + CephContext *cct = image_ctx.cct; ldout(cct, 5) << this << " " << __func__ << ": snap_id=" << m_snap_id << dendl; m_state = STATE_RELEASE_SNAP_ID; // TODO add async version of selfmanaged_snap_remove - int r = m_image_ctx.data_ctx.selfmanaged_snap_remove(m_snap_id); + int r = image_ctx.data_ctx.selfmanaged_snap_remove(m_snap_id); m_snap_id = CEPH_NOSNAP; - async_complete(r); + this->async_complete(r); return false; } return true; } -void SnapshotCreateRequest::resume_aio() { +template +void SnapshotCreateRequest::resume_aio() { + I &image_ctx = this->m_image_ctx; if (m_aio_suspended) { - CephContext *cct = m_image_ctx.cct; + CephContext *cct = image_ctx.cct; ldout(cct, 5) << this << " " << __func__ << dendl; - m_image_ctx.aio_work_queue->unblock_writes(); + image_ctx.aio_work_queue->unblock_writes(); m_aio_suspended = false; } } -void SnapshotCreateRequest::resume_requests() { +template +void SnapshotCreateRequest::resume_requests() { + I &image_ctx = this->m_image_ctx; if (m_requests_suspended) { - CephContext *cct = m_image_ctx.cct; + CephContext *cct = image_ctx.cct; ldout(cct, 5) << this << " " << __func__ << dendl; // TODO @@ -251,42 +276,46 @@ void SnapshotCreateRequest::resume_requests() { } } -void SnapshotCreateRequest::update_snap_context() { - assert(m_image_ctx.owner_lock.is_locked()); +template +void SnapshotCreateRequest::update_snap_context() { + I &image_ctx = this->m_image_ctx; + assert(image_ctx.owner_lock.is_locked()); m_snap_created = true; - RWLock::WLocker snap_locker(m_image_ctx.snap_lock); - if (m_image_ctx.old_format) { + RWLock::WLocker snap_locker(image_ctx.snap_lock); + if (image_ctx.old_format) { return; } - if (m_image_ctx.get_snap_info(m_snap_id) != NULL) { + if (image_ctx.get_snap_info(m_snap_id) != NULL) { return; } - CephContext *cct = m_image_ctx.cct; + CephContext *cct = image_ctx.cct; ldout(cct, 5) << this << " " << __func__ << dendl; // should have been canceled prior to releasing lock - assert(!m_image_ctx.image_watcher->is_lock_supported(m_image_ctx.snap_lock) || - m_image_ctx.image_watcher->is_lock_owner()); + assert(!image_ctx.image_watcher->is_lock_supported(image_ctx.snap_lock) || + image_ctx.image_watcher->is_lock_owner()); // immediately add a reference to the new snapshot - m_image_ctx.add_snap(m_snap_name, m_snap_id, m_size, m_parent_info, - RBD_PROTECTION_STATUS_UNPROTECTED, 0); + image_ctx.add_snap(m_snap_name, m_snap_id, m_size, m_parent_info, + RBD_PROTECTION_STATUS_UNPROTECTED, 0); // immediately start using the new snap context if we // own the exclusive lock std::vector snaps; snaps.push_back(m_snap_id); - snaps.insert(snaps.end(), m_image_ctx.snapc.snaps.begin(), - m_image_ctx.snapc.snaps.end()); + snaps.insert(snaps.end(), image_ctx.snapc.snaps.begin(), + image_ctx.snapc.snaps.end()); - m_image_ctx.snapc.seq = m_snap_id; - m_image_ctx.snapc.snaps.swap(snaps); - m_image_ctx.data_ctx.selfmanaged_snap_set_write_ctx( - m_image_ctx.snapc.seq, m_image_ctx.snaps); + image_ctx.snapc.seq = m_snap_id; + image_ctx.snapc.snaps.swap(snaps); + image_ctx.data_ctx.selfmanaged_snap_set_write_ctx( + image_ctx.snapc.seq, image_ctx.snaps); } } // namespace operation } // namespace librbd + +template class librbd::operation::SnapshotCreateRequest; diff --git a/src/librbd/operation/SnapshotCreateRequest.h b/src/librbd/operation/SnapshotCreateRequest.h index 5db8441fef8f1..249bcafbc2e57 100644 --- a/src/librbd/operation/SnapshotCreateRequest.h +++ b/src/librbd/operation/SnapshotCreateRequest.h @@ -17,7 +17,8 @@ class ImageCtx; namespace operation { -class SnapshotCreateRequest : public Request { +template +class SnapshotCreateRequest : public Request { public: /** * Snap Create goes through the following state machine: @@ -64,7 +65,7 @@ public: STATE_RELEASE_SNAP_ID }; - SnapshotCreateRequest(ImageCtx &image_ctx, Context *on_finish, + SnapshotCreateRequest(ImageCtxT &image_ctx, Context *on_finish, const std::string &snap_name); protected: @@ -121,4 +122,6 @@ private: } // namespace operation } // namespace librbd +extern template class librbd::operation::SnapshotCreateRequest; + #endif // CEPH_LIBRBD_OPERATION_SNAPSHOT_CREATE_REQUEST_H diff --git a/src/librbd/operation/SnapshotProtectRequest.cc b/src/librbd/operation/SnapshotProtectRequest.cc index 3e8a396981fdf..9ba415e4cf9dc 100644 --- a/src/librbd/operation/SnapshotProtectRequest.cc +++ b/src/librbd/operation/SnapshotProtectRequest.cc @@ -15,10 +15,11 @@ namespace operation { namespace { +template std::ostream& operator<<(std::ostream& os, - const SnapshotProtectRequest::State& state) { + const typename SnapshotProtectRequest::State& state) { switch(state) { - case SnapshotProtectRequest::STATE_PROTECT_SNAP: + case SnapshotProtectRequest::STATE_PROTECT_SNAP: os << "PROTECT_SNAP"; break; } @@ -27,18 +28,22 @@ std::ostream& operator<<(std::ostream& os, } // anonymous namespace -SnapshotProtectRequest::SnapshotProtectRequest(ImageCtx &image_ctx, - Context *on_finish, - const std::string &snap_name) - : Request(image_ctx, on_finish), m_snap_name(snap_name) { +template +SnapshotProtectRequest::SnapshotProtectRequest(I &image_ctx, + Context *on_finish, + const std::string &snap_name) + : Request(image_ctx, on_finish), m_snap_name(snap_name) { } -void SnapshotProtectRequest::send_op() { +template +void SnapshotProtectRequest::send_op() { send_protect_snap(); } -bool SnapshotProtectRequest::should_complete(int r) { - CephContext *cct = m_image_ctx.cct; +template +bool SnapshotProtectRequest::should_complete(int r) { + I &image_ctx = this->m_image_ctx; + CephContext *cct = image_ctx.cct; ldout(cct, 5) << this << " " << __func__ << ": state=" << m_state << ", " << "r=" << r << dendl; if (r < 0) { @@ -47,38 +52,42 @@ bool SnapshotProtectRequest::should_complete(int r) { return true; } -void SnapshotProtectRequest::send_protect_snap() { - assert(m_image_ctx.owner_lock.is_locked()); +template +void SnapshotProtectRequest::send_protect_snap() { + I &image_ctx = this->m_image_ctx; + assert(image_ctx.owner_lock.is_locked()); - CephContext *cct = m_image_ctx.cct; + CephContext *cct = image_ctx.cct; ldout(cct, 5) << this << " " << __func__ << dendl; m_state = STATE_PROTECT_SNAP; int r = verify_and_send_protect_snap(); if (r < 0) { - async_complete(r); + this->async_complete(r); return; } } -int SnapshotProtectRequest::verify_and_send_protect_snap() { - RWLock::RLocker md_locker(m_image_ctx.md_lock); - RWLock::RLocker snap_locker(m_image_ctx.snap_lock); +template +int SnapshotProtectRequest::verify_and_send_protect_snap() { + I &image_ctx = this->m_image_ctx; + RWLock::RLocker md_locker(image_ctx.md_lock); + RWLock::RLocker snap_locker(image_ctx.snap_lock); - CephContext *cct = m_image_ctx.cct; - if ((m_image_ctx.features & RBD_FEATURE_LAYERING) == 0) { + CephContext *cct = image_ctx.cct; + if ((image_ctx.features & RBD_FEATURE_LAYERING) == 0) { lderr(cct) << "image must support layering" << dendl; return -ENOSYS; } - uint64_t snap_id = m_image_ctx.get_snap_id(m_snap_name); + uint64_t snap_id = image_ctx.get_snap_id(m_snap_name); if (snap_id == CEPH_NOSNAP) { return -ENOENT; } bool is_protected; - int r = m_image_ctx.is_snap_protected(snap_id, &is_protected); + int r = image_ctx.is_snap_protected(snap_id, &is_protected); if (r < 0) { return r; } @@ -91,8 +100,9 @@ int SnapshotProtectRequest::verify_and_send_protect_snap() { cls_client::set_protection_status(&op, snap_id, RBD_PROTECTION_STATUS_PROTECTED); - librados::AioCompletion *rados_completion = create_callback_completion(); - r = m_image_ctx.md_ctx.aio_operate(m_image_ctx.header_oid, rados_completion, + librados::AioCompletion *rados_completion = + this->create_callback_completion(); + r = image_ctx.md_ctx.aio_operate(image_ctx.header_oid, rados_completion, &op); assert(r == 0); rados_completion->release(); @@ -102,3 +112,4 @@ int SnapshotProtectRequest::verify_and_send_protect_snap() { } // namespace operation } // namespace librbd +template class librbd::operation::SnapshotProtectRequest; diff --git a/src/librbd/operation/SnapshotProtectRequest.h b/src/librbd/operation/SnapshotProtectRequest.h index e2953f9c97fe6..02484e98e7428 100644 --- a/src/librbd/operation/SnapshotProtectRequest.h +++ b/src/librbd/operation/SnapshotProtectRequest.h @@ -16,7 +16,8 @@ class ImageCtx; namespace operation { -class SnapshotProtectRequest : public Request { +template +class SnapshotProtectRequest : public Request { public: /** * Snap Protect goes through the following state machine: @@ -38,7 +39,7 @@ public: STATE_PROTECT_SNAP }; - SnapshotProtectRequest(ImageCtx &image_ctx, Context *on_finish, + SnapshotProtectRequest(ImageCtxT &image_ctx, Context *on_finish, const std::string &snap_name); protected: @@ -61,4 +62,6 @@ private: } // namespace operation } // namespace librbd +extern template class librbd::operation::SnapshotProtectRequest; + #endif // CEPH_LIBRBD_OPERATION_SNAPSHOT_PROTECT_REQUEST_H diff --git a/src/librbd/operation/SnapshotRemoveRequest.cc b/src/librbd/operation/SnapshotRemoveRequest.cc index e8e76b09d86a0..5d8035c0e87ce 100644 --- a/src/librbd/operation/SnapshotRemoveRequest.cc +++ b/src/librbd/operation/SnapshotRemoveRequest.cc @@ -17,19 +17,20 @@ namespace operation { namespace { +template std::ostream& operator<<(std::ostream& os, - const SnapshotRemoveRequest::State& state) { + const typename SnapshotRemoveRequest::State& state) { switch(state) { - case SnapshotRemoveRequest::STATE_REMOVE_OBJECT_MAP: + case SnapshotRemoveRequest::STATE_REMOVE_OBJECT_MAP: os << "REMOVE_OBJECT_MAP"; break; - case SnapshotRemoveRequest::STATE_REMOVE_CHILD: + case SnapshotRemoveRequest::STATE_REMOVE_CHILD: os << "REMOVE_CHILD"; break; - case SnapshotRemoveRequest::STATE_REMOVE_SNAP: + case SnapshotRemoveRequest::STATE_REMOVE_SNAP: os << "REMOVE_SNAP"; break; - case SnapshotRemoveRequest::STATE_RELEASE_SNAP_ID: + case SnapshotRemoveRequest::STATE_RELEASE_SNAP_ID: os << "RELEASE_SNAP_ID"; break; default: @@ -41,20 +42,24 @@ std::ostream& operator<<(std::ostream& os, } // anonymous namespace -SnapshotRemoveRequest::SnapshotRemoveRequest(ImageCtx &image_ctx, - Context *on_finish, - const std::string &snap_name, - uint64_t snap_id) - : Request(image_ctx, on_finish), m_snap_name(snap_name), +template +SnapshotRemoveRequest::SnapshotRemoveRequest(I &image_ctx, + Context *on_finish, + const std::string &snap_name, + uint64_t snap_id) + : Request(image_ctx, on_finish), m_snap_name(snap_name), m_snap_id(snap_id) { } -void SnapshotRemoveRequest::send_op() { +template +void SnapshotRemoveRequest::send_op() { send_remove_object_map(); } -bool SnapshotRemoveRequest::should_complete(int r) { - CephContext *cct = m_image_ctx.cct; +template +bool SnapshotRemoveRequest::should_complete(int r) { + I &image_ctx = this->m_image_ctx; + CephContext *cct = image_ctx.cct; ldout(cct, 5) << this << " " << __func__ << ": state=" << m_state << ", " << "r=" << r << dendl; r = filter_state_return_code(r); @@ -62,7 +67,7 @@ bool SnapshotRemoveRequest::should_complete(int r) { return true; } - RWLock::RLocker owner_lock(m_image_ctx.owner_lock); + RWLock::RLocker owner_lock(image_ctx.owner_lock); bool finished = false; switch (m_state) { case STATE_REMOVE_OBJECT_MAP: @@ -86,52 +91,56 @@ bool SnapshotRemoveRequest::should_complete(int r) { return finished; } -void SnapshotRemoveRequest::send_remove_object_map() { - assert(m_image_ctx.owner_lock.is_locked()); +template +void SnapshotRemoveRequest::send_remove_object_map() { + I &image_ctx = this->m_image_ctx; + assert(image_ctx.owner_lock.is_locked()); { - RWLock::WLocker snap_locker(m_image_ctx.snap_lock); - RWLock::RLocker object_map_locker(m_image_ctx.object_map_lock); - if (m_image_ctx.object_map.enabled(m_image_ctx.object_map_lock)) { - CephContext *cct = m_image_ctx.cct; + RWLock::WLocker snap_locker(image_ctx.snap_lock); + RWLock::RLocker object_map_locker(image_ctx.object_map_lock); + if (image_ctx.object_map.enabled(image_ctx.object_map_lock)) { + CephContext *cct = image_ctx.cct; ldout(cct, 5) << this << " " << __func__ << dendl; m_state = STATE_REMOVE_OBJECT_MAP; - m_image_ctx.object_map.snapshot_remove( - m_snap_id, create_callback_context()); + image_ctx.object_map.snapshot_remove( + m_snap_id, this->create_callback_context()); return; } } send_remove_child(); } -void SnapshotRemoveRequest::send_remove_child() { - assert(m_image_ctx.owner_lock.is_locked()); +template +void SnapshotRemoveRequest::send_remove_child() { + I &image_ctx = this->m_image_ctx; + assert(image_ctx.owner_lock.is_locked()); - CephContext *cct = m_image_ctx.cct; + CephContext *cct = image_ctx.cct; { - RWLock::RLocker snap_locker(m_image_ctx.snap_lock); - RWLock::RLocker parent_locker(m_image_ctx.parent_lock); + RWLock::RLocker snap_locker(image_ctx.snap_lock); + RWLock::RLocker parent_locker(image_ctx.parent_lock); parent_spec our_pspec; - int r = m_image_ctx.get_parent_spec(m_snap_id, &our_pspec); + int r = image_ctx.get_parent_spec(m_snap_id, &our_pspec); if (r < 0) { lderr(cct) << "failed to retrieve parent spec" << dendl; - async_complete(r); + this->async_complete(r); return; } - if (m_image_ctx.parent_md.spec != our_pspec && + if (image_ctx.parent_md.spec != our_pspec && (scan_for_parents(our_pspec) == -ENOENT)) { // no other references to the parent image ldout(cct, 5) << this << " " << __func__ << dendl; m_state = STATE_REMOVE_CHILD; librados::ObjectWriteOperation op; - cls_client::remove_child(&op, our_pspec, m_image_ctx.id); + cls_client::remove_child(&op, our_pspec, image_ctx.id); - librados::AioCompletion *rados_completion = create_callback_completion(); - r = m_image_ctx.md_ctx.aio_operate(RBD_CHILDREN, rados_completion, &op); + librados::AioCompletion *rados_completion = this->create_callback_completion(); + r = image_ctx.md_ctx.aio_operate(RBD_CHILDREN, rados_completion, &op); assert(r == 0); rados_completion->release(); return; @@ -142,60 +151,68 @@ void SnapshotRemoveRequest::send_remove_child() { send_remove_snap(); } -void SnapshotRemoveRequest::send_remove_snap() { - assert(m_image_ctx.owner_lock.is_locked()); +template +void SnapshotRemoveRequest::send_remove_snap() { + I &image_ctx = this->m_image_ctx; + assert(image_ctx.owner_lock.is_locked()); - CephContext *cct = m_image_ctx.cct; + CephContext *cct = image_ctx.cct; ldout(cct, 5) << this << " " << __func__ << dendl; m_state = STATE_REMOVE_SNAP; librados::ObjectWriteOperation op; - if (m_image_ctx.old_format) { + if (image_ctx.old_format) { cls_client::old_snapshot_remove(&op, m_snap_name); } else { - if (m_image_ctx.image_watcher->is_lock_owner()) { - m_image_ctx.image_watcher->assert_header_locked(&op); + if (image_ctx.image_watcher->is_lock_owner()) { + image_ctx.image_watcher->assert_header_locked(&op); } cls_client::snapshot_remove(&op, m_snap_id); } - librados::AioCompletion *rados_completion = create_callback_completion(); - int r = m_image_ctx.md_ctx.aio_operate(m_image_ctx.header_oid, - rados_completion, &op); + librados::AioCompletion *rados_completion = this->create_callback_completion(); + int r = image_ctx.md_ctx.aio_operate(image_ctx.header_oid, + rados_completion, &op); assert(r == 0); rados_completion->release(); } -void SnapshotRemoveRequest::send_release_snap_id() { - assert(m_image_ctx.owner_lock.is_locked()); +template +void SnapshotRemoveRequest::send_release_snap_id() { + I &image_ctx = this->m_image_ctx; + assert(image_ctx.owner_lock.is_locked()); - CephContext *cct = m_image_ctx.cct; + CephContext *cct = image_ctx.cct; ldout(cct, 5) << this << " " << __func__ << ": " << "snap_name=" << m_snap_name << ", " << "snap_id=" << m_snap_id << dendl; m_state = STATE_RELEASE_SNAP_ID; // TODO add async version of selfmanaged_snap_remove - m_image_ctx.data_ctx.selfmanaged_snap_remove(m_snap_id); - async_complete(0); + image_ctx.data_ctx.selfmanaged_snap_remove(m_snap_id); + this->async_complete(0); } -void SnapshotRemoveRequest::remove_snap_context() { - CephContext *cct = m_image_ctx.cct; +template +void SnapshotRemoveRequest::remove_snap_context() { + I &image_ctx = this->m_image_ctx; + CephContext *cct = image_ctx.cct; ldout(cct, 5) << this << " " << __func__ << dendl; - RWLock::WLocker snap_locker(m_image_ctx.snap_lock); - m_image_ctx.rm_snap(m_snap_name, m_snap_id); + RWLock::WLocker snap_locker(image_ctx.snap_lock); + image_ctx.rm_snap(m_snap_name, m_snap_id); } -int SnapshotRemoveRequest::scan_for_parents(parent_spec &pspec) { - assert(m_image_ctx.snap_lock.is_locked()); - assert(m_image_ctx.parent_lock.is_locked()); +template +int SnapshotRemoveRequest::scan_for_parents(parent_spec &pspec) { + I &image_ctx = this->m_image_ctx; + assert(image_ctx.snap_lock.is_locked()); + assert(image_ctx.parent_lock.is_locked()); if (pspec.pool_id != -1) { map::iterator it; - for (it = m_image_ctx.snap_info.begin(); - it != m_image_ctx.snap_info.end(); ++it) { + for (it = image_ctx.snap_info.begin(); + it != image_ctx.snap_info.end(); ++it) { // skip our snap id (if checking base image, CEPH_NOSNAP won't match) if (it->first == m_snap_id) { continue; @@ -204,7 +221,7 @@ int SnapshotRemoveRequest::scan_for_parents(parent_spec &pspec) { break; } } - if (it == m_image_ctx.snap_info.end()) { + if (it == image_ctx.snap_info.end()) { return -ENOENT; } } @@ -213,3 +230,5 @@ int SnapshotRemoveRequest::scan_for_parents(parent_spec &pspec) { } // namespace operation } // namespace librbd + +template class librbd::operation::SnapshotRemoveRequest; diff --git a/src/librbd/operation/SnapshotRemoveRequest.h b/src/librbd/operation/SnapshotRemoveRequest.h index 621f3ee2c7631..ea950a55d3571 100644 --- a/src/librbd/operation/SnapshotRemoveRequest.h +++ b/src/librbd/operation/SnapshotRemoveRequest.h @@ -16,7 +16,8 @@ class ImageCtx; namespace operation { -class SnapshotRemoveRequest : public Request { +template +class SnapshotRemoveRequest : public Request { public: /** * Snap Remove goes through the following state machine: @@ -54,7 +55,7 @@ public: STATE_RELEASE_SNAP_ID }; - SnapshotRemoveRequest(ImageCtx &image_ctx, Context *on_finish, + SnapshotRemoveRequest(ImageCtxT &image_ctx, Context *on_finish, const std::string &snap_name, uint64_t snap_id); protected: @@ -90,4 +91,6 @@ private: } // namespace operation } // namespace librbd +extern template class librbd::operation::SnapshotRemoveRequest; + #endif // CEPH_LIBRBD_OPERATION_SNAPSHOT_REMOVE_REQUEST_H diff --git a/src/librbd/operation/SnapshotRenameRequest.cc b/src/librbd/operation/SnapshotRenameRequest.cc index c5804afc771b7..53ffb38256777 100644 --- a/src/librbd/operation/SnapshotRenameRequest.cc +++ b/src/librbd/operation/SnapshotRenameRequest.cc @@ -16,10 +16,11 @@ namespace operation { namespace { +template std::ostream& operator<<(std::ostream& os, - const SnapshotRenameRequest::State& state) { + const typename SnapshotRenameRequest::State& state) { switch(state) { - case SnapshotRenameRequest::STATE_RENAME_SNAP: + case SnapshotRenameRequest::STATE_RENAME_SNAP: os << "RENAME_SNAP"; break; } @@ -28,19 +29,23 @@ std::ostream& operator<<(std::ostream& os, } // anonymous namespace -SnapshotRenameRequest::SnapshotRenameRequest(ImageCtx &image_ctx, - Context *on_finish, - uint64_t snap_id, - const std::string &snap_name) - : Request(image_ctx, on_finish), m_snap_id(snap_id), m_snap_name(snap_name) { +template +SnapshotRenameRequest::SnapshotRenameRequest(I &image_ctx, + Context *on_finish, + uint64_t snap_id, + const std::string &snap_name) + : Request(image_ctx, on_finish), m_snap_id(snap_id), m_snap_name(snap_name) { } -void SnapshotRenameRequest::send_op() { +template +void SnapshotRenameRequest::send_op() { send_rename_snap(); } -bool SnapshotRenameRequest::should_complete(int r) { - CephContext *cct = m_image_ctx.cct; +template +bool SnapshotRenameRequest::should_complete(int r) { + I &image_ctx = this->m_image_ctx; + CephContext *cct = image_ctx.cct; ldout(cct, 5) << this << " " << __func__ << ": state=" << m_state << ", " << "r=" << r << dendl; if (r < 0) { @@ -49,29 +54,31 @@ bool SnapshotRenameRequest::should_complete(int r) { return true; } -void SnapshotRenameRequest::send_rename_snap() { - assert(m_image_ctx.owner_lock.is_locked()); - RWLock::RLocker md_locker(m_image_ctx.md_lock); - RWLock::RLocker snap_locker(m_image_ctx.snap_lock); +template +void SnapshotRenameRequest::send_rename_snap() { + I &image_ctx = this->m_image_ctx; + assert(image_ctx.owner_lock.is_locked()); + RWLock::RLocker md_locker(image_ctx.md_lock); + RWLock::RLocker snap_locker(image_ctx.snap_lock); - CephContext *cct = m_image_ctx.cct; + CephContext *cct = image_ctx.cct; ldout(cct, 5) << this << " " << __func__ << dendl; m_state = STATE_RENAME_SNAP; librados::ObjectWriteOperation op; - if (m_image_ctx.old_format) { + if (image_ctx.old_format) { cls_client::old_snapshot_rename(&op, m_snap_id, m_snap_name); } else { - if (m_image_ctx.image_watcher->is_lock_owner()) { - m_image_ctx.image_watcher->assert_header_locked(&op); + if (image_ctx.image_watcher->is_lock_owner()) { + image_ctx.image_watcher->assert_header_locked(&op); } cls_client::snapshot_rename(&op, m_snap_id, m_snap_name); } - librados::AioCompletion *rados_completion = create_callback_completion(); - int r = m_image_ctx.md_ctx.aio_operate(m_image_ctx.header_oid, - rados_completion, &op); + librados::AioCompletion *rados_completion = this->create_callback_completion(); + int r = image_ctx.md_ctx.aio_operate(image_ctx.header_oid, + rados_completion, &op); assert(r == 0); rados_completion->release(); } @@ -79,3 +86,4 @@ void SnapshotRenameRequest::send_rename_snap() { } // namespace operation } // namespace librbd +template class librbd::operation::SnapshotRenameRequest; diff --git a/src/librbd/operation/SnapshotRenameRequest.h b/src/librbd/operation/SnapshotRenameRequest.h index 8be3459086295..19a72c75a50ae 100644 --- a/src/librbd/operation/SnapshotRenameRequest.h +++ b/src/librbd/operation/SnapshotRenameRequest.h @@ -16,7 +16,8 @@ class ImageCtx; namespace operation { -class SnapshotRenameRequest : public Request { +template +class SnapshotRenameRequest : public Request { public: /** * Snap Rename goes through the following state machine: @@ -38,7 +39,7 @@ public: STATE_RENAME_SNAP }; - SnapshotRenameRequest(ImageCtx &image_ctx, Context *on_finish, + SnapshotRenameRequest(ImageCtxT &image_ctx, Context *on_finish, uint64_t snap_id, const std::string &snap_name); virtual journal::Event create_event() const { @@ -60,4 +61,6 @@ private: } // namespace operation } // namespace librbd +extern template class librbd::operation::SnapshotRenameRequest; + #endif // CEPH_LIBRBD_OPERATION_SNAPSHOT_RENAME_REQUEST_H diff --git a/src/librbd/operation/SnapshotRollbackRequest.cc b/src/librbd/operation/SnapshotRollbackRequest.cc index bde4a3a5cfb4d..2acd2aef0421f 100644 --- a/src/librbd/operation/SnapshotRollbackRequest.cc +++ b/src/librbd/operation/SnapshotRollbackRequest.cc @@ -22,19 +22,20 @@ namespace operation { namespace { +template std::ostream& operator<<(std::ostream& os, - const SnapshotRollbackRequest::State& state) { + const typename SnapshotRollbackRequest::State& state) { switch(state) { - case SnapshotRollbackRequest::STATE_RESIZE_IMAGE: + case SnapshotRollbackRequest::STATE_RESIZE_IMAGE: os << "RESIZE_IMAGE"; break; - case SnapshotRollbackRequest::STATE_ROLLBACK_OBJECT_MAP: + case SnapshotRollbackRequest::STATE_ROLLBACK_OBJECT_MAP: os << "ROLLBACK_OBJECT_MAP"; break; - case SnapshotRollbackRequest::STATE_ROLLBACK_OBJECTS: + case SnapshotRollbackRequest::STATE_ROLLBACK_OBJECTS: os << "ROLLBACK_OBJECTS"; break; - case SnapshotRollbackRequest::STATE_INVALIDATE_CACHE: + case SnapshotRollbackRequest::STATE_INVALIDATE_CACHE: os << "INVALIDATE_CACHE"; break; default: @@ -44,26 +45,28 @@ std::ostream& operator<<(std::ostream& os, return os; } +template class C_RollbackObject : public C_AsyncObjectThrottle<> { public: - C_RollbackObject(AsyncObjectThrottle<> &throttle, ImageCtx *image_ctx, + C_RollbackObject(AsyncObjectThrottle<> &throttle, I *image_ctx, uint64_t snap_id, uint64_t object_num) : C_AsyncObjectThrottle(throttle, *image_ctx), m_snap_id(snap_id), m_object_num(object_num) { } virtual int send() { - CephContext *cct = m_image_ctx.cct; + I &image_ctx = this->m_image_ctx; + CephContext *cct = image_ctx.cct; ldout(cct, 20) << "C_RollbackObject: " << __func__ << ": object_num=" << m_object_num << dendl; - std::string oid = m_image_ctx.get_object_name(m_object_num); + 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); - m_image_ctx.data_ctx.aio_operate(oid, rados_completion, &op); + image_ctx.data_ctx.aio_operate(oid, rados_completion, &op); rados_completion->release(); return 0; } @@ -75,22 +78,26 @@ private: } // anonymous namespace -SnapshotRollbackRequest::SnapshotRollbackRequest(ImageCtx &image_ctx, - Context *on_finish, - const std::string &snap_name, - uint64_t snap_id, - uint64_t snap_size, - ProgressContext &prog_ctx) - : Request(image_ctx, on_finish), m_snap_name(snap_name), m_snap_id(snap_id), - m_snap_size(snap_size), m_prog_ctx(prog_ctx) { +template +SnapshotRollbackRequest::SnapshotRollbackRequest(I &image_ctx, + Context *on_finish, + const std::string &snap_name, + uint64_t snap_id, + uint64_t snap_size, + ProgressContext &prog_ctx) + : Request(image_ctx, on_finish), m_snap_name(snap_name), + m_snap_id(snap_id), m_snap_size(snap_size), m_prog_ctx(prog_ctx) { } -void SnapshotRollbackRequest::send_op() { +template +void SnapshotRollbackRequest::send_op() { send_resize_image(); } -bool SnapshotRollbackRequest::should_complete(int r) { - CephContext *cct = m_image_ctx.cct; +template +bool SnapshotRollbackRequest::should_complete(int r) { + I &image_ctx = this->m_image_ctx; + CephContext *cct = image_ctx.cct; ldout(cct, 5) << this << " " << __func__ << ": state=" << m_state << ", " << "r=" << r << dendl; if (r < 0) { @@ -98,7 +105,7 @@ bool SnapshotRollbackRequest::should_complete(int r) { return true; } - RWLock::RLocker owner_lock(m_image_ctx.owner_lock); + RWLock::RLocker owner_lock(image_ctx.owner_lock); bool finished = false; switch (m_state) { case STATE_RESIZE_IMAGE: @@ -120,13 +127,15 @@ bool SnapshotRollbackRequest::should_complete(int r) { return finished; } -void SnapshotRollbackRequest::send_resize_image() { - assert(m_image_ctx.owner_lock.is_locked()); +template +void SnapshotRollbackRequest::send_resize_image() { + I &image_ctx = this->m_image_ctx; + assert(image_ctx.owner_lock.is_locked()); uint64_t current_size; { - RWLock::RLocker snap_locker(m_image_ctx.snap_lock); - current_size = m_image_ctx.get_image_size(CEPH_NOSNAP); + RWLock::RLocker snap_locker(image_ctx.snap_lock); + current_size = image_ctx.get_image_size(CEPH_NOSNAP); } if (current_size == m_snap_size) { @@ -134,27 +143,30 @@ void SnapshotRollbackRequest::send_resize_image() { return; } - CephContext *cct = m_image_ctx.cct; + CephContext *cct = image_ctx.cct; ldout(cct, 5) << this << " " << __func__ << dendl; m_state = STATE_RESIZE_IMAGE; - ResizeRequest *req = new ResizeRequest(m_image_ctx, create_callback_context(), - m_snap_size, m_no_op_prog_ctx); + ResizeRequest *req = new ResizeRequest(image_ctx, + this->create_callback_context(), + m_snap_size, m_no_op_prog_ctx); req->send(); } -void SnapshotRollbackRequest::send_rollback_object_map() { - assert(m_image_ctx.owner_lock.is_locked()); +template +void SnapshotRollbackRequest::send_rollback_object_map() { + I &image_ctx = this->m_image_ctx; + assert(image_ctx.owner_lock.is_locked()); { - RWLock::RLocker snap_locker(m_image_ctx.snap_lock); - RWLock::WLocker object_map_lock(m_image_ctx.object_map_lock); - if (m_image_ctx.object_map.enabled(m_image_ctx.object_map_lock)) { - CephContext *cct = m_image_ctx.cct; + RWLock::RLocker snap_locker(image_ctx.snap_lock); + RWLock::WLocker object_map_lock(image_ctx.object_map_lock); + if (image_ctx.object_map.enabled(image_ctx.object_map_lock)) { + CephContext *cct = image_ctx.cct; ldout(cct, 5) << this << " " << __func__ << dendl; m_state = STATE_ROLLBACK_OBJECT_MAP; - m_image_ctx.object_map.rollback(m_snap_id, create_callback_context()); + image_ctx.object_map.rollback(m_snap_id, this->create_callback_context()); return; } } @@ -162,43 +174,49 @@ void SnapshotRollbackRequest::send_rollback_object_map() { send_rollback_objects(); } -void SnapshotRollbackRequest::send_rollback_objects() { - assert(m_image_ctx.owner_lock.is_locked()); +template +void SnapshotRollbackRequest::send_rollback_objects() { + I &image_ctx = this->m_image_ctx; + assert(image_ctx.owner_lock.is_locked()); - CephContext *cct = m_image_ctx.cct; + CephContext *cct = image_ctx.cct; ldout(cct, 5) << this << " " << __func__ << dendl; m_state = STATE_ROLLBACK_OBJECTS; uint64_t num_objects; { - RWLock::RLocker snap_locker(m_image_ctx.snap_lock); - num_objects = Striper::get_num_objects(m_image_ctx.layout, - m_image_ctx.get_current_size()); + RWLock::RLocker snap_locker(image_ctx.snap_lock); + num_objects = Striper::get_num_objects(image_ctx.layout, + image_ctx.get_current_size()); } - Context *ctx = create_callback_context(); - AsyncObjectThrottle<>::ContextFactory context_factory( - boost::lambda::bind(boost::lambda::new_ptr(), - boost::lambda::_1, &m_image_ctx, m_snap_id, boost::lambda::_2)); - AsyncObjectThrottle<> *throttle = new AsyncObjectThrottle<>( - this, m_image_ctx, context_factory, ctx, &m_prog_ctx, 0, num_objects); - throttle->start_ops(m_image_ctx.concurrent_management_ops); + Context *ctx = this->create_callback_context(); + typename AsyncObjectThrottle::ContextFactory context_factory( + boost::lambda::bind(boost::lambda::new_ptr >(), + boost::lambda::_1, &image_ctx, m_snap_id, boost::lambda::_2)); + AsyncObjectThrottle *throttle = new AsyncObjectThrottle<>( + this, image_ctx, context_factory, ctx, &m_prog_ctx, 0, num_objects); + throttle->start_ops(image_ctx.concurrent_management_ops); } -bool SnapshotRollbackRequest::send_invalidate_cache() { - assert(m_image_ctx.owner_lock.is_locked()); +template +bool SnapshotRollbackRequest::send_invalidate_cache() { + I &image_ctx = this->m_image_ctx; + assert(image_ctx.owner_lock.is_locked()); - if (m_image_ctx.object_cacher == NULL) { + if (image_ctx.object_cacher == NULL) { return true; } - CephContext *cct = m_image_ctx.cct; + CephContext *cct = image_ctx.cct; ldout(cct, 5) << this << " " << __func__ << dendl; m_state = STATE_INVALIDATE_CACHE; - m_image_ctx.invalidate_cache(create_callback_context()); + image_ctx.invalidate_cache(this->create_callback_context()); return false; } } // namespace operation } // namespace librbd + +template class librbd::operation::SnapshotRollbackRequest; diff --git a/src/librbd/operation/SnapshotRollbackRequest.h b/src/librbd/operation/SnapshotRollbackRequest.h index f074e488465cf..f66fc5ba0b111 100644 --- a/src/librbd/operation/SnapshotRollbackRequest.h +++ b/src/librbd/operation/SnapshotRollbackRequest.h @@ -17,7 +17,8 @@ class ProgressContext; namespace operation { -class SnapshotRollbackRequest : public Request { +template +class SnapshotRollbackRequest : public Request { public: /** * Snap Rollback goes through the following state machine: @@ -54,7 +55,7 @@ public: STATE_INVALIDATE_CACHE }; - SnapshotRollbackRequest(ImageCtx &image_ctx, Context *on_finish, + SnapshotRollbackRequest(ImageCtxT &image_ctx, Context *on_finish, const std::string &snap_name, uint64_t snap_id, uint64_t snap_size, ProgressContext &prog_ctx); @@ -85,4 +86,6 @@ private: } // namespace operation } // namespace librbd +extern template class librbd::operation::SnapshotRollbackRequest; + #endif // CEPH_LIBRBD_OPERATION_SNAPSHOT_ROLLBACK_REQUEST_H diff --git a/src/librbd/operation/SnapshotUnprotectRequest.cc b/src/librbd/operation/SnapshotUnprotectRequest.cc index 6d6d334f40ce4..c9c8f54224c46 100644 --- a/src/librbd/operation/SnapshotUnprotectRequest.cc +++ b/src/librbd/operation/SnapshotUnprotectRequest.cc @@ -28,19 +28,20 @@ namespace { typedef std::pair Pool; typedef std::vector Pools; +template std::ostream& operator<<(std::ostream& os, - const SnapshotUnprotectRequest::State& state) { + const typename SnapshotUnprotectRequest::State& state) { switch(state) { - case SnapshotUnprotectRequest::STATE_UNPROTECT_SNAP_START: + case SnapshotUnprotectRequest::STATE_UNPROTECT_SNAP_START: os << "UNPROTECT_SNAP_START"; break; - case SnapshotUnprotectRequest::STATE_SCAN_POOL_CHILDREN: + case SnapshotUnprotectRequest::STATE_SCAN_POOL_CHILDREN: os << "SCAN_POOL_CHILDREN"; break; - case SnapshotUnprotectRequest::STATE_UNPROTECT_SNAP_FINISH: + case SnapshotUnprotectRequest::STATE_UNPROTECT_SNAP_FINISH: os << "UNPROTECT_SNAP_FINISH"; break; - case SnapshotUnprotectRequest::STATE_UNPROTECT_SNAP_ROLLBACK: + case SnapshotUnprotectRequest::STATE_UNPROTECT_SNAP_ROLLBACK: os << "UNPROTECT_SNAP_ROLLBACK"; break; default: @@ -50,23 +51,25 @@ std::ostream& operator<<(std::ostream& os, return os; } -class C_ScanPoolChildren : public C_AsyncObjectThrottle<> { +template +class C_ScanPoolChildren : public C_AsyncObjectThrottle { public: - C_ScanPoolChildren(AsyncObjectThrottle<> &throttle, ImageCtx *image_ctx, + C_ScanPoolChildren(AsyncObjectThrottle &throttle, I *image_ctx, const parent_spec &pspec, const Pools &pools, size_t pool_idx) - : C_AsyncObjectThrottle(throttle, *image_ctx), m_pspec(pspec), + : C_AsyncObjectThrottle(throttle, *image_ctx), m_pspec(pspec), m_pool(pools[pool_idx]) { } virtual int send() { - assert(m_image_ctx.owner_lock.is_locked()); + I &image_ctx = this->m_image_ctx; + assert(image_ctx.owner_lock.is_locked()); - CephContext *cct = m_image_ctx.cct; + CephContext *cct = image_ctx.cct; ldout(cct, 10) << this << " scanning pool '" << m_pool.second << "'" << dendl; - librados::Rados rados(m_image_ctx.md_ctx); + librados::Rados rados(image_ctx.md_ctx); int64_t base_tier; int r = rados.pool_get_base_tier(m_pool.first, &base_tier); if (r == -ENOENT) { @@ -101,7 +104,8 @@ public: protected: virtual void finish(int r) { - CephContext *cct = m_image_ctx.cct; + I &image_ctx = this->m_image_ctx; + CephContext *cct = image_ctx.cct; ldout(cct, 10) << this << " retrieved children: r=" << r << dendl; if (r == -ENOENT) { @@ -118,7 +122,7 @@ protected: << "in pool '" << m_pool.second << "'" << dendl; r = -EBUSY; } - C_AsyncObjectThrottle::finish(r); + C_AsyncObjectThrottle::finish(r); } private: @@ -132,19 +136,23 @@ private: } // anonymous namespace -SnapshotUnprotectRequest::SnapshotUnprotectRequest(ImageCtx &image_ctx, - Context *on_finish, - const std::string &snap_name) - : Request(image_ctx, on_finish), m_snap_name(snap_name), m_ret_val(0), +template +SnapshotUnprotectRequest::SnapshotUnprotectRequest(I &image_ctx, + Context *on_finish, + const std::string &snap_name) + : Request(image_ctx, on_finish), m_snap_name(snap_name), m_ret_val(0), m_snap_id(CEPH_NOSNAP) { } -void SnapshotUnprotectRequest::send_op() { +template +void SnapshotUnprotectRequest::send_op() { send_unprotect_snap_start(); } -bool SnapshotUnprotectRequest::should_complete(int r) { - CephContext *cct = m_image_ctx.cct; +template +bool SnapshotUnprotectRequest::should_complete(int r) { + I &image_ctx = this->m_image_ctx; + CephContext *cct = image_ctx.cct; ldout(cct, 5) << this << " " << __func__ << ": state=" << m_state << ", " << "r=" << r << dendl; if (r < 0) { @@ -159,7 +167,7 @@ bool SnapshotUnprotectRequest::should_complete(int r) { return should_complete_error(); } - RWLock::RLocker owner_lock(m_image_ctx.owner_lock); + RWLock::RLocker owner_lock(image_ctx.owner_lock); bool finished = false; switch (m_state) { case STATE_UNPROTECT_SNAP_START: @@ -178,9 +186,11 @@ bool SnapshotUnprotectRequest::should_complete(int r) { return finished; } -bool SnapshotUnprotectRequest::should_complete_error() { - RWLock::RLocker owner_locker(m_image_ctx.owner_lock); - CephContext *cct = m_image_ctx.cct; +template +bool SnapshotUnprotectRequest::should_complete_error() { + I &image_ctx = this->m_image_ctx; + RWLock::RLocker owner_locker(image_ctx.owner_lock); + CephContext *cct = image_ctx.cct; lderr(cct) << this << " " << __func__ << ": " << "ret_val=" << m_ret_val << dendl; @@ -193,54 +203,59 @@ bool SnapshotUnprotectRequest::should_complete_error() { return finished; } -void SnapshotUnprotectRequest::send_unprotect_snap_start() { - assert(m_image_ctx.owner_lock.is_locked()); +template +void SnapshotUnprotectRequest::send_unprotect_snap_start() { + I &image_ctx = this->m_image_ctx; + assert(image_ctx.owner_lock.is_locked()); - CephContext *cct = m_image_ctx.cct; + CephContext *cct = image_ctx.cct; ldout(cct, 5) << this << " " << __func__ << dendl; m_state = STATE_UNPROTECT_SNAP_START; int r = verify_and_send_unprotect_snap_start(); if (r < 0) { - async_complete(r); + this->async_complete(r); return; } } -void SnapshotUnprotectRequest::send_scan_pool_children() { - assert(m_image_ctx.owner_lock.is_locked()); +template +void SnapshotUnprotectRequest::send_scan_pool_children() { + I &image_ctx = this->m_image_ctx; + assert(image_ctx.owner_lock.is_locked()); - CephContext *cct = m_image_ctx.cct; + CephContext *cct = image_ctx.cct; ldout(cct, 5) << this << " " << __func__ << dendl; m_state = STATE_SCAN_POOL_CHILDREN; // search all pools for children depending on this snapshot // TODO add async version of wait_for_latest_osdmap - librados::Rados rados(m_image_ctx.md_ctx); + librados::Rados rados(image_ctx.md_ctx); rados.wait_for_latest_osdmap(); // protect against pools being renamed/deleted std::list pool_list; rados.pool_list2(pool_list); - parent_spec pspec(m_image_ctx.md_ctx.get_id(), m_image_ctx.id, m_snap_id); + parent_spec pspec(image_ctx.md_ctx.get_id(), image_ctx.id, m_snap_id); Pools pools(pool_list.begin(), pool_list.end()); - Context *ctx = create_callback_context(); - AsyncObjectThrottle<>::ContextFactory context_factory( - boost::lambda::bind(boost::lambda::new_ptr(), - boost::lambda::_1, &m_image_ctx, pspec, pools, boost::lambda::_2)); - AsyncObjectThrottle<> *throttle = new AsyncObjectThrottle<>( - this, m_image_ctx, context_factory, ctx, NULL, 0, - pools.size()); - throttle->start_ops(m_image_ctx.concurrent_management_ops); + Context *ctx = this->create_callback_context(); + typename AsyncObjectThrottle::ContextFactory context_factory( + boost::lambda::bind(boost::lambda::new_ptr >(), + boost::lambda::_1, &image_ctx, pspec, pools, boost::lambda::_2)); + AsyncObjectThrottle *throttle = new AsyncObjectThrottle( + this, image_ctx, context_factory, ctx, NULL, 0, pools.size()); + throttle->start_ops(image_ctx.concurrent_management_ops); } -void SnapshotUnprotectRequest::send_unprotect_snap_finish() { - assert(m_image_ctx.owner_lock.is_locked()); +template +void SnapshotUnprotectRequest::send_unprotect_snap_finish() { + I &image_ctx = this->m_image_ctx; + assert(image_ctx.owner_lock.is_locked()); - CephContext *cct = m_image_ctx.cct; + CephContext *cct = image_ctx.cct; ldout(cct, 5) << this << " " << __func__ << dendl; m_state = STATE_UNPROTECT_SNAP_FINISH; @@ -249,16 +264,18 @@ void SnapshotUnprotectRequest::send_unprotect_snap_finish() { cls_client::set_protection_status(&op, m_snap_id, RBD_PROTECTION_STATUS_UNPROTECTED); - librados::AioCompletion *comp = create_callback_completion(); - int r = m_image_ctx.md_ctx.aio_operate(m_image_ctx.header_oid, comp, &op); + librados::AioCompletion *comp = this->create_callback_completion(); + int r = image_ctx.md_ctx.aio_operate(image_ctx.header_oid, comp, &op); assert(r == 0); comp->release(); } -void SnapshotUnprotectRequest::send_unprotect_snap_rollback() { - assert(m_image_ctx.owner_lock.is_locked()); +template +void SnapshotUnprotectRequest::send_unprotect_snap_rollback() { + I &image_ctx = this->m_image_ctx; + assert(image_ctx.owner_lock.is_locked()); - CephContext *cct = m_image_ctx.cct; + CephContext *cct = image_ctx.cct; ldout(cct, 5) << this << " " << __func__ << dendl; m_state = STATE_UNPROTECT_SNAP_ROLLBACK; @@ -267,29 +284,31 @@ void SnapshotUnprotectRequest::send_unprotect_snap_rollback() { cls_client::set_protection_status(&op, m_snap_id, RBD_PROTECTION_STATUS_PROTECTED); - librados::AioCompletion *comp = create_callback_completion(); - int r = m_image_ctx.md_ctx.aio_operate(m_image_ctx.header_oid, comp, &op); + librados::AioCompletion *comp = this->create_callback_completion(); + int r = image_ctx.md_ctx.aio_operate(image_ctx.header_oid, comp, &op); assert(r == 0); comp->release(); } -int SnapshotUnprotectRequest::verify_and_send_unprotect_snap_start() { - RWLock::RLocker md_locker(m_image_ctx.md_lock); - RWLock::RLocker snap_locker(m_image_ctx.snap_lock); +template +int SnapshotUnprotectRequest::verify_and_send_unprotect_snap_start() { + I &image_ctx = this->m_image_ctx; + RWLock::RLocker md_locker(image_ctx.md_lock); + RWLock::RLocker snap_locker(image_ctx.snap_lock); - CephContext *cct = m_image_ctx.cct; - if ((m_image_ctx.features & RBD_FEATURE_LAYERING) == 0) { + CephContext *cct = image_ctx.cct; + if ((image_ctx.features & RBD_FEATURE_LAYERING) == 0) { lderr(cct) << "image must support layering" << dendl; return -ENOSYS; } - m_snap_id = m_image_ctx.get_snap_id(m_snap_name); + m_snap_id = image_ctx.get_snap_id(m_snap_name); if (m_snap_id == CEPH_NOSNAP) { return -ENOENT; } bool is_unprotected; - int r = m_image_ctx.is_snap_unprotected(m_snap_id, &is_unprotected); + int r = image_ctx.is_snap_unprotected(m_snap_id, &is_unprotected); if (r < 0) { return r; } @@ -303,8 +322,8 @@ int SnapshotUnprotectRequest::verify_and_send_unprotect_snap_start() { cls_client::set_protection_status(&op, m_snap_id, RBD_PROTECTION_STATUS_UNPROTECTING); - librados::AioCompletion *comp = create_callback_completion(); - r = m_image_ctx.md_ctx.aio_operate(m_image_ctx.header_oid, comp, &op); + librados::AioCompletion *comp = this->create_callback_completion(); + r = image_ctx.md_ctx.aio_operate(image_ctx.header_oid, comp, &op); assert(r == 0); comp->release(); @@ -315,3 +334,4 @@ int SnapshotUnprotectRequest::verify_and_send_unprotect_snap_start() { } // namespace operation } // namespace librbd +template class librbd::operation::SnapshotUnprotectRequest; diff --git a/src/librbd/operation/SnapshotUnprotectRequest.h b/src/librbd/operation/SnapshotUnprotectRequest.h index 3eacc3e71bec0..3b940c3acb4e5 100644 --- a/src/librbd/operation/SnapshotUnprotectRequest.h +++ b/src/librbd/operation/SnapshotUnprotectRequest.h @@ -16,7 +16,8 @@ class ImageCtx; namespace operation { -class SnapshotUnprotectRequest : public Request { +template +class SnapshotUnprotectRequest : public Request { public: /** * Snap Unprotect goes through the following state machine: @@ -49,7 +50,7 @@ public: STATE_UNPROTECT_SNAP_ROLLBACK }; - SnapshotUnprotectRequest(ImageCtx &image_ctx, Context *on_finish, + SnapshotUnprotectRequest(ImageCtxT &image_ctx, Context *on_finish, const std::string &snap_name); protected: @@ -87,4 +88,6 @@ private: } // namespace operation } // namespace librbd +extern template class librbd::operation::SnapshotUnprotectRequest; + #endif // CEPH_LIBRBD_OPERATION_SNAPSHOT_UNPROTECT_REQUEST_H diff --git a/src/librbd/operation/TrimRequest.cc b/src/librbd/operation/TrimRequest.cc index 71b1546ef6d2e..da5a3bb4bc3fa 100644 --- a/src/librbd/operation/TrimRequest.cc +++ b/src/librbd/operation/TrimRequest.cc @@ -25,24 +25,26 @@ namespace librbd { namespace operation { -class C_CopyupObject : public C_AsyncObjectThrottle<> { +template +class C_CopyupObject : public C_AsyncObjectThrottle { public: - C_CopyupObject(AsyncObjectThrottle<> &throttle, ImageCtx *image_ctx, + C_CopyupObject(AsyncObjectThrottle &throttle, I *image_ctx, ::SnapContext snapc, uint64_t object_no) - : C_AsyncObjectThrottle(throttle, *image_ctx), m_snapc(snapc), + : C_AsyncObjectThrottle(throttle, *image_ctx), m_snapc(snapc), m_object_no(object_no) { } virtual int send() { - assert(m_image_ctx.owner_lock.is_locked()); - assert(!m_image_ctx.image_watcher->is_lock_supported() || - m_image_ctx.image_watcher->is_lock_owner()); + I &image_ctx = this->m_image_ctx; + assert(image_ctx.owner_lock.is_locked()); + assert(!image_ctx.image_watcher->is_lock_supported() || + image_ctx.image_watcher->is_lock_owner()); - string oid = m_image_ctx.get_object_name(m_object_no); - ldout(m_image_ctx.cct, 10) << "removing (with copyup) " << oid << dendl; + string oid = image_ctx.get_object_name(m_object_no); + ldout(image_ctx.cct, 10) << "removing (with copyup) " << oid << dendl; - AioObjectRequest *req = new AioObjectTrim(&m_image_ctx, oid, m_object_no, + AioObjectRequest *req = new AioObjectTrim(&image_ctx, oid, m_object_no, m_snapc, this); req->send(); return 0; @@ -52,28 +54,30 @@ private: uint64_t m_object_no; }; -class C_RemoveObject : public C_AsyncObjectThrottle<> { +template +class C_RemoveObject : public C_AsyncObjectThrottle { public: - C_RemoveObject(AsyncObjectThrottle<> &throttle, ImageCtx *image_ctx, + C_RemoveObject(AsyncObjectThrottle &throttle, ImageCtx *image_ctx, uint64_t object_no) - : C_AsyncObjectThrottle(throttle, *image_ctx), m_object_no(object_no) + : C_AsyncObjectThrottle(throttle, *image_ctx), m_object_no(object_no) { } virtual int send() { - assert(m_image_ctx.owner_lock.is_locked()); - assert(!m_image_ctx.image_watcher->is_lock_supported() || - m_image_ctx.image_watcher->is_lock_owner()); - if (!m_image_ctx.object_map.object_may_exist(m_object_no)) { + I &image_ctx = this->m_image_ctx; + assert(image_ctx.owner_lock.is_locked()); + assert(!image_ctx.image_watcher->is_lock_supported() || + image_ctx.image_watcher->is_lock_owner()); + if (!image_ctx.object_map.object_may_exist(m_object_no)) { return 1; } - string oid = m_image_ctx.get_object_name(m_object_no); - ldout(m_image_ctx.cct, 10) << "removing " << oid << dendl; + string oid = image_ctx.get_object_name(m_object_no); + ldout(image_ctx.cct, 10) << "removing " << oid << dendl; librados::AioCompletion *rados_completion = librados::Rados::aio_create_completion(this, NULL, rados_ctx_cb); - int r = m_image_ctx.data_ctx.aio_remove(oid, rados_completion); + int r = image_ctx.data_ctx.aio_remove(oid, rados_completion); assert(r == 0); rados_completion->release(); return 0; @@ -83,20 +87,21 @@ private: uint64_t m_object_no; }; -TrimRequest::TrimRequest(ImageCtx &image_ctx, Context *on_finish, - uint64_t original_size, uint64_t new_size, - ProgressContext &prog_ctx) - : AsyncRequest(image_ctx, on_finish), m_new_size(new_size), +template +TrimRequest::TrimRequest(I &image_ctx, Context *on_finish, + uint64_t original_size, uint64_t new_size, + ProgressContext &prog_ctx) + : AsyncRequest(image_ctx, on_finish), m_new_size(new_size), m_prog_ctx(prog_ctx) { - uint64_t period = m_image_ctx.get_stripe_period(); + uint64_t period = image_ctx.get_stripe_period(); uint64_t new_num_periods = ((m_new_size + period - 1) / period); m_delete_off = MIN(new_num_periods * period, original_size); // first object we can delete free and clear - m_delete_start = new_num_periods * m_image_ctx.get_stripe_count(); - m_num_objects = Striper::get_num_objects(m_image_ctx.layout, original_size); + m_delete_start = new_num_periods * image_ctx.get_stripe_count(); + m_num_objects = Striper::get_num_objects(image_ctx.layout, original_size); - CephContext *cct = m_image_ctx.cct; + CephContext *cct = image_ctx.cct; ldout(cct, 10) << this << " trim image " << original_size << " -> " << m_new_size << " periods " << new_num_periods << " discard to offset " << m_delete_off @@ -104,17 +109,18 @@ TrimRequest::TrimRequest(ImageCtx &image_ctx, Context *on_finish, << " to " << m_num_objects << dendl; } - -bool TrimRequest::should_complete(int r) +template +bool TrimRequest::should_complete(int r) { - CephContext *cct = m_image_ctx.cct; + I &image_ctx = this->m_image_ctx; + CephContext *cct = image_ctx.cct; ldout(cct, 5) << this << " should_complete: r=" << r << dendl; if (r < 0) { lderr(cct) << "trim encountered an error: " << cpp_strerror(r) << dendl; return true; } - RWLock::RLocker owner_lock(m_image_ctx.owner_lock); + RWLock::RLocker owner_lock(image_ctx.owner_lock); switch (m_state) { case STATE_COPYUP_OBJECTS: ldout(cct, 5) << " COPYUP_OBJECTS" << dendl; @@ -153,14 +159,17 @@ bool TrimRequest::should_complete(int r) return false; } -void TrimRequest::send() { +template +void TrimRequest::send() { send_copyup_objects(); } -void TrimRequest::send_copyup_objects() { - assert(m_image_ctx.owner_lock.is_locked()); - assert(!m_image_ctx.image_watcher->is_lock_supported() || - m_image_ctx.image_watcher->is_lock_owner()); +template +void TrimRequest::send_copyup_objects() { + I &image_ctx = this->m_image_ctx; + assert(image_ctx.owner_lock.is_locked()); + assert(!image_ctx.image_watcher->is_lock_supported() || + image_ctx.image_watcher->is_lock_owner()); if (m_delete_start >= m_num_objects) { send_clean_boundary(); @@ -171,18 +180,18 @@ void TrimRequest::send_copyup_objects() { bool has_snapshots; uint64_t parent_overlap; { - RWLock::RLocker snap_locker(m_image_ctx.snap_lock); - RWLock::RLocker parent_locker(m_image_ctx.parent_lock); + RWLock::RLocker snap_locker(image_ctx.snap_lock); + RWLock::RLocker parent_locker(image_ctx.parent_lock); - snapc = m_image_ctx.snapc; - has_snapshots = !m_image_ctx.snaps.empty(); - int r = m_image_ctx.get_parent_overlap(m_image_ctx.get_copyup_snap_id(), + snapc = image_ctx.snapc; + has_snapshots = !image_ctx.snaps.empty(); + int r = image_ctx.get_parent_overlap(image_ctx.get_copyup_snap_id(), &parent_overlap); assert(r == 0); } // copyup is only required for portion of image that overlaps parent - uint64_t copyup_end = Striper::get_num_objects(m_image_ctx.layout, + uint64_t copyup_end = Striper::get_num_objects(image_ctx.layout, parent_overlap); // TODO: protect against concurrent shrink and snap create? if (copyup_end <= m_delete_start || !has_snapshots) { @@ -193,41 +202,45 @@ void TrimRequest::send_copyup_objects() { uint64_t copyup_start = m_delete_start; m_delete_start = copyup_end; - ldout(m_image_ctx.cct, 5) << this << " send_copyup_objects: " + ldout(image_ctx.cct, 5) << this << " send_copyup_objects: " << " start object=" << copyup_start << ", " << " end object=" << copyup_end << dendl; m_state = STATE_COPYUP_OBJECTS; - Context *ctx = create_callback_context(); - AsyncObjectThrottle<>::ContextFactory context_factory( - boost::lambda::bind(boost::lambda::new_ptr(), - boost::lambda::_1, &m_image_ctx, snapc, boost::lambda::_2)); - AsyncObjectThrottle<> *throttle = new AsyncObjectThrottle<>( - this, m_image_ctx, context_factory, ctx, &m_prog_ctx, copyup_start, + Context *ctx = this->create_callback_context(); + typename AsyncObjectThrottle::ContextFactory context_factory( + boost::lambda::bind(boost::lambda::new_ptr >(), + boost::lambda::_1, &image_ctx, snapc, boost::lambda::_2)); + AsyncObjectThrottle *throttle = new AsyncObjectThrottle( + this, image_ctx, context_factory, ctx, &m_prog_ctx, copyup_start, copyup_end); - throttle->start_ops(m_image_ctx.concurrent_management_ops); + throttle->start_ops(image_ctx.concurrent_management_ops); } -void TrimRequest::send_remove_objects() { - assert(m_image_ctx.owner_lock.is_locked()); +template +void TrimRequest::send_remove_objects() { + I &image_ctx = this->m_image_ctx; + assert(image_ctx.owner_lock.is_locked()); - ldout(m_image_ctx.cct, 5) << this << " send_remove_objects: " + ldout(image_ctx.cct, 5) << this << " send_remove_objects: " << " delete_start=" << m_delete_start << " num_objects=" << m_num_objects << dendl; m_state = STATE_REMOVE_OBJECTS; - Context *ctx = create_callback_context(); - AsyncObjectThrottle<>::ContextFactory context_factory( - boost::lambda::bind(boost::lambda::new_ptr(), - boost::lambda::_1, &m_image_ctx, boost::lambda::_2)); - AsyncObjectThrottle<> *throttle = new AsyncObjectThrottle<>( - this, m_image_ctx, context_factory, ctx, &m_prog_ctx, m_delete_start, + Context *ctx = this->create_callback_context(); + typename AsyncObjectThrottle::ContextFactory context_factory( + boost::lambda::bind(boost::lambda::new_ptr >(), + boost::lambda::_1, &image_ctx, boost::lambda::_2)); + AsyncObjectThrottle *throttle = new AsyncObjectThrottle( + this, image_ctx, context_factory, ctx, &m_prog_ctx, m_delete_start, m_num_objects); - throttle->start_ops(m_image_ctx.concurrent_management_ops); + throttle->start_ops(image_ctx.concurrent_management_ops); } -void TrimRequest::send_pre_remove() { - assert(m_image_ctx.owner_lock.is_locked()); +template +void TrimRequest::send_pre_remove() { + I &image_ctx = this->m_image_ctx; + assert(image_ctx.owner_lock.is_locked()); if (m_delete_start >= m_num_objects) { send_clean_boundary(); return; @@ -235,21 +248,21 @@ void TrimRequest::send_pre_remove() { bool remove_objects = false; { - RWLock::RLocker snap_locker(m_image_ctx.snap_lock); - if (!m_image_ctx.object_map.enabled()) { + RWLock::RLocker snap_locker(image_ctx.snap_lock); + if (!image_ctx.object_map.enabled()) { remove_objects = true; } else { - ldout(m_image_ctx.cct, 5) << this << " send_pre_remove: " + ldout(image_ctx.cct, 5) << this << " send_pre_remove: " << " delete_start=" << m_delete_start << " num_objects=" << m_num_objects << dendl; m_state = STATE_PRE_REMOVE; - assert(m_image_ctx.image_watcher->is_lock_owner()); + assert(image_ctx.image_watcher->is_lock_owner()); // flag the objects as pending deletion - Context *ctx = create_callback_context(); - RWLock::WLocker object_map_locker(m_image_ctx.object_map_lock); - if (!m_image_ctx.object_map.aio_update(m_delete_start, m_num_objects, + Context *ctx = this->create_callback_context(); + RWLock::WLocker object_map_locker(image_ctx.object_map_lock); + if (!image_ctx.object_map.aio_update(m_delete_start, m_num_objects, OBJECT_PENDING, OBJECT_EXISTS, ctx)) { delete ctx; @@ -265,26 +278,28 @@ void TrimRequest::send_pre_remove() { } } -void TrimRequest::send_post_remove() { - assert(m_image_ctx.owner_lock.is_locked()); +template +void TrimRequest::send_post_remove() { + I &image_ctx = this->m_image_ctx; + assert(image_ctx.owner_lock.is_locked()); bool clean_boundary = false; { - RWLock::RLocker snap_locker(m_image_ctx.snap_lock); - if (!m_image_ctx.object_map.enabled()) { + RWLock::RLocker snap_locker(image_ctx.snap_lock); + if (!image_ctx.object_map.enabled()) { clean_boundary = true; } else { - ldout(m_image_ctx.cct, 5) << this << " send_post_remove: " + ldout(image_ctx.cct, 5) << this << " send_post_remove: " << " delete_start=" << m_delete_start << " num_objects=" << m_num_objects << dendl; m_state = STATE_POST_REMOVE; - assert(m_image_ctx.image_watcher->is_lock_owner()); + assert(image_ctx.image_watcher->is_lock_owner()); // flag the pending objects as removed - Context *ctx = create_callback_context(); - RWLock::WLocker object_map_locker(m_image_ctx.object_map_lock); - if (!m_image_ctx.object_map.aio_update(m_delete_start, m_num_objects, + Context *ctx = this->create_callback_context(); + RWLock::WLocker object_map_locker(image_ctx.object_map_lock); + if (!image_ctx.object_map.aio_update(m_delete_start, m_num_objects, OBJECT_NONEXISTENT, OBJECT_PENDING, ctx)) { delete ctx; @@ -300,37 +315,39 @@ void TrimRequest::send_post_remove() { } } -void TrimRequest::send_clean_boundary() { - assert(m_image_ctx.owner_lock.is_locked()); - CephContext *cct = m_image_ctx.cct; +template +void TrimRequest::send_clean_boundary() { + I &image_ctx = this->m_image_ctx; + assert(image_ctx.owner_lock.is_locked()); + CephContext *cct = image_ctx.cct; if (m_delete_off <= m_new_size) { send_finish(0); return; } // should have been canceled prior to releasing lock - assert(!m_image_ctx.image_watcher->is_lock_supported() || - m_image_ctx.image_watcher->is_lock_owner()); + assert(!image_ctx.image_watcher->is_lock_supported() || + image_ctx.image_watcher->is_lock_owner()); uint64_t delete_len = m_delete_off - m_new_size; - ldout(m_image_ctx.cct, 5) << this << " send_clean_boundary: " + ldout(image_ctx.cct, 5) << this << " send_clean_boundary: " << " delete_off=" << m_delete_off << " length=" << delete_len << dendl; m_state = STATE_CLEAN_BOUNDARY; ::SnapContext snapc; { - RWLock::RLocker snap_locker(m_image_ctx.snap_lock); - snapc = m_image_ctx.snapc; + RWLock::RLocker snap_locker(image_ctx.snap_lock); + snapc = image_ctx.snapc; } // discard the weird boundary std::vector extents; - Striper::file_to_extents(cct, m_image_ctx.format_string, - &m_image_ctx.layout, m_new_size, delete_len, 0, + Striper::file_to_extents(cct, image_ctx.format_string, + &image_ctx.layout, m_new_size, delete_len, 0, extents); ContextCompletion *completion = - new ContextCompletion(create_async_callback_context(), true); + new ContextCompletion(this->create_async_callback_context(), true); for (vector::iterator p = extents.begin(); p != extents.end(); ++p) { ldout(cct, 20) << " ex " << *p << dendl; @@ -338,10 +355,10 @@ void TrimRequest::send_clean_boundary() { AioObjectRequest *req; if (p->offset == 0) { - req = new AioObjectTrim(&m_image_ctx, p->oid.name, p->objectno, snapc, + req = new AioObjectTrim(&image_ctx, p->oid.name, p->objectno, snapc, req_comp); } else { - req = new AioObjectTruncate(&m_image_ctx, p->oid.name, p->objectno, + req = new AioObjectTruncate(&image_ctx, p->oid.name, p->objectno, p->offset, snapc, req_comp); } req->send(); @@ -349,10 +366,13 @@ void TrimRequest::send_clean_boundary() { completion->finish_adding_requests(); } -void TrimRequest::send_finish(int r) { +template +void TrimRequest::send_finish(int r) { m_state = STATE_FINISHED; - async_complete(r); + this->async_complete(r); } } // namespace operation } // namespace librbd + +template class librbd::operation::TrimRequest; diff --git a/src/librbd/operation/TrimRequest.h b/src/librbd/operation/TrimRequest.h index d8b9358297ac4..6e6c50c9f4fc0 100644 --- a/src/librbd/operation/TrimRequest.h +++ b/src/librbd/operation/TrimRequest.h @@ -13,12 +13,13 @@ class ProgressContext; namespace operation { -class TrimRequest : public AsyncRequest<> +template +class TrimRequest : public AsyncRequest { public: - TrimRequest(ImageCtx &image_ctx, Context *on_finish, - uint64_t original_size, uint64_t new_size, - ProgressContext &prog_ctx); + TrimRequest(ImageCtxT &image_ctx, Context *on_finish, + uint64_t original_size, uint64_t new_size, + ProgressContext &prog_ctx); virtual void send(); @@ -90,4 +91,6 @@ private: } // namespace operation } // namespace librbd +extern template class librbd::operation::TrimRequest; + #endif // CEPH_LIBRBD_OPERATION_TRIM_REQUEST_H -- 2.39.5