From a3b2d82c2410957f912b4742198c6e2bc2277fd6 Mon Sep 17 00:00:00 2001 From: Jason Dillaman Date: Wed, 24 Jan 2018 16:26:51 -0500 Subject: [PATCH] librbd: flatten request now handles clone v2 Signed-off-by: Jason Dillaman --- src/librbd/operation/FlattenRequest.cc | 70 +++++++++++++------------- src/librbd/operation/FlattenRequest.h | 8 +-- 2 files changed, 38 insertions(+), 40 deletions(-) diff --git a/src/librbd/operation/FlattenRequest.cc b/src/librbd/operation/FlattenRequest.cc index 3ece4def30778..4df4094ab9c07 100644 --- a/src/librbd/operation/FlattenRequest.cc +++ b/src/librbd/operation/FlattenRequest.cc @@ -5,6 +5,7 @@ #include "librbd/AsyncObjectThrottle.h" #include "librbd/ExclusiveLock.h" #include "librbd/ImageCtx.h" +#include "librbd/image/DetachChildRequest.h" #include "librbd/io/ObjectRequest.h" #include "common/dout.h" #include "common/errno.h" @@ -75,10 +76,10 @@ bool FlattenRequest::should_complete(int r) { switch (m_state) { case STATE_FLATTEN_OBJECTS: ldout(cct, 5) << "FLATTEN_OBJECTS" << dendl; - return send_update_children(); + return send_detach_child(); - case STATE_UPDATE_CHILDREN: - ldout(cct, 5) << "UPDATE_CHILDREN" << dendl; + case STATE_DETACH_CHILD: + ldout(cct, 5) << "DETACH_CHILD" << dendl; return send_update_header(); case STATE_UPDATE_HEADER: @@ -111,69 +112,66 @@ void FlattenRequest::send_op() { } template -bool FlattenRequest::send_update_header() { +bool FlattenRequest::send_detach_child() { 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(image_ctx.exclusive_lock == nullptr || image_ctx.exclusive_lock->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 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 (!image_ctx.parent) { - ldout(cct, 5) << "image already flattened" << dendl; - return true; + RWLock::RLocker snap_locker(image_ctx.snap_lock); + if ((image_ctx.features & RBD_FEATURE_DEEP_FLATTEN) == 0 && + !image_ctx.snaps.empty()) { + return send_update_header(); } - m_parent_spec = image_ctx.parent_md.spec; } - // remove parent from this (base) image - librados::ObjectWriteOperation op; - cls_client::remove_parent(&op); + ldout(cct, 2) << "detaching child" << dendl; + m_state = STATE_DETACH_CHILD; - 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(); + auto req = image::DetachChildRequest::create( + image_ctx, this->create_callback_context()); + req->send(); return false; } template -bool FlattenRequest::send_update_children() { +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(image_ctx.exclusive_lock == nullptr || image_ctx.exclusive_lock->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(image_ctx.snap_lock); - if ((image_ctx.features & RBD_FEATURE_DEEP_FLATTEN) == 0 && - !image_ctx.snaps.empty()) { - return send_update_header(); + { + 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 (!image_ctx.parent) { + ldout(cct, 5) << "image already flattened" << dendl; + return true; + } + m_parent_spec = image_ctx.parent_md.spec; } - ldout(cct, 2) << "removing child from children list..." << dendl; - m_state = STATE_UPDATE_CHILDREN; - + // remove parent from this (base) image librados::ObjectWriteOperation op; - cls_client::remove_child(&op, m_parent_spec, image_ctx.id); + cls_client::remove_parent(&op); librados::AioCompletion *rados_completion = this->create_callback_completion(); - int r = image_ctx.md_ctx.aio_operate(RBD_CHILDREN, rados_completion, - &op); + int r = image_ctx.md_ctx.aio_operate(image_ctx.header_oid, + rados_completion, &op); assert(r == 0); rados_completion->release(); return false; diff --git a/src/librbd/operation/FlattenRequest.h b/src/librbd/operation/FlattenRequest.h index 7d87c0ead08dd..54638700e5332 100644 --- a/src/librbd/operation/FlattenRequest.h +++ b/src/librbd/operation/FlattenRequest.h @@ -43,7 +43,7 @@ private: * * | * v - * STATE_FLATTEN_OBJECTS ---> STATE_UPDATE_CHILDREN . . . . + * STATE_FLATTEN_OBJECTS ---> STATE_DETACH_CHILD . . . . . * . | . * . | . * . v . @@ -57,13 +57,13 @@ private: * * @endverbatim * - * The _UPDATE_CHILDREN state will be skipped if the image has one or + * The _DETACH_CHILD state will be skipped if the image has one or * more snapshots. The _UPDATE_HEADER state will be skipped if the * image was concurrently flattened by another client. */ enum State { STATE_FLATTEN_OBJECTS, - STATE_UPDATE_CHILDREN, + STATE_DETACH_CHILD, STATE_UPDATE_HEADER }; @@ -74,8 +74,8 @@ private: ParentSpec m_parent_spec; + bool send_detach_child(); bool send_update_header(); - bool send_update_children(); }; } // namespace operation -- 2.39.5