void CloseRequest<I>::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 <typename I>
+void CloseRequest<I>::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<I>, &CloseRequest<I>::handle_close_migration_parent>(this)));
+}
+
+template <typename I>
+void CloseRequest<I>::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();
}
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 <typename I>
m_on_finish = on_finish;
if (m_parent_image_ctx != nullptr) {
- send_close_parent();
+ send_close_migration_parent();
} else {
send_complete(0);
}
// 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 <typename I>
+void RefreshParentRequest<I>::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<I>;
+ Context *ctx = create_async_context_callback(
+ m_child_image_ctx, create_context_callback<
+ klass, &klass::handle_open_migration_parent, false>(this));
+ OpenRequest<I> *req = OpenRequest<I>::create(m_migration_parent_image_ctx, 0,
+ ctx);
+ req->send();
+}
+
+template <typename I>
+Context *RefreshParentRequest<I>::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 <typename I>
+void RefreshParentRequest<I>::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<I>;
+ Context *ctx = create_async_context_callback(
+ m_child_image_ctx, create_context_callback<
+ klass, &klass::handle_close_migration_parent, false>(this));
+ CloseRequest<I> *req = CloseRequest<I>::create(m_migration_parent_image_ctx,
+ ctx);
+ req->send();
+}
+
+template <typename I>
+Context *RefreshParentRequest<I>::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 <typename I>
void RefreshParentRequest<I>::send_close_parent() {
assert(m_parent_image_ctx != nullptr);
* <start>
* |
* | (open required)
- * |----------------> OPEN_PARENT * * * * * * * * * * * * * * *
- * | | *
- * | v (on error) *
- * \----------------> <apply> *
- * | *
- * | (close required) *
- * |-----------------> CLOSE_PARENT *
- * | | *
- * | v *
- * | RESET_EXISTENCE *
- * | | *
- * | v *
- * \-----------------> <finish> < * * * *
+ * |----------------> OPEN_PARENT * * * * * * * * * * * * * * * * * * * * *
+ * | | *
+ * | v *
+ * | OPEN_MIGRATION_PARENT * * * * * * * * * * * * * * *
+ * | | (skip if not * *
+ * | v needed) * *
+ * \----------------> <apply> * *
+ * | (skip if not * *
+ * | (close required) needed) * *
+ * |-----------------> CLOSE_MIGRATION_PARENT * *
+ * | | * *
+ * | v * *
+ * | CLOSE_PARENT <* * * * * * *
+ * | | (on error) *
+ * | v *
+ * | RESET_EXISTENCE *
+ * | | *
+ * | v *
+ * \-----------------> <finish> < * * * * * * * * * *
*
* @endverbatim
*/
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;
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);