#define dout_subsys ceph_subsys_rbd
#undef dout_prefix
#define dout_prefix *_dout << "librbd::image::RemoveRequest: " << this << " " \
- << __func__ << " "
+ << __func__ << ": "
namespace librbd {
namespace 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;
m_unknown_format = false;
check_exclusive_lock();
- return nullptr;
}
template<typename I>
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);
}
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>
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;
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);
}
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;
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);
}
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>
}
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>
}
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>
}
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>
}
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>
}
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>
}
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>
}
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>
}
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>
}
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>
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;
}
}
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>
}
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>
}
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>
}
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