X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fceph%2Fsrc%2Flibrbd%2Foperation%2FSnapshotUnprotectRequest.cc;fp=src%2Fceph%2Fsrc%2Flibrbd%2Foperation%2FSnapshotUnprotectRequest.cc;h=0000000000000000000000000000000000000000;hb=7da45d65be36d36b880cc55c5036e96c24b53f00;hp=369d8e283a140e58bf372385a35a818013853a8c;hpb=691462d09d0987b47e112d6ee8740375df3c51b2;p=stor4nfv.git diff --git a/src/ceph/src/librbd/operation/SnapshotUnprotectRequest.cc b/src/ceph/src/librbd/operation/SnapshotUnprotectRequest.cc deleted file mode 100644 index 369d8e2..0000000 --- a/src/ceph/src/librbd/operation/SnapshotUnprotectRequest.cc +++ /dev/null @@ -1,355 +0,0 @@ -// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- -// vim: ts=8 sw=2 smarttab - -#include "librbd/operation/SnapshotUnprotectRequest.h" -#include "include/rados/librados.hpp" -#include "include/stringify.h" -#include "common/dout.h" -#include "common/errno.h" -#include "librbd/AsyncObjectThrottle.h" -#include "librbd/ImageCtx.h" -#include "librbd/internal.h" -#include "librbd/Types.h" -#include "librbd/Utils.h" -#include -#include -#include -#include -#include - -#define dout_subsys ceph_subsys_rbd -#undef dout_prefix -#define dout_prefix *_dout << "librbd::SnapshotUnprotectRequest: " - -namespace librbd { -namespace operation { - -namespace { - -typedef std::pair Pool; -typedef std::vector Pools; - -template -std::ostream& operator<<(std::ostream& os, - const typename SnapshotUnprotectRequest::State& state) { - switch(state) { - case SnapshotUnprotectRequest::STATE_UNPROTECT_SNAP_START: - os << "UNPROTECT_SNAP_START"; - break; - case SnapshotUnprotectRequest::STATE_SCAN_POOL_CHILDREN: - os << "SCAN_POOL_CHILDREN"; - break; - case SnapshotUnprotectRequest::STATE_UNPROTECT_SNAP_FINISH: - os << "UNPROTECT_SNAP_FINISH"; - break; - case SnapshotUnprotectRequest::STATE_UNPROTECT_SNAP_ROLLBACK: - os << "UNPROTECT_SNAP_ROLLBACK"; - break; - default: - os << "UNKNOWN (" << static_cast(state) << ")"; - break; - } - return os; -} - -template -class C_ScanPoolChildren : public C_AsyncObjectThrottle { -public: - C_ScanPoolChildren(AsyncObjectThrottle &throttle, I *image_ctx, - const ParentSpec &pspec, const Pools &pools, - size_t pool_idx) - : C_AsyncObjectThrottle(throttle, *image_ctx), m_pspec(pspec), - m_pool(pools[pool_idx]) { - } - - int send() override { - I &image_ctx = this->m_image_ctx; - assert(image_ctx.owner_lock.is_locked()); - - CephContext *cct = image_ctx.cct; - ldout(cct, 10) << this << " scanning pool '" << m_pool.second << "'" - << dendl; - - 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) { - ldout(cct, 1) << "pool '" << m_pool.second << "' no longer exists" - << dendl; - return 1; - } else if (r < 0) { - lderr(cct) << "error retrieving base tier for pool '" - << m_pool.second << "'" << dendl; - return r; - } - if (m_pool.first != base_tier) { - // pool is a cache; skip it - return 1; - } - - r = rados.ioctx_create2(m_pool.first, m_pool_ioctx); - if (r == -ENOENT) { - ldout(cct, 1) << "pool '" << m_pool.second << "' no longer exists" - << dendl; - return 1; - } else if (r < 0) { - lderr(cct) << "can't create ioctx for pool '" << m_pool.second - << "'" << dendl; - return r; - } - - librados::ObjectReadOperation op; - cls_client::get_children_start(&op, m_pspec); - - librados::AioCompletion *rados_completion = - util::create_rados_callback(this); - r = m_pool_ioctx.aio_operate(RBD_CHILDREN, rados_completion, &op, - &m_children_bl); - assert(r == 0); - rados_completion->release(); - return 0; - } - -protected: - void finish(int r) override { - I &image_ctx = this->m_image_ctx; - CephContext *cct = image_ctx.cct; - - if (r == 0) { - bufferlist::iterator it = m_children_bl.begin(); - r= cls_client::get_children_finish(&it, &m_children); - } - - ldout(cct, 10) << this << " retrieved children: r=" << r << dendl; - if (r == -ENOENT) { - // no children -- proceed with unprotect - r = 0; - } else if (r < 0) { - lderr(cct) << "cannot get children for pool '" << m_pool.second << "'" - << dendl; - } else { - lderr(cct) << "cannot unprotect: at least " << m_children.size() << " " - << "child(ren) [" << joinify(m_children.begin(), - m_children.end(), - std::string(",")) << "] " - << "in pool '" << m_pool.second << "'" << dendl; - r = -EBUSY; - } - C_AsyncObjectThrottle::finish(r); - } - -private: - ParentSpec m_pspec; - Pool m_pool; - - IoCtx m_pool_ioctx; - std::set m_children; - bufferlist m_children_bl; -}; - -} // anonymous namespace - -template -SnapshotUnprotectRequest::SnapshotUnprotectRequest(I &image_ctx, - Context *on_finish, - const cls::rbd::SnapshotNamespace &snap_namespace, - const std::string &snap_name) - : Request(image_ctx, on_finish), m_snap_namespace(snap_namespace), - m_snap_name(snap_name), m_ret_val(0), m_snap_id(CEPH_NOSNAP) { -} - -template -void SnapshotUnprotectRequest::send_op() { - send_unprotect_snap_start(); -} - -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) { - if (r == -EINVAL) { - ldout(cct, 1) << "snapshot is already unprotected" << dendl; - } else { - lderr(cct) << "encountered error: " << cpp_strerror(r) << dendl; - } - if (m_ret_val == 0) { - m_ret_val = r; - } - } - - // use a different state machine once an error is encountered - if (m_ret_val < 0) { - return should_complete_error(); - } - - RWLock::RLocker owner_lock(image_ctx.owner_lock); - bool finished = false; - switch (m_state) { - case STATE_UNPROTECT_SNAP_START: - send_scan_pool_children(); - break; - case STATE_SCAN_POOL_CHILDREN: - send_unprotect_snap_finish(); - break; - case STATE_UNPROTECT_SNAP_FINISH: - finished = true; - break; - default: - assert(false); - break; - } - return finished; -} - -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; - - bool finished = true; - if (m_state == STATE_SCAN_POOL_CHILDREN || - m_state == STATE_UNPROTECT_SNAP_FINISH) { - send_unprotect_snap_rollback(); - finished = false; - } - return finished; -} - -template -void SnapshotUnprotectRequest::send_unprotect_snap_start() { - I &image_ctx = this->m_image_ctx; - assert(image_ctx.owner_lock.is_locked()); - - 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) { - this->async_complete(r); - return; - } -} - -template -void SnapshotUnprotectRequest::send_scan_pool_children() { - I &image_ctx = this->m_image_ctx; - assert(image_ctx.owner_lock.is_locked()); - - 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(image_ctx.md_ctx); - rados.wait_for_latest_osdmap(); - - // protect against pools being renamed/deleted - std::list pool_list; - rados.pool_list2(pool_list); - - ParentSpec pspec(image_ctx.md_ctx.get_id(), image_ctx.id, m_snap_id); - Pools pools(pool_list.begin(), pool_list.end()); - - 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( - nullptr, image_ctx, context_factory, ctx, NULL, 0, pools.size()); - throttle->start_ops(image_ctx.concurrent_management_ops); -} - -template -void SnapshotUnprotectRequest::send_unprotect_snap_finish() { - I &image_ctx = this->m_image_ctx; - assert(image_ctx.owner_lock.is_locked()); - - CephContext *cct = image_ctx.cct; - ldout(cct, 5) << this << " " << __func__ << dendl; - - m_state = STATE_UNPROTECT_SNAP_FINISH; - - librados::ObjectWriteOperation op; - cls_client::set_protection_status(&op, m_snap_id, - RBD_PROTECTION_STATUS_UNPROTECTED); - - 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(); -} - -template -void SnapshotUnprotectRequest::send_unprotect_snap_rollback() { - I &image_ctx = this->m_image_ctx; - assert(image_ctx.owner_lock.is_locked()); - - CephContext *cct = image_ctx.cct; - ldout(cct, 5) << this << " " << __func__ << dendl; - - m_state = STATE_UNPROTECT_SNAP_ROLLBACK; - - librados::ObjectWriteOperation op; - cls_client::set_protection_status(&op, m_snap_id, - RBD_PROTECTION_STATUS_PROTECTED); - - 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(); -} - -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 = image_ctx.cct; - if ((image_ctx.features & RBD_FEATURE_LAYERING) == 0) { - lderr(cct) << "image must support layering" << dendl; - return -ENOSYS; - } - - m_snap_id = image_ctx.get_snap_id(m_snap_namespace, m_snap_name); - if (m_snap_id == CEPH_NOSNAP) { - return -ENOENT; - } - - bool is_unprotected; - int r = image_ctx.is_snap_unprotected(m_snap_id, &is_unprotected); - if (r < 0) { - return r; - } - - if (is_unprotected) { - lderr(cct) << "snapshot is already unprotected" << dendl; - return -EINVAL; - } - - librados::ObjectWriteOperation op; - cls_client::set_protection_status(&op, m_snap_id, - RBD_PROTECTION_STATUS_UNPROTECTING); - - 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(); - - // TODO legacy code threw a notification post UNPROTECTING update -- required? - return 0; -} - -} // namespace operation -} // namespace librbd - -template class librbd::operation::SnapshotUnprotectRequest;