]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/librbd/image/RemoveRequest.cc
update sources to v12.1.0
[ceph.git] / ceph / src / librbd / image / RemoveRequest.cc
index 629fc7c799344abb3a86bbfd8a026677b4601a48..5782702d78f926640edc68b57e7088764e181e16 100644 (file)
@@ -17,7 +17,7 @@
 #define dout_subsys ceph_subsys_rbd
 #undef dout_prefix
 #define dout_prefix *_dout << "librbd::image::RemoveRequest: " << this << " " \
-                           << __func__ << " "
+                           << __func__ << ": "
 
 namespace librbd {
 namespace image {
@@ -62,20 +62,21 @@ void RemoveRequest<I>::open_image() {
 }
 
 template<typename I>
-Context *RemoveRequest<I>::handle_open_image(int *result) {
-  ldout(m_cct, 20) << ": r=" << *result << dendl;
+void RemoveRequest<I>::handle_open_image(int r) {
+  ldout(m_cct, 20) << "r=" << r << dendl;
 
-  if (*result < 0) {
+  if (r < 0) {
     m_image_ctx->destroy();
     m_image_ctx = nullptr;
 
-    if (*result != -ENOENT) {
-      lderr(m_cct) << "error opening image: " << cpp_strerror(*result) << dendl;
-      return m_on_finish;
+    if (r != -ENOENT) {
+      lderr(m_cct) << "error opening image: " << cpp_strerror(r) << dendl;
+      finish(r);
+      return;
     }
 
     remove_image();
-    return nullptr;
+    return;
   }
 
   m_image_id = m_image_ctx->id;
@@ -85,7 +86,6 @@ Context *RemoveRequest<I>::handle_open_image(int *result) {
   m_unknown_format = false;
 
   check_exclusive_lock();
-  return nullptr;
 }
 
 template<typename I>
@@ -107,7 +107,8 @@ void RemoveRequest<I>::acquire_exclusive_lock() {
   if (m_force) {
     Context *ctx = create_context_callback<
       klass, &klass::handle_exclusive_lock_force>(this);
-    m_image_ctx->exclusive_lock->shut_down(ctx);
+    m_exclusive_lock = m_image_ctx->exclusive_lock;
+    m_exclusive_lock->shut_down(ctx);
   } else {
     Context *ctx = create_context_callback<
       klass, &klass::handle_exclusive_lock>(this);
@@ -117,33 +118,34 @@ void RemoveRequest<I>::acquire_exclusive_lock() {
 }
 
 template<typename I>
-Context *RemoveRequest<I>::handle_exclusive_lock_force(int *result) {
-  ldout(m_cct, 20) << ": r=" << *result << dendl;
+void RemoveRequest<I>::handle_exclusive_lock_force(int r) {
+  ldout(m_cct, 20) << "r=" << r << dendl;
 
-  if (*result < 0) {
+  delete m_exclusive_lock;
+  m_exclusive_lock = nullptr;
+
+  if (r < 0) {
     lderr(m_cct) << "error shutting down exclusive lock: "
-                 << cpp_strerror(*result) << dendl;
-    send_close_image(*result);
-    return nullptr;
+                 << cpp_strerror(r) << dendl;
+    send_close_image(r);
+    return;
   }
 
   assert(m_image_ctx->exclusive_lock == nullptr);
   validate_image_removal();
-  return nullptr;
 }
 
 template<typename I>
-Context *RemoveRequest<I>::handle_exclusive_lock(int *result) {
-  ldout(m_cct, 20) << ": r=" << *result << dendl;
+void RemoveRequest<I>::handle_exclusive_lock(int r) {
+  ldout(m_cct, 20) << "r=" << r << dendl;
 
-  if ((*result < 0) || !m_image_ctx->exclusive_lock->is_lock_owner()) {
+  if (r < 0 || !m_image_ctx->exclusive_lock->is_lock_owner()) {
     lderr(m_cct) << "cannot obtain exclusive lock - not removing" << dendl;
     send_close_image(-EBUSY);
-    return nullptr;
+    return;
   }
 
   validate_image_removal();
-  return nullptr;
 }
 
 template<typename I>
@@ -163,11 +165,11 @@ void RemoveRequest<I>::check_image_snaps() {
     return;
   }
 
-  check_image_watchers();
+  list_image_watchers();
 }
 
 template<typename I>
-void RemoveRequest<I>::check_image_watchers() {
+void RemoveRequest<I>::list_image_watchers() {
   ldout(m_cct, 20) << dendl;
 
   librados::ObjectReadOperation op;
@@ -175,7 +177,7 @@ void RemoveRequest<I>::check_image_watchers() {
 
   using klass = RemoveRequest<I>;
   librados::AioCompletion *rados_completion =
-    create_rados_callback<klass, &klass::handle_check_image_watchers>(this);
+    create_rados_callback<klass, &klass::handle_list_image_watchers>(this);
 
   int r = m_image_ctx->md_ctx.aio_operate(m_header_oid, rados_completion,
                                           &op, &m_out_bl);
@@ -184,74 +186,109 @@ void RemoveRequest<I>::check_image_watchers() {
 }
 
 template<typename I>
-void RemoveRequest<I>::filter_out_mirror_watchers() {
-  if (m_watchers.empty()) {
-    return;
-  }
+void RemoveRequest<I>::handle_list_image_watchers(int r) {
+  ldout(m_cct, 20) << "r=" << r << dendl;
 
-  if ((m_image_ctx->features & RBD_FEATURE_JOURNALING) == 0) {
-    return;
+  if (r == 0 && m_ret_val < 0) {
+    r = m_ret_val;
   }
-
-  cls::rbd::MirrorImage mirror_image;
-  int r = cls_client::mirror_image_get(&m_image_ctx->md_ctx, m_image_ctx->id,
-                                       &mirror_image);
   if (r < 0) {
-    if (r != -ENOENT) {
-      lderr(m_cct) << "failed to retrieve mirroring state: "
-                       << cpp_strerror(r) << dendl;
-    }
+    lderr(m_cct) << "error listing image watchers: " << cpp_strerror(r)
+                 << dendl;
+    send_close_image(r);
     return;
   }
 
-  if (mirror_image.state != cls::rbd::MIRROR_IMAGE_STATE_ENABLED) {
+  get_mirror_image();
+}
+
+template<typename I>
+void RemoveRequest<I>::get_mirror_image() {
+  ldout(m_cct, 20) << dendl;
+  if ((m_watchers.empty()) ||
+      ((m_image_ctx->features & RBD_FEATURE_JOURNALING) == 0)) {
+    check_image_watchers();
     return;
   }
 
-  std::list<obj_watch_t> mirror_watchers;
-  r = m_image_ctx->md_ctx.list_watchers(RBD_MIRRORING, &mirror_watchers);
-  if (r < 0) {
-    if (r != -ENOENT) {
-      lderr(m_cct) << "error listing mirroring watchers: "
-                       << cpp_strerror(r) << dendl;
-    }
+  librados::ObjectReadOperation op;
+  cls_client::mirror_image_get_start(&op, m_image_id);
+
+  using klass = RemoveRequest<I>;
+  librados::AioCompletion *comp =
+    create_rados_callback<klass, &klass::handle_get_mirror_image>(this);
+  m_out_bl.clear();
+  int r = m_image_ctx->md_ctx.aio_operate(RBD_MIRRORING, comp, &op, &m_out_bl);
+  assert(r == 0);
+  comp->release();
+}
+
+template<typename I>
+void RemoveRequest<I>::handle_get_mirror_image(int r) {
+  ldout(m_cct, 20) << "r=" << r << dendl;
+
+  if (r == -ENOENT || r == -EOPNOTSUPP) {
+    check_image_watchers();
     return;
+  } else if (r < 0) {
+    ldout(m_cct, 5) << "error retrieving mirror image: " << cpp_strerror(r)
+                    << dendl;
   }
-  for (auto &watcher : mirror_watchers) {
-    m_watchers.remove_if([watcher] (obj_watch_t &w) {
-        return (strncmp(w.addr, watcher.addr, sizeof(w.addr)) == 0);
-      });
-  }
+
+  list_mirror_watchers();
 }
 
 template<typename I>
-Context *RemoveRequest<I>::handle_check_image_watchers(int *result) {
-  ldout(m_cct, 20) << ": r=" << *result << dendl;
+void RemoveRequest<I>::list_mirror_watchers() {
+  ldout(m_cct, 20) << dendl;
 
-  if (*result < 0) {
-    lderr(m_cct) << "error listing image watchers: " << cpp_strerror(*result)
-                 << dendl;
-    send_close_image(*result);
-    return nullptr;
+  librados::ObjectReadOperation op;
+  op.list_watchers(&m_mirror_watchers, &m_ret_val);
+
+  using klass = RemoveRequest<I>;
+  librados::AioCompletion *rados_completion =
+    create_rados_callback<klass, &klass::handle_list_mirror_watchers>(this);
+  m_out_bl.clear();
+  int r = m_image_ctx->md_ctx.aio_operate(RBD_MIRRORING, rados_completion,
+                                          &op, &m_out_bl);
+  assert(r == 0);
+  rados_completion->release();
+}
+
+template<typename I>
+void RemoveRequest<I>::handle_list_mirror_watchers(int r) {
+  ldout(m_cct, 20) << "r=" << r << dendl;
+
+  if (r == 0 && m_ret_val < 0) {
+    r = m_ret_val;
+  }
+  if (r < 0 && r != -ENOENT) {
+    ldout(m_cct, 5) << "error listing mirror watchers: " << cpp_strerror(r)
+                    << dendl;
+  }
+
+  for (auto &watcher : m_mirror_watchers) {
+    m_watchers.remove_if([watcher] (obj_watch_t &w) {
+        return (strncmp(w.addr, watcher.addr, sizeof(w.addr)) == 0);
+      });
   }
 
-  // If an image is being bootstrapped by rbd-mirror, it implies
-  // that the rbd-mirror daemon currently has the image open.
-  // Permit removal if this is the case.
-  filter_out_mirror_watchers();
+  check_image_watchers();
+}
 
+template<typename I>
+void RemoveRequest<I>::check_image_watchers() {
   if (m_watchers.size() > 1) {
     lderr(m_cct) << "image has watchers - not removing" << dendl;
     send_close_image(-EBUSY);
-    return nullptr;
+    return;
   }
 
-  check_image_consistency_group();
-  return nullptr;
+  check_group();
 }
 
 template<typename I>
-void RemoveRequest<I>::check_image_consistency_group() {
+void RemoveRequest<I>::check_group() {
   ldout(m_cct, 20) << dendl;
 
   librados::ObjectReadOperation op;
@@ -259,7 +296,7 @@ void RemoveRequest<I>::check_image_consistency_group() {
 
   using klass = RemoveRequest<I>;
   librados::AioCompletion *rados_completion = create_rados_callback<
-    klass, &klass::handle_check_image_consistency_group>(this);
+    klass, &klass::handle_check_group>(this);
   m_out_bl.clear();
   int r = m_image_ctx->md_ctx.aio_operate(m_header_oid, rados_completion, &op,
                                           &m_out_bl);
@@ -268,32 +305,28 @@ void RemoveRequest<I>::check_image_consistency_group() {
 }
 
 template<typename I>
-Context *RemoveRequest<I>::handle_check_image_consistency_group(int *result) {
-  ldout(m_cct, 20) << ": r=" << *result << dendl;
-
-  if (*result < 0) {
-    lderr(m_cct) << "error fetching consistency group for image: "
-                 << cpp_strerror(*result) << dendl;
-    send_close_image(*result);
-    return nullptr;
-  }
+void RemoveRequest<I>::handle_check_group(int r) {
+  ldout(m_cct, 20) << "r=" << r << dendl;
 
   cls::rbd::GroupSpec s;
-  bufferlist::iterator it = m_out_bl.begin();
-  *result = librbd::cls_client::image_get_group_finish(&it, &s);
-  if (*result < 0) {
-    send_close_image(*result);
-    return nullptr;
+  if (r == 0) {
+    bufferlist::iterator it = m_out_bl.begin();
+    r = librbd::cls_client::image_get_group_finish(&it, &s);
+  }
+  if (r < 0 && r != -EOPNOTSUPP) {
+    lderr(m_cct) << "error fetching group for image: "
+                 << cpp_strerror(r) << dendl;
+    send_close_image(r);
+    return;
   }
+
   if (s.is_valid()) {
     lderr(m_cct) << "image is in a group - not removing" << dendl;
     send_close_image(-EMLINK);
-    return nullptr;
+    return;
   }
 
   trim_image();
-
-  return nullptr;
 }
 
 template<typename I>
@@ -312,21 +345,20 @@ void RemoveRequest<I>::trim_image() {
 }
 
 template<typename I>
-Context *RemoveRequest<I>::handle_trim_image(int *result) {
-  ldout(m_cct, 20) << ": r=" << *result << dendl;
+void RemoveRequest<I>::handle_trim_image(int r) {
+  ldout(m_cct, 20) << "r=" << r << dendl;
 
-  if (*result < 0) {
+  if (r < 0) {
     lderr(m_cct) << "warning: failed to remove some object(s): "
-                 << cpp_strerror(*result) << dendl;
+                 << cpp_strerror(r) << dendl;
   }
 
   if (m_old_format) {
-    send_close_image(*result);
-    return nullptr;
+    send_close_image(r);
+    return;
   }
 
   remove_child();
-  return nullptr;
 }
 
 template<typename I>
@@ -349,21 +381,20 @@ void RemoveRequest<I>::remove_child() {
 }
 
 template<typename I>
-Context *RemoveRequest<I>::handle_remove_child(int *result) {
-  ldout(m_cct, 20) << ": r=" << *result << dendl;
+void RemoveRequest<I>::handle_remove_child(int r) {
+  ldout(m_cct, 20) << "r=" << r << dendl;
 
-  if (*result == -ENOENT) {
-    *result = 0;
-  } else if (*result < 0) {
+  if (r == -ENOENT) {
+    r = 0;
+  } else if (r < 0) {
     lderr(m_cct) << "error removing child from children list: "
-                 << cpp_strerror(*result) << dendl;
-    send_close_image(*result);
-    return nullptr;
+                 << cpp_strerror(r) << dendl;
+    send_close_image(r);
+    return;
   }
 
 
   send_disable_mirror();
-  return nullptr;
 }
 
 template<typename I>
@@ -380,18 +411,17 @@ void RemoveRequest<I>::send_disable_mirror() {
 }
 
 template<typename I>
-Context *RemoveRequest<I>::handle_disable_mirror(int *result) {
-  ldout(m_cct, 20) << ": r=" << *result << dendl;
+void RemoveRequest<I>::handle_disable_mirror(int r) {
+  ldout(m_cct, 20) << "r=" << r << dendl;
 
-  if (*result == -EOPNOTSUPP) {
-    *result = 0;
-  } else if (*result < 0) {
+  if (r == -EOPNOTSUPP) {
+    r = 0;
+  } else if (r < 0) {
     lderr(m_cct) << "error disabling image mirroring: "
-                 << cpp_strerror(*result) << dendl;
+                 << cpp_strerror(r) << dendl;
   }
 
-  send_close_image(*result);
-  return nullptr;
+  send_close_image(r);
 }
 
 template<typename I>
@@ -407,23 +437,23 @@ void RemoveRequest<I>::send_close_image(int r) {
 }
 
 template<typename I>
-Context *RemoveRequest<I>::handle_send_close_image(int *result) {
-  ldout(m_cct, 20) << ": r=" << *result << dendl;
+void RemoveRequest<I>::handle_send_close_image(int r) {
+  ldout(m_cct, 20) << "r=" << r << dendl;
 
-  if (*result < 0) {
+  if (r < 0) {
     lderr(m_cct) << "error encountered while closing image: "
-                 << cpp_strerror(*result) << dendl;
+                 << cpp_strerror(r) << dendl;
   }
 
   m_image_ctx->destroy();
   m_image_ctx = nullptr;
   if (m_ret_val < 0) {
-    *result = m_ret_val;
-    return m_on_finish;
+    r = m_ret_val;
+    finish(r);
+    return;
   }
 
   remove_header();
-  return nullptr;
 }
 
 template<typename I>
@@ -439,16 +469,15 @@ void RemoveRequest<I>::remove_header() {
 }
 
 template<typename I>
-Context *RemoveRequest<I>::handle_remove_header(int *result) {
-  ldout(m_cct, 20) << ": r=" << *result << dendl;
+void RemoveRequest<I>::handle_remove_header(int r) {
+  ldout(m_cct, 20) << "r=" << r << dendl;
 
-  if ((*result < 0) && (*result != -ENOENT)) {
-    lderr(m_cct) << "error removing header: " << cpp_strerror(*result) << dendl;
-    m_ret_val = *result;
+  if (r < 0 && r != -ENOENT) {
+    lderr(m_cct) << "error removing header: " << cpp_strerror(r) << dendl;
+    m_ret_val = r;
   }
 
   remove_image();
-  return nullptr;
 }
 
 template<typename I>
@@ -468,16 +497,16 @@ void RemoveRequest<I>::remove_header_v2() {
 }
 
 template<typename I>
-Context *RemoveRequest<I>::handle_remove_header_v2(int *result) {
-  ldout(m_cct, 20) << ": r=" << *result << dendl;
+void RemoveRequest<I>::handle_remove_header_v2(int r) {
+  ldout(m_cct, 20) << "r=" << r << dendl;
 
-  if ((*result < 0) && (*result != -ENOENT)) {
-    lderr(m_cct) << "error removing header: " << cpp_strerror(*result) << dendl;
-    return m_on_finish;
+  if (r < 0 && r != -ENOENT) {
+    lderr(m_cct) << "error removing header: " << cpp_strerror(r) << dendl;
+    finish(r);
+    return;
   }
 
   send_journal_remove();
-  return nullptr;
 }
 
 template<typename I>
@@ -494,19 +523,19 @@ void RemoveRequest<I>::send_journal_remove() {
 }
 
 template<typename I>
-Context *RemoveRequest<I>::handle_journal_remove(int *result) {
-  ldout(m_cct, 20) << ": r=" << *result << dendl;
+void RemoveRequest<I>::handle_journal_remove(int r) {
+  ldout(m_cct, 20) << "r=" << r << dendl;
 
-  if (*result < 0 && *result != -ENOENT) {
-    lderr(m_cct) << "failed to remove image journal: " << cpp_strerror(*result)
+  if (r < 0 && r != -ENOENT) {
+    lderr(m_cct) << "failed to remove image journal: " << cpp_strerror(r)
                  << dendl;
-    return m_on_finish;
+    finish(r);
+    return;
   } else {
-    *result = 0;
+    r = 0;
   }
 
   send_object_map_remove();
-  return nullptr;
 }
 
 template<typename I>
@@ -525,19 +554,19 @@ void RemoveRequest<I>::send_object_map_remove() {
 }
 
 template<typename I>
-Context *RemoveRequest<I>::handle_object_map_remove(int *result) {
-  ldout(m_cct, 20) << ": r=" << *result << dendl;
+void RemoveRequest<I>::handle_object_map_remove(int r) {
+  ldout(m_cct, 20) << "r=" << r << dendl;
 
-  if (*result < 0 && *result != -ENOENT) {
-    lderr(m_cct) << "failed to remove image journal: " << cpp_strerror(*result)
+  if (r < 0 && r != -ENOENT) {
+    lderr(m_cct) << "failed to remove image journal: " << cpp_strerror(r)
                  << dendl;
-    return m_on_finish;
+    finish(r);
+    return;
   } else {
-    *result = 0;
+    r = 0;
   }
 
   mirror_image_remove();
-  return nullptr;
 }
 
 template<typename I>
@@ -556,27 +585,24 @@ void RemoveRequest<I>::mirror_image_remove() {
 }
 
 template<typename I>
-Context *RemoveRequest<I>::handle_mirror_image_remove(int *result) {
-  ldout(m_cct, 20) << ": r=" << *result << dendl;
+void RemoveRequest<I>::handle_mirror_image_remove(int r) {
+  ldout(m_cct, 20) << "r=" << r << dendl;
 
-  if (*result < 0 && *result != -ENOENT && *result != -EOPNOTSUPP) {
+  if (r < 0 && r != -ENOENT && r != -EOPNOTSUPP) {
     lderr(m_cct) << "failed to remove mirror image state: "
-                 << cpp_strerror(*result) << dendl;
-    return m_on_finish;
-  } else {
-    *result = 0;
+                 << cpp_strerror(r) << dendl;
+    finish(r);
+    return;
   }
 
   if (m_from_trash_remove) {
     // both the id object and the directory entry have been removed in
     // a previous call to trash_move.
-
-    *result = 0;
-    return m_on_finish;
+    finish(0);
+    return;
   }
 
   remove_id_object();
-  return nullptr;
 }
 
 template<typename I>
@@ -604,11 +630,11 @@ void RemoveRequest<I>::remove_v1_image() {
 
 template<typename I>
 void RemoveRequest<I>::handle_remove_v1_image(int r) {
-  ldout(m_cct, 20) << "r=" << r << dendl;
+  ldout(m_cct, 20) << "r=" << r << dendl;
 
   m_old_format = (r == 0);
-  if ((r == 0) || ((r < 0) && !m_unknown_format)) {
-    if ((r < 0) && (r != -ENOENT)) {
+  if (r == 0 || (r < 0 && !m_unknown_format)) {
+    if (r < 0 && r != -ENOENT) {
       lderr(m_cct) << "error removing image from v1 directory: "
                    << cpp_strerror(r) << dendl;
     }
@@ -656,25 +682,26 @@ void RemoveRequest<I>::dir_get_image_id() {
 }
 
 template<typename I>
-Context *RemoveRequest<I>::handle_dir_get_image_id(int *result) {
-  ldout(m_cct, 20) << ": r=" << *result << dendl;
+void RemoveRequest<I>::handle_dir_get_image_id(int r) {
+  ldout(m_cct, 20) << "r=" << r << dendl;
 
-  if ((*result < 0) && (*result != -ENOENT)) {
-    lderr(m_cct) << "error fetching image id: " << cpp_strerror(*result)
+  if (r < 0 && r != -ENOENT) {
+    lderr(m_cct) << "error fetching image id: " << cpp_strerror(r)
                  << dendl;
-    return m_on_finish;
+    finish(r);
+    return;
   }
 
-  if (!*result) {
+  if (r == 0) {
     bufferlist::iterator iter = m_out_bl.begin();
-    *result = librbd::cls_client::dir_get_id_finish(&iter, &m_image_id);
-    if (*result < 0) {
-      return m_on_finish;
+    r = librbd::cls_client::dir_get_id_finish(&iter, &m_image_id);
+    if (r < 0) {
+      finish(r);
+      return;
     }
   }
 
   remove_header_v2();
-  return nullptr;
 }
 
 template<typename I>
@@ -694,25 +721,26 @@ void RemoveRequest<I>::dir_get_image_name() {
 }
 
 template<typename I>
-Context *RemoveRequest<I>::handle_dir_get_image_name(int *result) {
-  ldout(m_cct, 20) << ": r=" << *result << dendl;
+void RemoveRequest<I>::handle_dir_get_image_name(int r) {
+  ldout(m_cct, 20) << "r=" << r << dendl;
 
-  if ((*result < 0) && (*result != -ENOENT)) {
-    lderr(m_cct) << "error fetching image name: " << cpp_strerror(*result)
+  if (r < 0 && r != -ENOENT) {
+    lderr(m_cct) << "error fetching image name: " << cpp_strerror(r)
                  << dendl;
-    return m_on_finish;
+    finish(r);
+    return;
   }
 
-  if (!*result) {
+  if (r == 0) {
     bufferlist::iterator iter = m_out_bl.begin();
-    *result = librbd::cls_client::dir_get_name_finish(&iter, &m_image_name);
-    if (*result < 0) {
-      return m_on_finish;
+    r = librbd::cls_client::dir_get_name_finish(&iter, &m_image_name);
+    if (r < 0) {
+      finish(r);
+      return;
     }
   }
 
   remove_header_v2();
-  return nullptr;
 }
 
 template<typename I>
@@ -728,17 +756,17 @@ void RemoveRequest<I>::remove_id_object() {
 }
 
 template<typename I>
-Context *RemoveRequest<I>::handle_remove_id_object(int *result) {
-  ldout(m_cct, 20) << ": r=" << *result << dendl;
+void RemoveRequest<I>::handle_remove_id_object(int r) {
+  ldout(m_cct, 20) << "r=" << r << dendl;
 
-  if ((*result < 0) && (*result != -ENOENT)) {
-    lderr(m_cct) << "error removing id object: " << cpp_strerror(*result)
+  if (r < 0 && r != -ENOENT) {
+    lderr(m_cct) << "error removing id object: " << cpp_strerror(r)
                  << dendl;
-    return m_on_finish;
+    finish(r);
+    return;
   }
 
   dir_remove_image();
-  return nullptr;
 }
 
 template<typename I>
@@ -757,15 +785,23 @@ void RemoveRequest<I>::dir_remove_image() {
 }
 
 template<typename I>
-Context *RemoveRequest<I>::handle_dir_remove_image(int *result) {
-  ldout(m_cct, 20) << ":r =" << *result << dendl;
+void RemoveRequest<I>::handle_dir_remove_image(int r) {
+  ldout(m_cct, 20) << "r=" << r << dendl;
 
-  if ((*result < 0) && (*result != -ENOENT)) {
+  if (r < 0 && r != -ENOENT) {
     lderr(m_cct) << "error removing image from v2 directory: "
-                 << cpp_strerror(*result) << dendl;
+                 << cpp_strerror(r) << dendl;
   }
 
-  return m_on_finish;
+  finish(r);
+}
+
+template<typename I>
+void RemoveRequest<I>::finish(int r) {
+  ldout(m_cct, 20) << "r=" << r << dendl;
+
+  m_on_finish->complete(r);
+  delete this;
 }
 
 } // namespace image