done
testlog "TEST: disable mirror while daemon is stopped"
-# TODO: workaround for the daemon to ack the deletion, to remove when
-# image_map cleanup is fixed
-for i in ${image2} ${image4}; do
- wait_for_image_present ${CLUSTER1} ${POOL} ${i} 'deleted'
-done
stop_mirrors ${CLUSTER1}
stop_mirrors ${CLUSTER2}
set_pool_mirror_mode ${CLUSTER2} ${POOL} 'image'
test_image_present ${CLUSTER1} ${POOL} ${image} 'present'
fi
start_mirrors ${CLUSTER1}
-start_mirrors ${CLUSTER2} # TODO: remove start/stop of cluster2 deamons when
- # image_map cleanup at startup is resolved
-wait_for_image_in_omap ${CLUSTER1} ${POOL}
-wait_for_image_in_omap ${CLUSTER2} ${POOL}
-stop_mirrors ${CLUSTER2}
wait_for_image_present ${CLUSTER1} ${POOL} ${image} 'deleted'
set_pool_mirror_mode ${CLUSTER2} ${POOL} 'pool'
enable_journaling ${CLUSTER2} ${POOL} ${image}
done
testlog "TEST: disable mirror while daemon is stopped"
-# TODO: workaround for the daemon to ack the deletion, to remove when
-# image_map cleanup is fixed
-for i in ${image2} ${image4}; do
- wait_for_image_present ${CLUSTER1} ${POOL} ${i} 'deleted'
-done
stop_mirrors ${CLUSTER1}
stop_mirrors ${CLUSTER2}
disable_mirror ${CLUSTER2} ${POOL} ${image}
test_image_present ${CLUSTER1} ${POOL} ${image} 'present'
fi
start_mirrors ${CLUSTER1}
-start_mirrors ${CLUSTER2} # TODO: remove start/stop of cluster2 deamons when
- # image_map cleanup at startup is resolved
-wait_for_image_in_omap ${CLUSTER1} ${POOL}
-wait_for_image_in_omap ${CLUSTER2} ${POOL}
-stop_mirrors ${CLUSTER2}
wait_for_image_present ${CLUSTER1} ${POOL} ${image} 'deleted'
enable_mirror ${CLUSTER2} ${POOL} ${image}
wait_for_image_present ${CLUSTER1} ${POOL} ${image} 'present'
#include "include/rbd_types.h"
#include "cls/rbd/cls_rbd_client.h"
+#include "UpdateRequest.h"
#include "LoadRequest.h"
#define dout_context g_ceph_context
static const uint32_t MAX_RETURN = 1024;
using librbd::util::create_rados_callback;
+using librbd::util::create_context_callback;
template<typename I>
LoadRequest<I>::LoadRequest(librados::IoCtx &ioctx,
return;
}
- finish(0);
+ mirror_image_list();
+}
+
+template<typename I>
+void LoadRequest<I>::mirror_image_list() {
+ dout(20) << dendl;
+
+ librados::ObjectReadOperation op;
+ librbd::cls_client::mirror_image_list_start(&op, m_start_after, MAX_RETURN);
+
+ m_out_bl.clear();
+ librados::AioCompletion *aio_comp = create_rados_callback<
+ LoadRequest<I>,
+ &LoadRequest<I>::handle_mirror_image_list>(this);
+ int r = m_ioctx.aio_operate(RBD_MIRRORING, aio_comp, &op, &m_out_bl);
+ ceph_assert(r == 0);
+ aio_comp->release();
+}
+
+template<typename I>
+void LoadRequest<I>::handle_mirror_image_list(int r) {
+ dout(20) << ": r=" << r << dendl;
+
+ std::map<std::string, std::string> ids;
+ if (r == 0) {
+ auto it = m_out_bl.cbegin();
+ r = librbd::cls_client::mirror_image_list_finish(&it, &ids);
+ }
+
+ if (r < 0 && r != -ENOENT) {
+ derr << "failed to list mirrored images: " << cpp_strerror(r) << dendl;
+ finish(r);
+ return;
+ }
+
+ for (auto &id : ids) {
+ m_global_image_ids.emplace(id.second);
+ }
+
+ if (ids.size() == MAX_RETURN) {
+ m_start_after = ids.rbegin()->first;
+ mirror_image_list();
+ return;
+ }
+
+ cleanup_image_map();
+}
+
+template<typename I>
+void LoadRequest<I>::cleanup_image_map() {
+ dout(20) << dendl;
+
+ std::set<std::string> map_removals;
+
+ auto it = m_image_mapping->begin();
+ while (it != m_image_mapping->end()) {
+ if (m_global_image_ids.count(it->first) > 0) {
+ ++it;
+ continue;
+ }
+ map_removals.emplace(it->first);
+ it = m_image_mapping->erase(it);
+ }
+
+ if (map_removals.size() == 0) {
+ finish(0);
+ return;
+ }
+
+ auto ctx = create_context_callback<
+ LoadRequest<I>,
+ &LoadRequest<I>::finish>(this);
+ image_map::UpdateRequest<I> *req = image_map::UpdateRequest<I>::create(
+ m_ioctx, {}, std::move(map_removals), ctx);
+ req->send();
}
template<typename I>
* IMAGE_MAP_LIST. . . . . . .
* |
* v
+ * MIRROR_IMAGE_LIST
+ * |
+ * v
+ * CLEANUP_IMAGE_MAP
+ * |
+ * v
* <finish>
*
* @endverbatim
std::map<std::string, cls::rbd::MirrorImageMap> *m_image_mapping;
Context *m_on_finish;
+ std::set<std::string> m_global_image_ids;
+
bufferlist m_out_bl;
std::string m_start_after;
void image_map_list();
void handle_image_map_list(int r);
+ void mirror_image_list();
+ void handle_mirror_image_list(int r);
+
+ void cleanup_image_map();
+
void finish(int r);
};