rbd-mirror: support resync request for snapshot-based mirroring

When a local image has the resync requested image-meta property, the
snapshot replayer will stop and initiate the resync request.

Signed-off-by: Jason Dillaman <dillaman@redhat.com>
This commit is contained in:
Jason Dillaman 2020-02-22 15:23:10 -05:00
parent fc073c54a1
commit 86d39fb9ee
4 changed files with 273 additions and 50 deletions

View File

@ -6,6 +6,7 @@
#include "librbd/deep_copy/SnapshotCopyRequest.h"
#include "librbd/mirror/snapshot/CreateNonPrimaryRequest.h"
#include "librbd/mirror/snapshot/GetImageStateRequest.h"
#include "librbd/mirror/snapshot/ImageMeta.h"
#include "librbd/mirror/snapshot/UnlinkPeerRequest.h"
#include "tools/rbd_mirror/Threads.h"
#include "tools/rbd_mirror/image_replayer/CloseImageRequest.h"
@ -173,6 +174,13 @@ struct GetImageStateRequest<MockTestImageCtx> {
MOCK_METHOD0(send, void());
};
template <>
struct ImageMeta<MockTestImageCtx> {
MOCK_METHOD1(load, void(Context*));
bool resync_requested = false;
};
template <>
struct UnlinkPeerRequest<MockTestImageCtx> {
uint64_t snap_id;
@ -296,15 +304,21 @@ struct ApplyImageStateRequest<librbd::MockTestImageCtx> {
template<>
struct StateBuilder<librbd::MockTestImageCtx> {
StateBuilder(librbd::MockTestImageCtx& local_image_ctx,
librbd::MockTestImageCtx& remote_image_ctx)
librbd::MockTestImageCtx& remote_image_ctx,
librbd::mirror::snapshot::ImageMeta<librbd::MockTestImageCtx>&
local_image_meta)
: local_image_ctx(&local_image_ctx),
remote_image_ctx(&remote_image_ctx) {
remote_image_ctx(&remote_image_ctx),
local_image_meta(&local_image_meta) {
}
librbd::MockTestImageCtx* local_image_ctx;
librbd::MockTestImageCtx* remote_image_ctx;
std::string remote_mirror_uuid = "remote mirror uuid";
librbd::mirror::snapshot::ImageMeta<librbd::MockTestImageCtx>*
local_image_meta = nullptr;
};
ApplyImageStateRequest<librbd::MockTestImageCtx>* ApplyImageStateRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
@ -341,6 +355,7 @@ public:
typedef librbd::deep_copy::SnapshotCopyRequest<librbd::MockTestImageCtx> MockSnapshotCopyRequest;
typedef librbd::mirror::snapshot::CreateNonPrimaryRequest<librbd::MockTestImageCtx> MockCreateNonPrimaryRequest;
typedef librbd::mirror::snapshot::GetImageStateRequest<librbd::MockTestImageCtx> MockGetImageStateRequest;
typedef librbd::mirror::snapshot::ImageMeta<librbd::MockTestImageCtx> MockImageMeta;
typedef librbd::mirror::snapshot::UnlinkPeerRequest<librbd::MockTestImageCtx> MockUnlinkPeerRequest;
void SetUp() override {
@ -399,6 +414,15 @@ public:
})));
}
void expect_load_image_meta(MockImageMeta& mock_image_meta,
bool resync_requested, int r) {
EXPECT_CALL(mock_image_meta, load(_))
.WillOnce(Invoke([this, &mock_image_meta, resync_requested, r](Context* ctx) {
mock_image_meta.resync_requested = resync_requested;
m_threads->work_queue->queue(ctx, r);
}));
}
void expect_is_refresh_required(librbd::MockTestImageCtx& mock_image_ctx,
bool is_required) {
EXPECT_CALL(*mock_image_ctx.state, is_refresh_required())
@ -556,11 +580,13 @@ public:
librbd::MockTestImageCtx& mock_local_image_ctx,
librbd::MockTestImageCtx& mock_remote_image_ctx,
MockReplayerListener& mock_replayer_listener,
MockImageMeta& mock_image_meta,
librbd::UpdateWatchCtx** update_watch_ctx) {
expect_register_update_watcher(mock_local_image_ctx, update_watch_ctx, 123,
0);
expect_register_update_watcher(mock_remote_image_ctx, update_watch_ctx, 234,
0);
expect_load_image_meta(mock_image_meta, false, 0);
expect_is_refresh_required(mock_local_image_ctx, false);
expect_is_refresh_required(mock_remote_image_ctx, false);
@ -609,8 +635,10 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, InitShutDown) {
InSequence seq;
MockImageMeta mock_image_meta;
MockStateBuilder mock_state_builder(mock_local_image_ctx,
mock_remote_image_ctx);
mock_remote_image_ctx,
mock_image_meta);
MockReplayer mock_replayer{&mock_threads, "local mirror uuid",
&m_pool_meta_cache, &mock_state_builder,
&mock_replayer_listener};
@ -623,6 +651,7 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, InitShutDown) {
mock_local_image_ctx,
mock_remote_image_ctx,
mock_replayer_listener,
mock_image_meta,
&update_watch_ctx));
ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer, mock_threads,
mock_local_image_ctx,
@ -659,8 +688,10 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, SyncSnapshot) {
InSequence seq;
MockImageMeta mock_image_meta;
MockStateBuilder mock_state_builder(mock_local_image_ctx,
mock_remote_image_ctx);
mock_remote_image_ctx,
mock_image_meta);
MockReplayer mock_replayer{&mock_threads, "local mirror uuid",
&m_pool_meta_cache, &mock_state_builder,
&mock_replayer_listener};
@ -677,6 +708,7 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, SyncSnapshot) {
0);
// sync snap1
expect_load_image_meta(mock_image_meta, false, 0);
expect_is_refresh_required(mock_local_image_ctx, false);
expect_is_refresh_required(mock_remote_image_ctx, false);
MockSnapshotCopyRequest mock_snapshot_copy_request;
@ -698,6 +730,7 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, SyncSnapshot) {
expect_notify_update(mock_local_image_ctx);
// sync snap4
expect_load_image_meta(mock_image_meta, false, 0);
expect_is_refresh_required(mock_local_image_ctx, true);
expect_refresh(
mock_local_image_ctx, {
@ -724,6 +757,7 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, SyncSnapshot) {
0);
// idle
expect_load_image_meta(mock_image_meta, false, 0);
expect_is_refresh_required(mock_local_image_ctx, true);
expect_refresh(
mock_local_image_ctx, {
@ -764,8 +798,10 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, InterruptedSync) {
InSequence seq;
MockImageMeta mock_image_meta;
MockStateBuilder mock_state_builder(mock_local_image_ctx,
mock_remote_image_ctx);
mock_remote_image_ctx,
mock_image_meta);
MockReplayer mock_replayer{&mock_threads, "local mirror uuid",
&m_pool_meta_cache, &mock_state_builder,
&mock_replayer_listener};
@ -778,6 +814,7 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, InterruptedSync) {
mock_local_image_ctx,
mock_remote_image_ctx,
mock_replayer_listener,
mock_image_meta,
&update_watch_ctx));
// inject a incomplete sync snapshot
@ -793,6 +830,7 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, InterruptedSync) {
0, {}, 0, 0, {}}}};
// re-sync snap1
expect_load_image_meta(mock_image_meta, false, 0);
expect_is_refresh_required(mock_local_image_ctx, false);
expect_is_refresh_required(mock_remote_image_ctx, false);
MockGetImageStateRequest mock_get_image_state_request;
@ -808,6 +846,7 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, InterruptedSync) {
expect_notify_update(mock_local_image_ctx);
// idle
expect_load_image_meta(mock_image_meta, false, 0);
expect_is_refresh_required(mock_local_image_ctx, true);
expect_refresh(
mock_local_image_ctx, {
@ -841,8 +880,10 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, RemoteImageDemoted) {
InSequence seq;
MockImageMeta mock_image_meta;
MockStateBuilder mock_state_builder(mock_local_image_ctx,
mock_remote_image_ctx);
mock_remote_image_ctx,
mock_image_meta);
MockReplayer mock_replayer{&mock_threads, "local mirror uuid",
&m_pool_meta_cache, &mock_state_builder,
&mock_replayer_listener};
@ -855,6 +896,7 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, RemoteImageDemoted) {
mock_local_image_ctx,
mock_remote_image_ctx,
mock_replayer_listener,
mock_image_meta,
&update_watch_ctx));
// inject a demotion snapshot
@ -865,6 +907,7 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, RemoteImageDemoted) {
0, {}, 0, 0, {}}}};
// sync snap1
expect_load_image_meta(mock_image_meta, false, 0);
expect_is_refresh_required(mock_local_image_ctx, false);
expect_is_refresh_required(mock_remote_image_ctx, false);
MockSnapshotCopyRequest mock_snapshot_copy_request;
@ -886,6 +929,7 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, RemoteImageDemoted) {
expect_notify_update(mock_local_image_ctx);
// idle
expect_load_image_meta(mock_image_meta, false, 0);
expect_is_refresh_required(mock_local_image_ctx, true);
expect_refresh(
mock_local_image_ctx, {
@ -920,8 +964,10 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, LocalImagePromoted) {
InSequence seq;
MockImageMeta mock_image_meta;
MockStateBuilder mock_state_builder(mock_local_image_ctx,
mock_remote_image_ctx);
mock_remote_image_ctx,
mock_image_meta);
MockReplayer mock_replayer{&mock_threads, "local mirror uuid",
&m_pool_meta_cache, &mock_state_builder,
&mock_replayer_listener};
@ -934,6 +980,7 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, LocalImagePromoted) {
mock_local_image_ctx,
mock_remote_image_ctx,
mock_replayer_listener,
mock_image_meta,
&update_watch_ctx));
// inject a promotion snapshot
@ -944,6 +991,7 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, LocalImagePromoted) {
0, {}, 0, 0, {}}}};
// idle
expect_load_image_meta(mock_image_meta, false, 0);
expect_is_refresh_required(mock_local_image_ctx, false);
expect_is_refresh_required(mock_remote_image_ctx, false);
@ -959,6 +1007,52 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, LocalImagePromoted) {
mock_remote_image_ctx));
}
TEST_F(TestMockImageReplayerSnapshotReplayer, ResyncRequested) {
librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx};
librbd::MockTestImageCtx mock_remote_image_ctx{*m_remote_image_ctx};
MockThreads mock_threads(m_threads);
expect_work_queue_repeatedly(mock_threads);
MockReplayerListener mock_replayer_listener;
expect_notification(mock_threads, mock_replayer_listener);
InSequence seq;
MockImageMeta mock_image_meta;
MockStateBuilder mock_state_builder(mock_local_image_ctx,
mock_remote_image_ctx,
mock_image_meta);
MockReplayer mock_replayer{&mock_threads, "local mirror uuid",
&m_pool_meta_cache, &mock_state_builder,
&mock_replayer_listener};
m_pool_meta_cache.set_remote_pool_meta(
m_remote_io_ctx.get_id(),
{"remote mirror uuid", "remote mirror peer uuid"});
librbd::UpdateWatchCtx* update_watch_ctx = nullptr;
ASSERT_EQ(0, init_entry_replayer(mock_replayer, mock_threads,
mock_local_image_ctx,
mock_remote_image_ctx,
mock_replayer_listener,
mock_image_meta,
&update_watch_ctx));
// idle
expect_load_image_meta(mock_image_meta, true, 0);
// wake-up replayer
update_watch_ctx->handle_notify();
// wait for sync to complete and expect replay complete
ASSERT_EQ(0, wait_for_notification(1));
ASSERT_FALSE(mock_replayer.is_replaying());
ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer, mock_threads,
mock_local_image_ctx,
mock_remote_image_ctx));
}
TEST_F(TestMockImageReplayerSnapshotReplayer, RegisterLocalUpdateWatcherError) {
librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx};
librbd::MockTestImageCtx mock_remote_image_ctx{*m_remote_image_ctx};
@ -968,8 +1062,10 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, RegisterLocalUpdateWatcherError) {
InSequence seq;
MockImageMeta mock_image_meta;
MockStateBuilder mock_state_builder(mock_local_image_ctx,
mock_remote_image_ctx);
mock_remote_image_ctx,
mock_image_meta);
MockReplayerListener mock_replayer_listener;
MockReplayer mock_replayer{&mock_threads, "local mirror uuid",
&m_pool_meta_cache, &mock_state_builder,
@ -998,8 +1094,10 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, RegisterRemoteUpdateWatcherError)
InSequence seq;
MockImageMeta mock_image_meta;
MockStateBuilder mock_state_builder(mock_local_image_ctx,
mock_remote_image_ctx);
mock_remote_image_ctx,
mock_image_meta);
MockReplayerListener mock_replayer_listener;
MockReplayer mock_replayer{&mock_threads, "local mirror uuid",
&m_pool_meta_cache, &mock_state_builder,
@ -1035,8 +1133,10 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, UnregisterRemoteUpdateWatcherError
InSequence seq;
MockImageMeta mock_image_meta;
MockStateBuilder mock_state_builder(mock_local_image_ctx,
mock_remote_image_ctx);
mock_remote_image_ctx,
mock_image_meta);
MockReplayer mock_replayer{&mock_threads, "local mirror uuid",
&m_pool_meta_cache, &mock_state_builder,
&mock_replayer_listener};
@ -1049,6 +1149,7 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, UnregisterRemoteUpdateWatcherError
mock_local_image_ctx,
mock_remote_image_ctx,
mock_replayer_listener,
mock_image_meta,
&update_watch_ctx));
@ -1073,8 +1174,10 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, UnregisterLocalUpdateWatcherError)
InSequence seq;
MockImageMeta mock_image_meta;
MockStateBuilder mock_state_builder(mock_local_image_ctx,
mock_remote_image_ctx);
mock_remote_image_ctx,
mock_image_meta);
MockReplayer mock_replayer{&mock_threads, "local mirror uuid",
&m_pool_meta_cache, &mock_state_builder,
&mock_replayer_listener};
@ -1087,6 +1190,7 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, UnregisterLocalUpdateWatcherError)
mock_local_image_ctx,
mock_remote_image_ctx,
mock_replayer_listener,
mock_image_meta,
&update_watch_ctx));
@ -1099,6 +1203,53 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, UnregisterLocalUpdateWatcherError)
ASSERT_EQ(-EINVAL, shutdown_ctx.wait());
}
TEST_F(TestMockImageReplayerSnapshotReplayer, LoadImageMetaError) {
librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx};
librbd::MockTestImageCtx mock_remote_image_ctx{*m_remote_image_ctx};
MockThreads mock_threads(m_threads);
expect_work_queue_repeatedly(mock_threads);
MockReplayerListener mock_replayer_listener;
expect_notification(mock_threads, mock_replayer_listener);
InSequence seq;
MockImageMeta mock_image_meta;
MockStateBuilder mock_state_builder(mock_local_image_ctx,
mock_remote_image_ctx,
mock_image_meta);
MockReplayer mock_replayer{&mock_threads, "local mirror uuid",
&m_pool_meta_cache, &mock_state_builder,
&mock_replayer_listener};
m_pool_meta_cache.set_remote_pool_meta(
m_remote_io_ctx.get_id(),
{"remote mirror uuid", "remote mirror peer uuid"});
librbd::UpdateWatchCtx* update_watch_ctx = nullptr;
ASSERT_EQ(0, init_entry_replayer(mock_replayer, mock_threads,
mock_local_image_ctx,
mock_remote_image_ctx,
mock_replayer_listener,
mock_image_meta,
&update_watch_ctx));
// sync
expect_load_image_meta(mock_image_meta, false, -EINVAL);
// wake-up replayer
update_watch_ctx->handle_notify();
// wait for sync to complete and expect replay complete
ASSERT_EQ(0, wait_for_notification(1));
ASSERT_FALSE(mock_replayer.is_replaying());
ASSERT_EQ(-EINVAL, mock_replayer.get_error_code());
ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer, mock_threads,
mock_local_image_ctx,
mock_remote_image_ctx));
}
TEST_F(TestMockImageReplayerSnapshotReplayer, RefreshLocalImageError) {
librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx};
librbd::MockTestImageCtx mock_remote_image_ctx{*m_remote_image_ctx};
@ -1111,8 +1262,10 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, RefreshLocalImageError) {
InSequence seq;
MockImageMeta mock_image_meta;
MockStateBuilder mock_state_builder(mock_local_image_ctx,
mock_remote_image_ctx);
mock_remote_image_ctx,
mock_image_meta);
MockReplayer mock_replayer{&mock_threads, "local mirror uuid",
&m_pool_meta_cache, &mock_state_builder,
&mock_replayer_listener};
@ -1125,9 +1278,11 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, RefreshLocalImageError) {
mock_local_image_ctx,
mock_remote_image_ctx,
mock_replayer_listener,
mock_image_meta,
&update_watch_ctx));
// sync
expect_load_image_meta(mock_image_meta, false, 0);
expect_is_refresh_required(mock_local_image_ctx, true);
expect_refresh(mock_local_image_ctx, {}, -EINVAL);
@ -1156,8 +1311,10 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, RefreshRemoteImageError) {
InSequence seq;
MockImageMeta mock_image_meta;
MockStateBuilder mock_state_builder(mock_local_image_ctx,
mock_remote_image_ctx);
mock_remote_image_ctx,
mock_image_meta);
MockReplayer mock_replayer{&mock_threads, "local mirror uuid",
&m_pool_meta_cache, &mock_state_builder,
&mock_replayer_listener};
@ -1170,9 +1327,11 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, RefreshRemoteImageError) {
mock_local_image_ctx,
mock_remote_image_ctx,
mock_replayer_listener,
mock_image_meta,
&update_watch_ctx));
// sync
expect_load_image_meta(mock_image_meta, false, 0);
expect_is_refresh_required(mock_local_image_ctx, false);
expect_is_refresh_required(mock_remote_image_ctx, true);
expect_refresh(mock_remote_image_ctx, {}, -EINVAL);
@ -1202,8 +1361,10 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, CopySnapshotsError) {
InSequence seq;
MockImageMeta mock_image_meta;
MockStateBuilder mock_state_builder(mock_local_image_ctx,
mock_remote_image_ctx);
mock_remote_image_ctx,
mock_image_meta);
MockReplayer mock_replayer{&mock_threads, "local mirror uuid",
&m_pool_meta_cache, &mock_state_builder,
&mock_replayer_listener};
@ -1216,6 +1377,7 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, CopySnapshotsError) {
mock_local_image_ctx,
mock_remote_image_ctx,
mock_replayer_listener,
mock_image_meta,
&update_watch_ctx));
// inject snapshot
@ -1226,6 +1388,7 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, CopySnapshotsError) {
0, {}, 0, 0, {}}}};
// sync snap1
expect_load_image_meta(mock_image_meta, false, 0);
expect_is_refresh_required(mock_local_image_ctx, false);
expect_is_refresh_required(mock_remote_image_ctx, false);
MockSnapshotCopyRequest mock_snapshot_copy_request;
@ -1257,8 +1420,10 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, GetImageStateError) {
InSequence seq;
MockImageMeta mock_image_meta;
MockStateBuilder mock_state_builder(mock_local_image_ctx,
mock_remote_image_ctx);
mock_remote_image_ctx,
mock_image_meta);
MockReplayer mock_replayer{&mock_threads, "local mirror uuid",
&m_pool_meta_cache, &mock_state_builder,
&mock_replayer_listener};
@ -1271,6 +1436,7 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, GetImageStateError) {
mock_local_image_ctx,
mock_remote_image_ctx,
mock_replayer_listener,
mock_image_meta,
&update_watch_ctx));
// inject snapshot
@ -1281,6 +1447,7 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, GetImageStateError) {
0, {}, 0, 0, {}}}};
// sync snap1
expect_load_image_meta(mock_image_meta, false, 0);
expect_is_refresh_required(mock_local_image_ctx, false);
expect_is_refresh_required(mock_remote_image_ctx, false);
MockSnapshotCopyRequest mock_snapshot_copy_request;
@ -1314,8 +1481,10 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, CreateNonPrimarySnapshotError) {
InSequence seq;
MockImageMeta mock_image_meta;
MockStateBuilder mock_state_builder(mock_local_image_ctx,
mock_remote_image_ctx);
mock_remote_image_ctx,
mock_image_meta);
MockReplayer mock_replayer{&mock_threads, "local mirror uuid",
&m_pool_meta_cache, &mock_state_builder,
&mock_replayer_listener};
@ -1328,6 +1497,7 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, CreateNonPrimarySnapshotError) {
mock_local_image_ctx,
mock_remote_image_ctx,
mock_replayer_listener,
mock_image_meta,
&update_watch_ctx));
// inject snapshot
@ -1338,6 +1508,7 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, CreateNonPrimarySnapshotError) {
0, {}, 0, 0, {}}}};
// sync snap1
expect_load_image_meta(mock_image_meta, false, 0);
expect_is_refresh_required(mock_local_image_ctx, false);
expect_is_refresh_required(mock_remote_image_ctx, false);
MockSnapshotCopyRequest mock_snapshot_copy_request;
@ -1375,8 +1546,10 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, CopyImageError) {
InSequence seq;
MockImageMeta mock_image_meta;
MockStateBuilder mock_state_builder(mock_local_image_ctx,
mock_remote_image_ctx);
mock_remote_image_ctx,
mock_image_meta);
MockReplayer mock_replayer{&mock_threads, "local mirror uuid",
&m_pool_meta_cache, &mock_state_builder,
&mock_replayer_listener};
@ -1389,6 +1562,7 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, CopyImageError) {
mock_local_image_ctx,
mock_remote_image_ctx,
mock_replayer_listener,
mock_image_meta,
&update_watch_ctx));
// inject snapshot
@ -1399,6 +1573,7 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, CopyImageError) {
0, {}, 0, 0, {}}}};
// sync snap1
expect_load_image_meta(mock_image_meta, false, 0);
expect_is_refresh_required(mock_local_image_ctx, false);
expect_is_refresh_required(mock_remote_image_ctx, false);
MockSnapshotCopyRequest mock_snapshot_copy_request;
@ -1439,8 +1614,10 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, UpdateNonPrimarySnapshotError) {
InSequence seq;
MockImageMeta mock_image_meta;
MockStateBuilder mock_state_builder(mock_local_image_ctx,
mock_remote_image_ctx);
mock_remote_image_ctx,
mock_image_meta);
MockReplayer mock_replayer{&mock_threads, "local mirror uuid",
&m_pool_meta_cache, &mock_state_builder,
&mock_replayer_listener};
@ -1453,6 +1630,7 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, UpdateNonPrimarySnapshotError) {
mock_local_image_ctx,
mock_remote_image_ctx,
mock_replayer_listener,
mock_image_meta,
&update_watch_ctx));
// inject snapshot
@ -1463,6 +1641,7 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, UpdateNonPrimarySnapshotError) {
0, {}, 0, 0, {}}}};
// sync snap1
expect_load_image_meta(mock_image_meta, false, 0);
expect_is_refresh_required(mock_local_image_ctx, false);
expect_is_refresh_required(mock_remote_image_ctx, false);
MockSnapshotCopyRequest mock_snapshot_copy_request;
@ -1507,8 +1686,10 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, UnlinkPeerError) {
InSequence seq;
MockImageMeta mock_image_meta;
MockStateBuilder mock_state_builder(mock_local_image_ctx,
mock_remote_image_ctx);
mock_remote_image_ctx,
mock_image_meta);
MockReplayer mock_replayer{&mock_threads, "local mirror uuid",
&m_pool_meta_cache, &mock_state_builder,
&mock_replayer_listener};
@ -1521,6 +1702,7 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, UnlinkPeerError) {
mock_local_image_ctx,
mock_remote_image_ctx,
mock_replayer_listener,
mock_image_meta,
&update_watch_ctx));
// inject snapshot
@ -1540,6 +1722,7 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, UnlinkPeerError) {
0, {}, 0, 0, {}}}};
// sync snap2
expect_load_image_meta(mock_image_meta, false, 0);
expect_is_refresh_required(mock_local_image_ctx, false);
expect_is_refresh_required(mock_remote_image_ctx, false);
MockSnapshotCopyRequest mock_snapshot_copy_request;

View File

@ -122,9 +122,14 @@ public:
features |= RBD_FEATURE_EXCLUSIVE_LOCK | RBD_FEATURE_JOURNALING;
EXPECT_EQ(0, librbd::api::Mirror<>::mode_set(m_remote_ioctx,
RBD_MIRROR_MODE_POOL));
EXPECT_EQ(0, librbd::api::Mirror<>::mode_set(m_local_ioctx,
RBD_MIRROR_MODE_POOL));
} else {
EXPECT_EQ(0, librbd::api::Mirror<>::mode_set(m_remote_ioctx,
RBD_MIRROR_MODE_IMAGE));
EXPECT_EQ(0, librbd::api::Mirror<>::mode_set(m_local_ioctx,
RBD_MIRROR_MODE_IMAGE));
uuid_d uuid_gen;
uuid_gen.generate_random();
@ -139,6 +144,11 @@ public:
m_remote_ioctx.get_id(), {m_remote_mirror_uuid, remote_peer_uuid});
}
EXPECT_EQ(0, librbd::api::Mirror<>::uuid_get(m_remote_ioctx,
&m_remote_mirror_uuid));
EXPECT_EQ(0, librbd::api::Mirror<>::uuid_get(m_local_ioctx,
&m_local_mirror_uuid));
m_image_name = get_temp_image_name();
int order = 0;
EXPECT_EQ(0, librbd::create(m_remote_ioctx, m_image_name.c_str(), 1 << 22,
@ -212,6 +222,10 @@ public:
m_replayer->start(&cond);
ASSERT_EQ(0, cond.wait());
create_watch_ctx();
}
void create_watch_ctx() {
std::string oid;
if (MIRROR_IMAGE_MODE == cls::rbd::MIRROR_IMAGE_MODE_JOURNAL) {
oid = ::journal::Journaler::header_oid(m_remote_image_id);
@ -220,12 +234,9 @@ public:
}
ASSERT_EQ(0U, m_watch_handle);
create_watch_ctx(oid);
ASSERT_EQ(0, m_remote_ioctx.watch2(oid, &m_watch_handle, m_watch_ctx));
}
void create_watch_ctx(const std::string& oid) {
ASSERT_TRUE(m_watch_ctx == nullptr);
m_watch_ctx = new C_WatchCtx(this, oid);
ASSERT_EQ(0, m_remote_ioctx.watch2(oid, &m_watch_handle, m_watch_ctx));
}
void unwatch() {
@ -824,9 +835,8 @@ TEST_F(TestImageReplayerJournal, NextTag)
this->stop();
}
TEST_F(TestImageReplayerJournal, Resync)
TYPED_TEST(TestImageReplayer, Resync)
{
// TODO add support to snapshot-based mirroring
this->bootstrap();
librbd::ImageCtx *ictx;
@ -852,7 +862,7 @@ TEST_F(TestImageReplayerJournal, Resync)
this->close_image(ictx);
this->open_local_image(&ictx);
librbd::Journal<>::request_resync(ictx);
EXPECT_EQ(0, librbd::api::Mirror<>::image_resync(ictx));
this->close_image(ictx);
this->wait_for_stopped();
@ -874,10 +884,8 @@ TEST_F(TestImageReplayerJournal, Resync)
this->stop();
}
TEST_F(TestImageReplayerJournal, Resync_While_Stop)
TYPED_TEST(TestImageReplayer, Resync_While_Stop)
{
// TODO add support to snapshot-based mirroring
this->bootstrap();
this->start();
@ -908,7 +916,7 @@ TEST_F(TestImageReplayerJournal, Resync_While_Stop)
ASSERT_EQ(0, cond.wait());
this->open_local_image(&ictx);
librbd::Journal<>::request_resync(ictx);
EXPECT_EQ(0, librbd::api::Mirror<>::image_resync(ictx));
this->close_image(ictx);
C_SaferCond cond2;
@ -935,15 +943,13 @@ TEST_F(TestImageReplayerJournal, Resync_While_Stop)
this->stop();
}
TEST_F(TestImageReplayerJournal, Resync_StartInterrupted)
TYPED_TEST(TestImageReplayer, Resync_StartInterrupted)
{
// TODO add support to snapshot-based mirroring
this->bootstrap();
librbd::ImageCtx *ictx;
this->open_local_image(&ictx);
librbd::Journal<>::request_resync(ictx);
EXPECT_EQ(0, librbd::api::Mirror<>::image_resync(ictx));
this->close_image(ictx);
C_SaferCond cond;
@ -956,11 +962,7 @@ TEST_F(TestImageReplayerJournal, Resync_StartInterrupted)
this->m_replayer->start(&cond2);
ASSERT_EQ(0, cond2.wait());
ASSERT_EQ(0U, this->m_watch_handle);
std::string oid = ::journal::Journaler::header_oid(this->m_remote_image_id);
this->create_watch_ctx(oid);
ASSERT_EQ(0, this->m_remote_ioctx.watch2(oid, &this->m_watch_handle,
this->m_watch_ctx));
this->create_watch_ctx();
ASSERT_TRUE(this->m_replayer->is_replaying());

View File

@ -15,6 +15,7 @@
#include "librbd/deep_copy/SnapshotCopyRequest.h"
#include "librbd/mirror/snapshot/CreateNonPrimaryRequest.h"
#include "librbd/mirror/snapshot/GetImageStateRequest.h"
#include "librbd/mirror/snapshot/ImageMeta.h"
#include "librbd/mirror/snapshot/UnlinkPeerRequest.h"
#include "tools/rbd_mirror/PoolMetaCache.h"
#include "tools/rbd_mirror/Threads.h"
@ -274,6 +275,37 @@ bool Replayer<I>::get_replay_status(std::string* description,
return true;
}
template <typename I>
void Replayer<I>::load_local_image_meta() {
dout(10) << dendl;
ceph_assert(m_state_builder->local_image_meta != nullptr);
auto ctx = create_context_callback<
Replayer<I>, &Replayer<I>::handle_load_local_image_meta>(this);
m_state_builder->local_image_meta->load(ctx);
}
template <typename I>
void Replayer<I>::handle_load_local_image_meta(int r) {
dout(10) << "r=" << r << dendl;
if (r < 0 && r != -ENOENT) {
derr << "failed to load local image-meta: " << cpp_strerror(r) << dendl;
handle_replay_complete(r, "failed to load local image-meta");
return;
}
if (r >= 0 && m_state_builder->local_image_meta->resync_requested) {
m_resync_requested = true;
dout(10) << "local image resync requested" << dendl;
handle_replay_complete(0, "resync requested");
return;
}
refresh_local_image();
}
template <typename I>
void Replayer<I>::refresh_local_image() {
if (!m_state_builder->local_image_ctx->state->is_refresh_required()) {
@ -551,7 +583,7 @@ void Replayer<I>::scan_remote_mirror_snapshots(
dout(10) << "restarting snapshot scan due to remote update notification"
<< dendl;
refresh_local_image();
load_local_image_meta();
return;
}
@ -866,7 +898,7 @@ void Replayer<I>::unlink_peer() {
notify_status_updated();
}
refresh_local_image();
load_local_image_meta();
return;
}
@ -898,7 +930,7 @@ void Replayer<I>::handle_unlink_peer(int r) {
notify_status_updated();
}
refresh_local_image();
load_local_image_meta();
}
template <typename I>
@ -975,7 +1007,7 @@ void Replayer<I>::handle_register_remote_update_watcher(int r) {
notify_status_updated();
}
refresh_local_image();
load_local_image_meta();
}
template <typename I>
@ -1067,7 +1099,7 @@ void Replayer<I>::handle_image_update_notify() {
locker.unlock();
dout(15) << "restarting idle replayer" << dendl;
refresh_local_image();
load_local_image_meta();
}
}

View File

@ -73,9 +73,8 @@ public:
}
bool is_resync_requested() const override {
std::unique_lock locker(m_lock);
// TODO
return false;
std::unique_lock locker{m_lock};
return m_resync_requested;
}
int get_error_code() const override {
@ -100,8 +99,11 @@ private:
* v
* REGISTER_REMOTE_UPDATE_WATCHER
* |
* v (skip if not needed)
* REFRESH_LOCAL_IMAGE <------------------------------\
* v
* LOAD_LOCAL_IMAGE_META <----------------------------\
* | |
* v (skip if not needed) |
* REFRESH_LOCAL_IMAGE |
* | |
* v (skip if not needed) |
* REFRESH_REMOTE_IMAGE |
@ -189,6 +191,7 @@ private:
Context* m_on_init_shutdown = nullptr;
bool m_resync_requested = false;
int m_error_code = 0;
std::string m_error_description;
@ -215,6 +218,9 @@ private:
bool m_remote_image_updated = false;
bool m_updating_sync_point = false;
void load_local_image_meta();
void handle_load_local_image_meta(int r);
void refresh_local_image();
void handle_refresh_local_image(int r);