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>
-void RemoveRequest<I>::handle_check_image_watchers(int r) {
+void RemoveRequest<I>::list_mirror_watchers() {
+ ldout(m_cct, 20) << dendl;
+
+ 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) {
- lderr(m_cct) << "error listing image watchers: " << cpp_strerror(r)
- << dendl;
- send_close_image(r);
- return;
+ 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);