bool m_do_resync;
};
-TEST_F(TestMockImageReplayerBootstrapRequest, NonPrimaryRemoteSyncingState) {
+TEST_F(TestMockImageReplayerBootstrapRequest, LocalDemotedRemoteSyncingState) {
create_local_image();
InSequence seq;
expect_get_remote_mirror_info(mock_get_mirror_info_request,
{cls::rbd::MIRROR_IMAGE_MODE_JOURNAL, "uuid",
cls::rbd::MIRROR_IMAGE_STATE_ENABLED},
- librbd::mirror::PROMOTION_STATE_NON_PRIMARY, 0);
+ librbd::mirror::PROMOTION_STATE_PRIMARY, 0);
- // switch the state to replaying
+ // open the local image
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
+ mock_local_image_ctx.journal = &mock_journal;
+ MockOpenLocalImageRequest mock_open_local_image_request;
+ expect_open_local_image(mock_open_local_image_request, m_local_io_ctx,
+ mock_local_image_ctx.id, &mock_local_image_ctx, 0);
+ expect_is_resync_requested(mock_journal, false, 0);
+
+ expect_journal_get_tag_tid(mock_journal, 345);
+ expect_journal_get_tag_data(mock_journal, {librbd::Journal<>::ORPHAN_MIRROR_UUID,
+ "remote mirror uuid", true, 4, 1});
+
+ // update client state
librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
mock_local_image_ctx.id};
mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
::journal::MockJournaler mock_journaler;
expect_journaler_update_client(mock_journaler, client_data, 0);
+ // lookup remote image tag class
+ client_data = {librbd::journal::ImageClientMeta{123}};
+ cls::journal::Client client;
+ encode(client_data, client.data);
+ expect_journaler_get_client(mock_journaler,
+ librbd::Journal<>::IMAGE_CLIENT_ID,
+ client, 0);
+
+ // remote demotion / promotion event
+ Tags tags = {
+ {2, 123, encode_tag_data({librbd::Journal<>::LOCAL_MIRROR_UUID,
+ librbd::Journal<>::LOCAL_MIRROR_UUID,
+ true, 1, 99})},
+ {3, 123, encode_tag_data({librbd::Journal<>::ORPHAN_MIRROR_UUID,
+ librbd::Journal<>::LOCAL_MIRROR_UUID,
+ true, 2, 1})},
+ {4, 123, encode_tag_data({librbd::Journal<>::LOCAL_MIRROR_UUID,
+ librbd::Journal<>::ORPHAN_MIRROR_UUID,
+ true, 3, 1})},
+ {5, 123, encode_tag_data({librbd::Journal<>::ORPHAN_MIRROR_UUID,
+ librbd::Journal<>::LOCAL_MIRROR_UUID,
+ true, 4, 1})},
+ {6, 123, encode_tag_data({librbd::Journal<>::LOCAL_MIRROR_UUID,
+ librbd::Journal<>::ORPHAN_MIRROR_UUID,
+ true, 5, 1})},
+ {7, 123, encode_tag_data({librbd::Journal<>::ORPHAN_MIRROR_UUID,
+ librbd::Journal<>::LOCAL_MIRROR_UUID,
+ true, 6, 1})},
+ {8, 123, encode_tag_data({librbd::Journal<>::LOCAL_MIRROR_UUID,
+ librbd::Journal<>::ORPHAN_MIRROR_UUID,
+ true, 7, 1})}
+ };
+ expect_journaler_get_tags(mock_journaler, 123, tags, 0);
+
MockCloseImageRequest mock_close_image_request;
expect_close_image(mock_close_image_request, mock_remote_image_ctx, 0);
"local mirror uuid", "remote mirror uuid", &client_state,
&mirror_peer_client_meta, &ctx);
request->send();
- ASSERT_EQ(-EREMOTEIO, ctx.wait());
+ ASSERT_EQ(0, ctx.wait());
}
TEST_F(TestMockImageReplayerBootstrapRequest, NonPrimaryRemoteNotTagOwner) {
return;
}
- if (m_promotion_state != librbd::mirror::PROMOTION_STATE_PRIMARY) {
- if (m_local_image_id.empty()) {
- // no local image and remote isn't primary -- don't sync it
- dout(5) << "remote image is not primary -- not syncing"
- << dendl;
- m_ret_val = -EREMOTEIO;
- close_remote_image();
- return;
- } else if (m_client_meta->state !=
- librbd::journal::MIRROR_PEER_STATE_REPLAYING) {
- // ensure we attempt to re-sync to remote if it's re-promoted
- dout(5) << "remote image is not primary -- sync interrupted"
- << dendl;
- m_ret_val = -EREMOTEIO;
- update_client_state();
- return;
- }
+ if (m_promotion_state != librbd::mirror::PROMOTION_STATE_PRIMARY &&
+ m_local_image_id.empty()) {
+ // no local image and remote isn't primary -- don't sync it
+ dout(5) << "remote image is not primary -- not syncing"
+ << dendl;
+ m_ret_val = -EREMOTEIO;
+ close_remote_image();
+ return;
}
if (!m_client_meta->image_id.empty()) {
open_local_image();
}
-template <typename I>
-void BootstrapRequest<I>::update_client_state() {
- dout(15) << dendl;
- update_progress("UPDATE_CLIENT_STATE");
-
- librbd::journal::MirrorPeerClientMeta client_meta(*m_client_meta);
- client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
-
- librbd::journal::ClientData client_data(client_meta);
- bufferlist data_bl;
- encode(client_data, data_bl);
-
- Context *ctx = create_context_callback<
- BootstrapRequest<I>, &BootstrapRequest<I>::handle_update_client_state>(
- this);
- m_journaler->update_client(data_bl, ctx);
-}
-
-template <typename I>
-void BootstrapRequest<I>::handle_update_client_state(int r) {
- dout(15) << "r=" << r << dendl;
- if (r < 0) {
- derr << "failed to update client: " << cpp_strerror(r) << dendl;
- } else {
- m_client_meta->state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
- }
-
- close_remote_image();
-}
-
template <typename I>
void BootstrapRequest<I>::open_local_image() {
dout(15) << "local_image_id=" << m_local_image_id << dendl;
return;
}
+ update_client_state();
+}
+
+template <typename I>
+void BootstrapRequest<I>::update_client_state() {
+ if (m_client_meta->state != librbd::journal::MIRROR_PEER_STATE_SYNCING ||
+ m_local_tag_data.mirror_uuid == m_remote_mirror_uuid) {
+ get_remote_tag_class();
+ return;
+ }
+
+ // our local image is not primary, is flagged as syncing on the remote side,
+ // but is no longer tied to the remote -- this implies we were forced
+ // promoted and then demoted at some point
+ dout(15) << dendl;
+ update_progress("UPDATE_CLIENT_STATE");
+
+ librbd::journal::MirrorPeerClientMeta client_meta(*m_client_meta);
+ client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
+
+ librbd::journal::ClientData client_data(client_meta);
+ bufferlist data_bl;
+ encode(client_data, data_bl);
+
+ Context *ctx = create_context_callback<
+ BootstrapRequest<I>, &BootstrapRequest<I>::handle_update_client_state>(
+ this);
+ m_journaler->update_client(data_bl, ctx);
+}
+
+template <typename I>
+void BootstrapRequest<I>::handle_update_client_state(int r) {
+ dout(15) << "r=" << r << dendl;
+ if (r < 0) {
+ derr << "failed to update client: " << cpp_strerror(r) << dendl;
+ m_ret_val = r;
+ close_local_image();
+ return;
+ }
+
+ m_client_meta->state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
get_remote_tag_class();
}
* | v * * |
* | (remote image primary) * * |
* \----> OPEN_LOCAL_IMAGE * * * * * * * * * * * * * * |
- * | | . * * |
- * | | . (image doesn't exist) * * |
- * | | . . > UNREGISTER_CLIENT * * * * * * * |
- * | | | * * |
- * | | v * * |
- * | | REGISTER_CLIENT * * * * * * * * |
- * | | | * * |
- * | | \-----------------------*---*---/
- * | | * *
- * | v (skip if not needed) * *
- * | GET_REMOTE_TAG_CLASS * * * * * * *
- * | | * * *
- * | v (skip if not needed) * * *
- * | GET_REMOTE_TAGS * * * * * * * * *
- * | | * * *
- * | v (skip if not needed) v * *
- * | IMAGE_SYNC * * * > CLOSE_LOCAL_IMAGE * *
- * | | | * *
- * | \-----------------\ /-----/ * *
- * | | * *
- * | | * *
- * | (skip if not needed) | * *
- * \----> UPDATE_CLIENT_STATE *|* * * * * * * * * * *
- * | | * *
- * /-----------/----------------/ * *
+ * | . * * |
+ * | . (image doesn't exist) * * |
+ * | . . > UNREGISTER_CLIENT * * * * * * * |
+ * | | * * |
+ * | v * * |
+ * | REGISTER_CLIENT * * * * * * * * |
+ * | | * * |
+ * | \-----------------------*---*---/
+ * | * *
+ * v (skip if not needed) * *
+ * UPDATE_CLIENT_STATE * *
+ * | * *
+ * v (skip if not needed) * *
+ * GET_REMOTE_TAG_CLASS * * * * * * *
+ * | * * *
+ * v (skip if not needed) * * *
+ * GET_REMOTE_TAGS * * * * * * * * *
+ * | * * *
+ * v (skip if not needed) v * *
+ * IMAGE_SYNC * * * > CLOSE_LOCAL_IMAGE * *
+ * | | * *
+ * \-----------------\ /-----/ * *
+ * | * *
+ * | * *
+ * /----------------------------/ * *
* | * *
* v * *
* CLOSE_REMOTE_IMAGE < * * * * * * * * * * * * * * * * *
void get_remote_mirror_info();
void handle_get_remote_mirror_info(int r);
- void update_client_state();
- void handle_update_client_state(int r);
-
void open_local_image();
void handle_open_local_image(int r);
void update_client_image();
void handle_update_client_image(int r);
+ void update_client_state();
+ void handle_update_client_state(int r);
+
void get_remote_tag_class();
void handle_get_remote_tag_class(int r);