From: Mykola Golub Date: Sun, 27 May 2018 12:06:59 +0000 (+0300) Subject: librbd: open migration image parent and store its pointer in ImageCtx X-Git-Tag: v14.0.1~590^2~6 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=1cfbf1ec65ff8404da747d86ccb882fa8ddb0128;p=ceph.git librbd: open migration image parent and store its pointer in ImageCtx Use the pointer in copyup and migrate requests, when deep copying an object. Signed-off-by: Mykola Golub --- diff --git a/src/librbd/ImageCtx.h b/src/librbd/ImageCtx.h index b2558ea471e20..259227870e3ab 100644 --- a/src/librbd/ImageCtx.h +++ b/src/librbd/ImageCtx.h @@ -124,6 +124,7 @@ namespace librbd { ImageCtx *parent; ImageCtx *child = nullptr; MigrationInfo migration_info; + ImageCtx *migration_parent = nullptr; cls::rbd::GroupSpec group_spec; uint64_t stripe_unit, stripe_count; uint64_t flags; diff --git a/src/librbd/image/CloseRequest.cc b/src/librbd/image/CloseRequest.cc index de0928ee1819e..f4c0eb8a4d6a3 100644 --- a/src/librbd/image/CloseRequest.cc +++ b/src/librbd/image/CloseRequest.cc @@ -266,6 +266,36 @@ template void CloseRequest::handle_flush_op_work_queue(int r) { CephContext *cct = m_image_ctx->cct; ldout(cct, 10) << this << " " << __func__ << ": r=" << r << dendl; + send_close_migration_parent(); +} + +template +void CloseRequest::send_close_migration_parent() { + if (m_image_ctx->migration_parent == nullptr) { + send_close_parent(); + return; + } + + CephContext *cct = m_image_ctx->cct; + ldout(cct, 10) << this << " " << __func__ << dendl; + + m_image_ctx->migration_parent->state->close(create_async_context_callback( + *m_image_ctx, create_context_callback< + CloseRequest, &CloseRequest::handle_close_migration_parent>(this))); +} + +template +void CloseRequest::handle_close_migration_parent(int r) { + CephContext *cct = m_image_ctx->cct; + ldout(cct, 10) << this << " " << __func__ << ": r=" << r << dendl; + + delete m_image_ctx->migration_parent; + m_image_ctx->migration_parent = nullptr; + save_result(r); + if (r < 0) { + lderr(cct) << "error closing migration parent image: " << cpp_strerror(r) + << dendl; + } send_close_parent(); } diff --git a/src/librbd/image/CloseRequest.h b/src/librbd/image/CloseRequest.h index fd101beedb331..44916f781f13e 100644 --- a/src/librbd/image/CloseRequest.h +++ b/src/librbd/image/CloseRequest.h @@ -55,6 +55,9 @@ private: * v * FLUSH_OP_WORK_QUEUE * | + * v (skip if no migration parent) + * CLOSE_MIGRATION_PARENT + * | * v (skip if no parent) * CLOSE_PARENT * | @@ -103,6 +106,9 @@ private: void send_flush_op_work_queue(); void handle_flush_op_work_queue(int r); + void send_close_migration_parent(); + void handle_close_migration_parent(int r); + void send_close_parent(); void handle_close_parent(int r); diff --git a/src/librbd/image/RefreshParentRequest.cc b/src/librbd/image/RefreshParentRequest.cc index 5c55f2fa720ef..38aeb765c37e7 100644 --- a/src/librbd/image/RefreshParentRequest.cc +++ b/src/librbd/image/RefreshParentRequest.cc @@ -84,6 +84,7 @@ void RefreshParentRequest::apply() { assert(m_child_image_ctx.snap_lock.is_wlocked()); assert(m_child_image_ctx.parent_lock.is_wlocked()); std::swap(m_child_image_ctx.parent, m_parent_image_ctx); + std::swap(m_child_image_ctx.migration_parent, m_migration_parent_image_ctx); } template @@ -93,7 +94,7 @@ void RefreshParentRequest::finalize(Context *on_finish) { m_on_finish = on_finish; if (m_parent_image_ctx != nullptr) { - send_close_parent(); + send_close_migration_parent(); } else { send_complete(0); } @@ -158,11 +159,124 @@ Context *RefreshParentRequest::handle_open_parent(int *result) { // image already closed by open state machine delete m_parent_image_ctx; m_parent_image_ctx = nullptr; + return m_on_finish; + } + + if (m_migration_info.empty()) { + return m_on_finish; + } + + send_open_migration_parent(); + return nullptr; +} + +template +void RefreshParentRequest::send_open_migration_parent() { + assert(m_parent_image_ctx != nullptr); + assert(!m_migration_info.empty()); + + CephContext *cct = m_child_image_ctx.cct; + ParentSpec parent_spec; + { + RWLock::RLocker snap_locker(m_parent_image_ctx->snap_lock); + RWLock::RLocker parent_locker(m_parent_image_ctx->parent_lock); + + auto snap_id = m_migration_info.snap_map.begin()->first; + auto parent_info = m_parent_image_ctx->get_parent_info(snap_id); + if (parent_info == nullptr) { + lderr(cct) << "could not find parent info for snap id " << snap_id + << dendl; + } else { + parent_spec = parent_info->spec; + } + } + + if (parent_spec.pool_id == -1) { + send_complete(0); + return; + } + + ldout(cct, 10) << this << " " << __func__ << dendl; + + librados::Rados rados(m_child_image_ctx.md_ctx); + + librados::IoCtx parent_io_ctx; + int r = rados.ioctx_create2(parent_spec.pool_id, parent_io_ctx); + if (r < 0) { + lderr(cct) << "failed to access parent pool (id=" << parent_spec.pool_id + << "): " << cpp_strerror(r) << dendl; + save_result(&r); + send_close_parent(); + return; + } + + m_migration_parent_image_ctx = new I("", parent_spec.image_id, + parent_spec.snap_id, parent_io_ctx, + true); + + using klass = RefreshParentRequest; + Context *ctx = create_async_context_callback( + m_child_image_ctx, create_context_callback< + klass, &klass::handle_open_migration_parent, false>(this)); + OpenRequest *req = OpenRequest::create(m_migration_parent_image_ctx, 0, + ctx); + req->send(); +} + +template +Context *RefreshParentRequest::handle_open_migration_parent(int *result) { + CephContext *cct = m_child_image_ctx.cct; + ldout(cct, 10) << this << " " << __func__ << " r=" << *result << dendl; + + save_result(result); + if (*result < 0) { + lderr(cct) << "failed to open migration parent image: " + << cpp_strerror(*result) << dendl; + + // image already closed by open state machine + delete m_migration_parent_image_ctx; + m_migration_parent_image_ctx = nullptr; } return m_on_finish; } +template +void RefreshParentRequest::send_close_migration_parent() { + if (m_migration_parent_image_ctx == nullptr) { + send_close_parent(); + return; + } + + CephContext *cct = m_child_image_ctx.cct; + ldout(cct, 10) << this << " " << __func__ << dendl; + + using klass = RefreshParentRequest; + Context *ctx = create_async_context_callback( + m_child_image_ctx, create_context_callback< + klass, &klass::handle_close_migration_parent, false>(this)); + CloseRequest *req = CloseRequest::create(m_migration_parent_image_ctx, + ctx); + req->send(); +} + +template +Context *RefreshParentRequest::handle_close_migration_parent(int *result) { + CephContext *cct = m_child_image_ctx.cct; + ldout(cct, 10) << this << " " << __func__ << " r=" << *result << dendl; + + delete m_migration_parent_image_ctx; + m_migration_parent_image_ctx = nullptr; + + if (*result < 0) { + lderr(cct) << "failed to close migration parent image: " + << cpp_strerror(*result) << dendl; + } + + send_close_parent(); + return nullptr; +} + template void RefreshParentRequest::send_close_parent() { assert(m_parent_image_ctx != nullptr); diff --git a/src/librbd/image/RefreshParentRequest.h b/src/librbd/image/RefreshParentRequest.h index 39abc1b789c7d..2211da01373b6 100644 --- a/src/librbd/image/RefreshParentRequest.h +++ b/src/librbd/image/RefreshParentRequest.h @@ -41,19 +41,25 @@ private: * * | * | (open required) - * |----------------> OPEN_PARENT * * * * * * * * * * * * * * * - * | | * - * | v (on error) * - * \----------------> * - * | * - * | (close required) * - * |-----------------> CLOSE_PARENT * - * | | * - * | v * - * | RESET_EXISTENCE * - * | | * - * | v * - * \-----------------> < * * * * + * |----------------> OPEN_PARENT * * * * * * * * * * * * * * * * * * * * * + * | | * + * | v * + * | OPEN_MIGRATION_PARENT * * * * * * * * * * * * * * * + * | | (skip if not * * + * | v needed) * * + * \----------------> * * + * | (skip if not * * + * | (close required) needed) * * + * |-----------------> CLOSE_MIGRATION_PARENT * * + * | | * * + * | v * * + * | CLOSE_PARENT <* * * * * * * + * | | (on error) * + * | v * + * | RESET_EXISTENCE * + * | | * + * | v * + * \-----------------> < * * * * * * * * * * * * @endverbatim */ @@ -67,6 +73,7 @@ private: Context *m_on_finish; ImageCtxT *m_parent_image_ctx; + ImageCtxT *m_migration_parent_image_ctx = nullptr; uint64_t m_parent_snap_id; int m_error_result; @@ -84,6 +91,12 @@ private: void send_open_parent(); Context *handle_open_parent(int *result); + void send_open_migration_parent(); + Context *handle_open_migration_parent(int *result); + + void send_close_migration_parent(); + Context *handle_close_migration_parent(int *result); + void send_close_parent(); Context *handle_close_parent(int *result); diff --git a/src/librbd/io/CopyupRequest.cc b/src/librbd/io/CopyupRequest.cc index a09f36a4d0991..3addb8f2c1ed4 100644 --- a/src/librbd/io/CopyupRequest.cc +++ b/src/librbd/io/CopyupRequest.cc @@ -234,7 +234,7 @@ void CopyupRequest::send() if (is_deep_copy()) { bool flatten = is_copyup_required() ? true : m_ictx->migration_info.flatten; auto req = deep_copy::ObjectCopyRequest::create( - m_ictx->parent, m_ictx->parent->parent /* TODO */, m_ictx, + m_ictx->parent, m_ictx->migration_parent, m_ictx, m_ictx->migration_info.snap_map, m_object_no, flatten, util::create_context_callback(this)); ldout(m_ictx->cct, 20) << "deep copy object req " << req diff --git a/src/librbd/operation/MigrateRequest.cc b/src/librbd/operation/MigrateRequest.cc index 5d51f33ca6098..d736a8668b89b 100644 --- a/src/librbd/operation/MigrateRequest.cc +++ b/src/librbd/operation/MigrateRequest.cc @@ -127,7 +127,7 @@ private: assert(image_ctx.parent != nullptr); auto req = deep_copy::ObjectCopyRequest::create( - image_ctx.parent, image_ctx.parent->parent /* TODO */, &image_ctx, + image_ctx.parent, image_ctx.migration_parent, &image_ctx, image_ctx.migration_info.snap_map, m_object_no, image_ctx.migration_info.flatten, ctx);