]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: open migration image parent and store its pointer in ImageCtx
authorMykola Golub <mgolub@suse.com>
Sun, 27 May 2018 12:06:59 +0000 (15:06 +0300)
committerJason Dillaman <dillaman@redhat.com>
Tue, 14 Aug 2018 22:29:45 +0000 (18:29 -0400)
Use the pointer in copyup and migrate requests, when deep copying an
object.

Signed-off-by: Mykola Golub <mgolub@suse.com>
src/librbd/ImageCtx.h
src/librbd/image/CloseRequest.cc
src/librbd/image/CloseRequest.h
src/librbd/image/RefreshParentRequest.cc
src/librbd/image/RefreshParentRequest.h
src/librbd/io/CopyupRequest.cc
src/librbd/operation/MigrateRequest.cc

index b2558ea471e203c14950ae0f110e738e1f725fa3..259227870e3ab20c303a736e828f90dd0ec49252 100644 (file)
@@ -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;
index de0928ee1819eccfc0f0c13079a1846f3b4ed23a..f4c0eb8a4d6a32e4786420a3ab8a9813323e9525 100644 (file)
@@ -266,6 +266,36 @@ template <typename I>
 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();
 }
 
index fd101beedb331c2fb679068d01da4f17a7334b81..44916f781f13ec60fe02d4a47bb922bfd86d99d4 100644 (file)
@@ -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);
 
index 5c55f2fa720ef27a7277a515870e45773e5b275c..38aeb765c37e72895212464d4aae1d292c1fee44 100644 (file)
@@ -84,6 +84,7 @@ void RefreshParentRequest<I>::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 <typename I>
@@ -93,7 +94,7 @@ void RefreshParentRequest<I>::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<I>::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 <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);
index 39abc1b789c7d239e9b1b8051f94f85694a2b420..2211da01373b627ef4b8037951c4dd56c21593da 100644 (file)
@@ -41,19 +41,25 @@ private:
    * <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
    */
@@ -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);
 
index a09f36a4d09916468f7faf59726176e421eabe74..3addb8f2c1ed4d3d05bbdcf3c3cc1bcc20c3fa0f 100644 (file)
@@ -234,7 +234,7 @@ void CopyupRequest<I>::send()
   if (is_deep_copy()) {
     bool flatten = is_copyup_required() ? true : m_ictx->migration_info.flatten;
     auto req = deep_copy::ObjectCopyRequest<I>::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
index 5d51f33ca609854543c43055611deccfe6adcda4..d736a8668b89b5972dcd06c0a32c1068fbd31fa6 100644 (file)
@@ -127,7 +127,7 @@ private:
       assert(image_ctx.parent != nullptr);
 
       auto req = deep_copy::ObjectCopyRequest<I>::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);