rbd-mirror: prune obsolete primary mirror snapshots after relocation

Previously, obsolete primary and demoted primary snapshots on the
secondary cluster were not cleaned up immediately after relocation.
Instead, old primary snapshots remained until a subsequent promote
operation triggered their cleanup, while old demoted primary snapshots
persisted until a later demote operation removed them.

Adding changes for proactive cleanup of obsolete primary and demoted
primary snapshots that are no longer required after relocation.

Also adding test coverage to validate the cleanup behavior.

Fixes: https://tracker.ceph.com/issues/76154

Signed-off-by: Miki Patel <miki.patel132@gmail.com>
This commit is contained in:
Miki Patel 2026-04-19 11:59:40 +05:30 committed by Super User
parent e98037a639
commit a10f58df8c
13 changed files with 312 additions and 115 deletions

View File

@ -274,6 +274,60 @@ wait_for_replaying_status_in_pool_dir ${CLUSTER1} ${POOL} ${image}
wait_for_status_in_pool_dir ${CLUSTER2} ${POOL} ${image} 'up+stopped'
compare_images ${CLUSTER1} ${CLUSTER2} ${POOL} ${POOL} ${image}
if [ "${RBD_MIRROR_MODE}" = "snapshot" ]; then
testlog "TEST: failover / failback loop with snapshot presence checks"
snap_id_1=""
demote_snap_id_1=""
snap_id_2=""
demote_snap_id_2=""
get_newest_complete_mirror_snapshot_id ${CLUSTER2} ${POOL} ${image} snap_id_2
for i in `seq 1 5`; do
demote_image ${CLUSTER2} ${POOL} ${image}
wait_for_image_replay_stopped ${CLUSTER1} ${POOL} ${image}
wait_for_status_in_pool_dir ${CLUSTER1} ${POOL} ${image} 'up+unknown'
wait_for_status_in_pool_dir ${CLUSTER2} ${POOL} ${image} 'up+unknown'
get_newest_complete_mirror_snapshot_id ${CLUSTER2} ${POOL} ${image} demote_snap_id_2
wait_for_non_primary_snap_present ${CLUSTER1} ${POOL} ${image} ${demote_snap_id_2}
wait_for_non_primary_snap_not_present ${CLUSTER1} ${POOL} ${image} ${snap_id_2}
promote_image ${CLUSTER1} ${POOL} ${image}
wait_for_image_replay_started ${CLUSTER2} ${POOL} ${image}
wait_for_status_in_pool_dir ${CLUSTER1} ${POOL} ${image} 'up+stopped'
wait_for_status_in_pool_dir ${CLUSTER2} ${POOL} ${image} 'up+replaying'
get_newest_complete_mirror_snapshot_id ${CLUSTER1} ${POOL} ${image} snap_id_1
wait_for_non_primary_snap_present ${CLUSTER2} ${POOL} ${image} ${snap_id_1}
wait_for_snap_not_present ${CLUSTER2} ${POOL} ${image} ${snap_id_2}
wait_for_snap_not_present ${CLUSTER2} ${POOL} ${image} ${demote_snap_id_2}
demote_image ${CLUSTER1} ${POOL} ${image}
wait_for_non_primary_snap_not_present ${CLUSTER1} ${POOL} ${image} ${demote_snap_id_2}
wait_for_image_replay_stopped ${CLUSTER2} ${POOL} ${image}
wait_for_status_in_pool_dir ${CLUSTER1} ${POOL} ${image} 'up+unknown'
wait_for_status_in_pool_dir ${CLUSTER2} ${POOL} ${image} 'up+unknown'
get_newest_complete_mirror_snapshot_id ${CLUSTER1} ${POOL} ${image} demote_snap_id_1
wait_for_non_primary_snap_present ${CLUSTER2} ${POOL} ${image} ${demote_snap_id_1}
wait_for_non_primary_snap_not_present ${CLUSTER2} ${POOL} ${image} ${snap_id_1}
promote_image ${CLUSTER2} ${POOL} ${image}
wait_for_image_replay_started ${CLUSTER1} ${POOL} ${image}
wait_for_status_in_pool_dir ${CLUSTER2} ${POOL} ${image} 'up+stopped'
wait_for_status_in_pool_dir ${CLUSTER1} ${POOL} ${image} 'up+replaying'
get_newest_complete_mirror_snapshot_id ${CLUSTER2} ${POOL} ${image} snap_id_2
wait_for_non_primary_snap_present ${CLUSTER1} ${POOL} ${image} ${snap_id_2}
wait_for_snap_not_present ${CLUSTER1} ${POOL} ${image} ${snap_id_1}
wait_for_snap_not_present ${CLUSTER1} ${POOL} ${image} ${demote_snap_id_1}
done
# expected snapshot in non-primary image: non-primary
SNAPS=$(get_snaps_json ${CLUSTER1} ${POOL} ${image})
jq -e 'length == 1' <<< ${SNAPS}
jq -e '.[0].namespace["type"] == "mirror" and .[0].namespace["state"] == "non-primary"' <<< ${SNAPS}
# expected snapshots in primary image: non-primary demoted, primary
SNAPS=$(get_snaps_json ${CLUSTER2} ${POOL} ${image})
jq -e 'length == 2' <<< ${SNAPS}
jq -e '.[0].namespace["type"] == "mirror" and .[0].namespace["state"] == "demoted" and (.[0]["name"] | startswith(".mirror.non_primary"))' <<< ${SNAPS}
jq -e '.[1].namespace["type"] == "mirror" and .[1].namespace["state"] == "primary"' <<< ${SNAPS}
fi
testlog "TEST: failover / failback loop"
for i in `seq 1 20`; do
demote_image ${CLUSTER2} ${POOL} ${image}

View File

@ -826,6 +826,43 @@ wait_for_non_primary_snap_present()
return 1
}
wait_for_snap_not_present()
{
local cluster=$1
local pool=$2
local image=$3
local snap_id=$4
local snap_count
local s
for s in 0.1 1 2 4 8 8 8 8 8 8 8 8 16 16 32 32; do
sleep ${s}
snap_count=$(rbd --cluster ${cluster} snap list --all ${pool}/${image} --format xml | \
xmlstarlet sel -t -v "count(//snapshots/snapshot[id='${snap_id}'])")
[ "${snap_count}" = "0" ] && return 0
done
return 1
}
wait_for_non_primary_snap_not_present()
{
local cluster=$1
local pool=$2
local image=$3
local primary_snap_id=$4
local snap_count
local s
for s in 0.1 1 2 4 8 8 8 8 8 8 8 8 16 16 32 32; do
sleep ${s}
snap_count=$(rbd --cluster ${cluster} snap list --all ${pool}/${image} --format xml | \
xmlstarlet sel -t -v "count(//snapshots/snapshot/namespace[primary_snap_id='${primary_snap_id}'])")
[ "${snap_count}" = "0" ] && return 0
done
return 1
}
wait_for_snapshot_sync_complete()
{
local local_cluster=$1

View File

@ -495,8 +495,8 @@ public:
}));
}
void expect_prune_non_primary_snapshot(librbd::MockTestImageCtx& mock_image_ctx,
uint64_t snap_id, int r) {
void expect_prune_mirror_snapshot(librbd::MockTestImageCtx& mock_image_ctx,
uint64_t snap_id, int r) {
EXPECT_CALL(mock_image_ctx, get_snap_info(snap_id))
.WillOnce(Invoke([&mock_image_ctx](uint64_t snap_id) -> librbd::SnapInfo* {
auto it = mock_image_ctx.snap_info.find(snap_id);
@ -734,8 +734,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, InitShutDown) {
mock_remote_image_ctx,
mock_image_meta);
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
"local mirror uuid", &m_pool_meta_cache,
&mock_state_builder, &mock_replayer_listener};
"local mirror uuid", "local mirror peer uuid",
&m_pool_meta_cache, &mock_state_builder,
&mock_replayer_listener};
m_pool_meta_cache.set_remote_pool_meta(
m_remote_fsid, m_remote_io_ctx.get_id(),
{"remote mirror uuid", "remote mirror peer uuid"});
@ -788,8 +789,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, SyncSnapshot) {
mock_remote_image_ctx,
mock_image_meta);
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
"local mirror uuid", &m_pool_meta_cache,
&mock_state_builder, &mock_replayer_listener};
"local mirror uuid", "local mirror peer uuid",
&m_pool_meta_cache, &mock_state_builder,
&mock_replayer_listener};
m_pool_meta_cache.set_remote_pool_meta(
m_remote_fsid, m_remote_io_ctx.get_id(),
{"remote mirror uuid", "remote mirror peer uuid"});
@ -913,7 +915,7 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, SyncSnapshot) {
4, true, 0, {}},
0, {}, 0, 0, {}}},
}, 0);
expect_prune_non_primary_snapshot(mock_local_image_ctx, 11, 0);
expect_prune_mirror_snapshot(mock_local_image_ctx, 11, 0);
// idle
expect_load_image_meta(mock_image_meta, false, 0);
@ -966,8 +968,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, InterruptedSyncInitial) {
mock_remote_image_ctx,
mock_image_meta);
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
"local mirror uuid", &m_pool_meta_cache,
&mock_state_builder, &mock_replayer_listener};
"local mirror uuid", "local mirror peer uuid",
&m_pool_meta_cache, &mock_state_builder,
&mock_replayer_listener};
m_pool_meta_cache.set_remote_pool_meta(
m_remote_fsid, m_remote_io_ctx.get_id(),
{"remote mirror uuid", "remote mirror peer uuid"});
@ -1051,8 +1054,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, InterruptedSyncDelta) {
mock_remote_image_ctx,
mock_image_meta);
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
"local mirror uuid", &m_pool_meta_cache,
&mock_state_builder, &mock_replayer_listener};
"local mirror uuid", "local mirror peer uuid",
&m_pool_meta_cache, &mock_state_builder,
&mock_replayer_listener};
m_pool_meta_cache.set_remote_pool_meta(
m_remote_fsid, m_remote_io_ctx.get_id(),
{"remote mirror uuid", "remote mirror peer uuid"});
@ -1129,7 +1133,7 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, InterruptedSyncDelta) {
2, true, 0, {}},
0, {}, 0, 0, {}}},
}, 0);
expect_prune_non_primary_snapshot(mock_local_image_ctx, 11, 0);
expect_prune_mirror_snapshot(mock_local_image_ctx, 11, 0);
// idle
expect_load_image_meta(mock_image_meta, false, 0);
@ -1172,8 +1176,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, InterruptedSyncDeltaDemote) {
mock_remote_image_ctx,
mock_image_meta);
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
"local mirror uuid", &m_pool_meta_cache,
&mock_state_builder, &mock_replayer_listener};
"local mirror uuid", "local mirror peer uuid",
&m_pool_meta_cache, &mock_state_builder,
&mock_replayer_listener};
m_pool_meta_cache.set_remote_pool_meta(
m_remote_fsid, m_remote_io_ctx.get_id(),
{"remote mirror uuid", "remote mirror peer uuid"});
@ -1201,7 +1206,7 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, InterruptedSyncDeltaDemote) {
mock_local_image_ctx.snap_info = {
{11U, librbd::SnapInfo{"snap1", cls::rbd::MirrorSnapshotNamespace{
cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED,
{"remote mirror peer uuid"}, "", CEPH_NOSNAP, true, 0, {}},
{"local mirror peer uuid"}, "", CEPH_NOSNAP, true, 0, {}},
0, {}, 0, 0, {}}},
{12U, librbd::SnapInfo{"snap2", cls::rbd::MirrorSnapshotNamespace{
cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY, {}, "remote mirror uuid",
@ -1229,7 +1234,7 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, InterruptedSyncDeltaDemote) {
false, 0);
expect_notify_sync_complete(mock_instance_watcher, mock_local_image_ctx.id);
// idle
// prune primary demotion snap1
expect_load_image_meta(mock_image_meta, false, 0);
expect_is_refresh_required(mock_remote_image_ctx, true);
expect_refresh(
@ -1244,13 +1249,26 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, InterruptedSyncDeltaDemote) {
mock_local_image_ctx, {
{11U, librbd::SnapInfo{"snap1", cls::rbd::MirrorSnapshotNamespace{
cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED,
{"remote mirror peer uuid"}, "", CEPH_NOSNAP, true, 0, {}},
{"local mirror peer uuid"}, "", CEPH_NOSNAP, true, 0, {}},
0, {}, 0, 0, {}}},
{12U, librbd::SnapInfo{"snap2", cls::rbd::MirrorSnapshotNamespace{
cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY, {}, "remote mirror uuid",
2, true, 0, {}},
0, {}, 0, 0, {}}},
}, 0);
expect_prune_mirror_snapshot(mock_local_image_ctx, 11, 0);
// idle
expect_load_image_meta(mock_image_meta, false, 0);
expect_is_refresh_required(mock_remote_image_ctx, false);
expect_is_refresh_required(mock_local_image_ctx, true);
expect_refresh(
mock_local_image_ctx, {
{12U, librbd::SnapInfo{"snap2", cls::rbd::MirrorSnapshotNamespace{
cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY, {}, "remote mirror uuid",
2, true, 0, {}},
0, {}, 0, 0, {}}},
}, 0);
// wake-up replayer
update_watch_ctx->handle_notify();
@ -1281,8 +1299,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, InterruptedPendingSyncInitial) {
mock_remote_image_ctx,
mock_image_meta);
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
"local mirror uuid", &m_pool_meta_cache,
&mock_state_builder, &mock_replayer_listener};
"local mirror uuid", "local mirror peer uuid",
&m_pool_meta_cache, &mock_state_builder,
&mock_replayer_listener};
m_pool_meta_cache.set_remote_pool_meta(
m_remote_fsid, m_remote_io_ctx.get_id(),
{"remote mirror uuid", "remote mirror peer uuid"});
@ -1365,8 +1384,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, InterruptedPendingSyncDelta) {
mock_remote_image_ctx,
mock_image_meta);
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
"local mirror uuid", &m_pool_meta_cache,
&mock_state_builder, &mock_replayer_listener};
"local mirror uuid", "local mirror peer uuid",
&m_pool_meta_cache, &mock_state_builder,
&mock_replayer_listener};
m_pool_meta_cache.set_remote_pool_meta(
m_remote_fsid, m_remote_io_ctx.get_id(),
{"remote mirror uuid", "remote mirror peer uuid"});
@ -1404,7 +1424,7 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, InterruptedPendingSyncDelta) {
expect_load_image_meta(mock_image_meta, false, 0);
expect_is_refresh_required(mock_remote_image_ctx, false);
expect_is_refresh_required(mock_local_image_ctx, false);
expect_prune_non_primary_snapshot(mock_local_image_ctx, 12, 0);
expect_prune_mirror_snapshot(mock_local_image_ctx, 12, 0);
// sync snap2
expect_load_image_meta(mock_image_meta, false, 0);
@ -1462,7 +1482,7 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, InterruptedPendingSyncDelta) {
2, true, 0, {}},
0, {}, 0, 0, {}}},
}, 0);
expect_prune_non_primary_snapshot(mock_local_image_ctx, 11, 0);
expect_prune_mirror_snapshot(mock_local_image_ctx, 11, 0);
// idle
expect_load_image_meta(mock_image_meta, false, 0);
@ -1505,8 +1525,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, InterruptedPendingSyncDeltaDemote)
mock_remote_image_ctx,
mock_image_meta);
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
"local mirror uuid", &m_pool_meta_cache,
&mock_state_builder, &mock_replayer_listener};
"local mirror uuid", "local mirror peer uuid",
&m_pool_meta_cache, &mock_state_builder,
&mock_replayer_listener};
m_pool_meta_cache.set_remote_pool_meta(
m_remote_fsid, m_remote_io_ctx.get_id(),
{"remote mirror uuid", "remote mirror peer uuid"});
@ -1534,7 +1555,7 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, InterruptedPendingSyncDeltaDemote)
mock_local_image_ctx.snap_info = {
{11U, librbd::SnapInfo{"snap1", cls::rbd::MirrorSnapshotNamespace{
cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED,
{"remote mirror peer uuid"}, "", CEPH_NOSNAP, true, 0, {}},
{"local mirror peer uuid"}, "", CEPH_NOSNAP, true, 0, {}},
0, {}, 0, 0, {}}},
{12U, librbd::SnapInfo{"snap2", cls::rbd::MirrorSnapshotNamespace{
cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY, {}, "remote mirror uuid",
@ -1545,7 +1566,7 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, InterruptedPendingSyncDeltaDemote)
expect_load_image_meta(mock_image_meta, false, 0);
expect_is_refresh_required(mock_remote_image_ctx, false);
expect_is_refresh_required(mock_local_image_ctx, false);
expect_prune_non_primary_snapshot(mock_local_image_ctx, 12, 0);
expect_prune_mirror_snapshot(mock_local_image_ctx, 12, 0);
// sync snap2
expect_load_image_meta(mock_image_meta, false, 0);
@ -1555,7 +1576,7 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, InterruptedPendingSyncDeltaDemote)
mock_local_image_ctx, {
{11U, librbd::SnapInfo{"snap1", cls::rbd::MirrorSnapshotNamespace{
cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED,
{"remote mirror peer uuid"}, "", CEPH_NOSNAP, true, 0, {}},
{"local mirror peer uuid"}, "", CEPH_NOSNAP, true, 0, {}},
0, {}, 0, 0, {}}},
}, 0);
MockSnapshotCopyRequest mock_snapshot_copy_request;
@ -1581,7 +1602,7 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, InterruptedPendingSyncDeltaDemote)
false, 0);
expect_notify_sync_complete(mock_instance_watcher, mock_local_image_ctx.id);
// idle
// prune primary demotion snap1
expect_load_image_meta(mock_image_meta, false, 0);
expect_is_refresh_required(mock_remote_image_ctx, true);
expect_refresh(
@ -1596,13 +1617,26 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, InterruptedPendingSyncDeltaDemote)
mock_local_image_ctx, {
{11U, librbd::SnapInfo{"snap1", cls::rbd::MirrorSnapshotNamespace{
cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED,
{"remote mirror peer uuid"}, "", CEPH_NOSNAP, true, 0, {}},
{"local mirror peer uuid"}, "", CEPH_NOSNAP, true, 0, {}},
0, {}, 0, 0, {}}},
{13U, librbd::SnapInfo{"snap2", cls::rbd::MirrorSnapshotNamespace{
cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY, {}, "remote mirror uuid",
2, true, 0, {}},
0, {}, 0, 0, {}}},
}, 0);
expect_prune_mirror_snapshot(mock_local_image_ctx, 11, 0);
// idle
expect_load_image_meta(mock_image_meta, false, 0);
expect_is_refresh_required(mock_remote_image_ctx, false);
expect_is_refresh_required(mock_local_image_ctx, true);
expect_refresh(
mock_local_image_ctx, {
{13U, librbd::SnapInfo{"snap2", cls::rbd::MirrorSnapshotNamespace{
cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY, {}, "remote mirror uuid",
2, true, 0, {}},
0, {}, 0, 0, {}}},
}, 0);
// wake-up replayer
update_watch_ctx->handle_notify();
@ -1633,8 +1667,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, RemoteImageDemoted) {
mock_remote_image_ctx,
mock_image_meta);
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
"local mirror uuid", &m_pool_meta_cache,
&mock_state_builder, &mock_replayer_listener};
"local mirror uuid", "local mirror peer uuid",
&m_pool_meta_cache, &mock_state_builder,
&mock_replayer_listener};
m_pool_meta_cache.set_remote_pool_meta(
m_remote_fsid, m_remote_io_ctx.get_id(),
{"remote mirror uuid", "remote mirror peer uuid"});
@ -1687,8 +1722,8 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, RemoteImageDemoted) {
expect_refresh(
mock_local_image_ctx, {
{11U, librbd::SnapInfo{"snap1", cls::rbd::MirrorSnapshotNamespace{
cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY, {}, "remote mirror uuid",
1, true, 0, {}},
cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY_DEMOTED,
{"local mirror peer uuid"}, "remote mirror uuid", 1, true, 0, {}},
0, {}, 0, 0, {}}},
}, 0);
@ -1722,8 +1757,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, LocalImagePromoted) {
mock_remote_image_ctx,
mock_image_meta);
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
"local mirror uuid", &m_pool_meta_cache,
&mock_state_builder, &mock_replayer_listener};
"local mirror uuid", "local mirror peer uuid",
&m_pool_meta_cache, &mock_state_builder,
&mock_replayer_listener};
m_pool_meta_cache.set_remote_pool_meta(
m_remote_fsid, m_remote_io_ctx.get_id(),
{"remote mirror uuid", "remote mirror peer uuid"});
@ -1740,7 +1776,7 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, LocalImagePromoted) {
mock_local_image_ctx.snap_info = {
{1U, librbd::SnapInfo{"snap1", cls::rbd::MirrorSnapshotNamespace{
cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY,
{"remote mirror peer uuid"}, "", CEPH_NOSNAP, true, 0, {}},
{"local mirror peer uuid"}, "", CEPH_NOSNAP, true, 0, {}},
0, {}, 0, 0, {}}}};
// idle
@ -1778,8 +1814,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, ResyncRequested) {
mock_remote_image_ctx,
mock_image_meta);
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
"local mirror uuid", &m_pool_meta_cache,
&mock_state_builder, &mock_replayer_listener};
"local mirror uuid", "local mirror peer uuid",
&m_pool_meta_cache, &mock_state_builder,
&mock_replayer_listener};
m_pool_meta_cache.set_remote_pool_meta(
m_remote_fsid, m_remote_io_ctx.get_id(),
{"remote mirror uuid", "remote mirror peer uuid"});
@ -1834,8 +1871,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, ResyncRequestedRemoteNotPrimary) {
mock_remote_image_ctx,
mock_image_meta);
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
"local mirror uuid", &m_pool_meta_cache,
&mock_state_builder, &mock_replayer_listener};
"local mirror uuid", "local mirror peer uuid",
&m_pool_meta_cache, &mock_state_builder,
&mock_replayer_listener};
m_pool_meta_cache.set_remote_pool_meta(
m_remote_fsid, m_remote_io_ctx.get_id(),
{"remote mirror uuid", "remote mirror peer uuid"});
@ -1890,8 +1928,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, ResyncRequestedRemoteNotPrimary) {
expect_refresh(
mock_local_image_ctx, {
{11U, librbd::SnapInfo{"snap1", cls::rbd::MirrorSnapshotNamespace{
cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY_DEMOTED, {"uuid"},
"remote mirror uuid", 1, true, 0, {{1, CEPH_NOSNAP}}},
cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY_DEMOTED,
{"local mirror peer uuid"}, "remote mirror uuid", 1, true, 0,
{{1, CEPH_NOSNAP}}},
0, {}, 0, 0, {}}},
}, 0);
@ -1923,8 +1962,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, RegisterLocalUpdateWatcherError) {
mock_image_meta);
MockReplayerListener mock_replayer_listener;
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
"local mirror uuid", &m_pool_meta_cache,
&mock_state_builder, &mock_replayer_listener};
"local mirror uuid", "local mirror peer uuid",
&m_pool_meta_cache, &mock_state_builder,
&mock_replayer_listener};
m_pool_meta_cache.set_remote_pool_meta(
m_remote_fsid, m_remote_io_ctx.get_id(),
{"remote mirror uuid", "remote mirror peer uuid"});
@ -1956,8 +1996,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, RegisterRemoteUpdateWatcherError)
mock_image_meta);
MockReplayerListener mock_replayer_listener;
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
"local mirror uuid", &m_pool_meta_cache,
&mock_state_builder, &mock_replayer_listener};
"local mirror uuid", "local mirror peer uuid",
&m_pool_meta_cache, &mock_state_builder,
&mock_replayer_listener};
m_pool_meta_cache.set_remote_pool_meta(
m_remote_fsid, m_remote_io_ctx.get_id(),
{"remote mirror uuid", "remote mirror peer uuid"});
@ -1995,8 +2036,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, UnregisterRemoteUpdateWatcherError
mock_remote_image_ctx,
mock_image_meta);
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
"local mirror uuid", &m_pool_meta_cache,
&mock_state_builder, &mock_replayer_listener};
"local mirror uuid", "local mirror peer uuid",
&m_pool_meta_cache, &mock_state_builder,
&mock_replayer_listener};
m_pool_meta_cache.set_remote_pool_meta(
m_remote_fsid, m_remote_io_ctx.get_id(),
{"remote mirror uuid", "remote mirror peer uuid"});
@ -2037,8 +2079,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, UnregisterLocalUpdateWatcherError)
mock_remote_image_ctx,
mock_image_meta);
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
"local mirror uuid", &m_pool_meta_cache,
&mock_state_builder, &mock_replayer_listener};
"local mirror uuid", "local mirror peer uuid",
&m_pool_meta_cache, &mock_state_builder,
&mock_replayer_listener};
m_pool_meta_cache.set_remote_pool_meta(
m_remote_fsid, m_remote_io_ctx.get_id(),
{"remote mirror uuid", "remote mirror peer uuid"});
@ -2079,8 +2122,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, LoadImageMetaError) {
mock_remote_image_ctx,
mock_image_meta);
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
"local mirror uuid", &m_pool_meta_cache,
&mock_state_builder, &mock_replayer_listener};
"local mirror uuid", "local mirror peer uuid",
&m_pool_meta_cache, &mock_state_builder,
&mock_replayer_listener};
m_pool_meta_cache.set_remote_pool_meta(
m_remote_fsid, m_remote_io_ctx.get_id(),
{"remote mirror uuid", "remote mirror peer uuid"});
@ -2127,8 +2171,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, RefreshLocalImageError) {
mock_remote_image_ctx,
mock_image_meta);
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
"local mirror uuid", &m_pool_meta_cache,
&mock_state_builder, &mock_replayer_listener};
"local mirror uuid", "local mirror peer uuid",
&m_pool_meta_cache, &mock_state_builder,
&mock_replayer_listener};
m_pool_meta_cache.set_remote_pool_meta(
m_remote_fsid, m_remote_io_ctx.get_id(),
{"remote mirror uuid", "remote mirror peer uuid"});
@ -2178,8 +2223,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, RefreshRemoteImageError) {
mock_remote_image_ctx,
mock_image_meta);
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
"local mirror uuid", &m_pool_meta_cache,
&mock_state_builder, &mock_replayer_listener};
"local mirror uuid", "local mirror peer uuid",
&m_pool_meta_cache, &mock_state_builder,
&mock_replayer_listener};
m_pool_meta_cache.set_remote_pool_meta(
m_remote_fsid, m_remote_io_ctx.get_id(),
{"remote mirror uuid", "remote mirror peer uuid"});
@ -2228,8 +2274,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, CopySnapshotsError) {
mock_remote_image_ctx,
mock_image_meta);
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
"local mirror uuid", &m_pool_meta_cache,
&mock_state_builder, &mock_replayer_listener};
"local mirror uuid", "local mirror peer uuid",
&m_pool_meta_cache, &mock_state_builder,
&mock_replayer_listener};
m_pool_meta_cache.set_remote_pool_meta(
m_remote_fsid, m_remote_io_ctx.get_id(),
{"remote mirror uuid", "remote mirror peer uuid"});
@ -2288,8 +2335,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, GetImageStateError) {
mock_remote_image_ctx,
mock_image_meta);
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
"local mirror uuid", &m_pool_meta_cache,
&mock_state_builder, &mock_replayer_listener};
"local mirror uuid", "local mirror peer uuid",
&m_pool_meta_cache, &mock_state_builder,
&mock_replayer_listener};
m_pool_meta_cache.set_remote_pool_meta(
m_remote_fsid, m_remote_io_ctx.get_id(),
{"remote mirror uuid", "remote mirror peer uuid"});
@ -2350,8 +2398,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, CreateNonPrimarySnapshotError) {
mock_remote_image_ctx,
mock_image_meta);
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
"local mirror uuid", &m_pool_meta_cache,
&mock_state_builder, &mock_replayer_listener};
"local mirror uuid", "local mirror peer uuid",
&m_pool_meta_cache, &mock_state_builder,
&mock_replayer_listener};
m_pool_meta_cache.set_remote_pool_meta(
m_remote_fsid, m_remote_io_ctx.get_id(),
{"remote mirror uuid", "remote mirror peer uuid"});
@ -2416,8 +2465,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, UpdateMirrorImageStateError) {
mock_remote_image_ctx,
mock_image_meta);
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
"local mirror uuid", &m_pool_meta_cache,
&mock_state_builder, &mock_replayer_listener};
"local mirror uuid", "local mirror peer uuid",
&m_pool_meta_cache, &mock_state_builder,
&mock_replayer_listener};
m_pool_meta_cache.set_remote_pool_meta(
m_remote_fsid, m_remote_io_ctx.get_id(),
{"remote mirror uuid", "remote mirror peer uuid"});
@ -2484,8 +2534,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, RequestSyncError) {
mock_remote_image_ctx,
mock_image_meta);
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
"local mirror uuid", &m_pool_meta_cache,
&mock_state_builder, &mock_replayer_listener};
"local mirror uuid", "local mirror peer uuid",
&m_pool_meta_cache, &mock_state_builder,
&mock_replayer_listener};
m_pool_meta_cache.set_remote_pool_meta(
m_remote_fsid, m_remote_io_ctx.get_id(),
{"remote mirror uuid", "remote mirror peer uuid"});
@ -2554,8 +2605,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, CopyImageError) {
mock_remote_image_ctx,
mock_image_meta);
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
"local mirror uuid", &m_pool_meta_cache,
&mock_state_builder, &mock_replayer_listener};
"local mirror uuid", "local mirror peer uuid",
&m_pool_meta_cache, &mock_state_builder,
&mock_replayer_listener};
m_pool_meta_cache.set_remote_pool_meta(
m_remote_fsid, m_remote_io_ctx.get_id(),
{"remote mirror uuid", "remote mirror peer uuid"});
@ -2627,8 +2679,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, UpdateNonPrimarySnapshotError) {
mock_remote_image_ctx,
mock_image_meta);
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
"local mirror uuid", &m_pool_meta_cache,
&mock_state_builder, &mock_replayer_listener};
"local mirror uuid", "local mirror peer uuid",
&m_pool_meta_cache, &mock_state_builder,
&mock_replayer_listener};
m_pool_meta_cache.set_remote_pool_meta(
m_remote_fsid, m_remote_io_ctx.get_id(),
{"remote mirror uuid", "remote mirror peer uuid"});
@ -2704,8 +2757,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, UnlinkPeerError) {
mock_remote_image_ctx,
mock_image_meta);
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
"local mirror uuid", &m_pool_meta_cache,
&mock_state_builder, &mock_replayer_listener};
"local mirror uuid", "local mirror peer uuid",
&m_pool_meta_cache, &mock_state_builder,
&mock_replayer_listener};
m_pool_meta_cache.set_remote_pool_meta(
m_remote_fsid, m_remote_io_ctx.get_id(),
{"remote mirror uuid", "remote mirror peer uuid"});
@ -2792,8 +2846,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, SplitBrain) {
mock_remote_image_ctx,
mock_image_meta);
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
"local mirror uuid", &m_pool_meta_cache,
&mock_state_builder, &mock_replayer_listener};
"local mirror uuid", "local mirror peer uuid",
&m_pool_meta_cache, &mock_state_builder,
&mock_replayer_listener};
m_pool_meta_cache.set_remote_pool_meta(
m_remote_fsid, m_remote_io_ctx.get_id(),
{"remote mirror uuid", "remote mirror peer uuid"});
@ -2855,8 +2910,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, RemoteSnapshotMissingSplitBrain) {
mock_remote_image_ctx,
mock_image_meta);
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
"local mirror uuid", &m_pool_meta_cache,
&mock_state_builder, &mock_replayer_listener};
"local mirror uuid", "local mirror peer uuid",
&m_pool_meta_cache, &mock_state_builder,
&mock_replayer_listener};
m_pool_meta_cache.set_remote_pool_meta(
m_remote_fsid, m_remote_io_ctx.get_id(),
{"remote mirror uuid", "remote mirror peer uuid"});
@ -2923,8 +2979,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, RemoteFailover) {
mock_remote_image_ctx,
mock_image_meta);
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
"local mirror uuid", &m_pool_meta_cache,
&mock_state_builder, &mock_replayer_listener};
"local mirror uuid", "local mirror peer uuid",
&m_pool_meta_cache, &mock_state_builder,
&mock_replayer_listener};
m_pool_meta_cache.set_remote_pool_meta(
m_remote_fsid, m_remote_io_ctx.get_id(),
{"remote mirror uuid", "remote mirror peer uuid"});
@ -2956,8 +3013,8 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, RemoteFailover) {
{11U, librbd::SnapInfo{"snap1", cls::rbd::UserSnapshotNamespace{},
0, {}, 0, 0, {}}},
{12U, librbd::SnapInfo{"snap2", cls::rbd::MirrorSnapshotNamespace{
cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED, {}, "", CEPH_NOSNAP,
true, 0, {}},
cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED,
{"local mirror peer uuid"}, "", CEPH_NOSNAP, true, 0, {}},
0, {}, 0, 0, {}}}};
// attach to promoted remote image
@ -2988,7 +3045,7 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, RemoteFailover) {
false, 0);
expect_notify_sync_complete(mock_instance_watcher, mock_local_image_ctx.id);
// idle
// prune primary demotion snap2
expect_load_image_meta(mock_image_meta, false, 0);
expect_is_refresh_required(mock_remote_image_ctx, true);
expect_refresh(
@ -2997,11 +3054,11 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, RemoteFailover) {
0, {}, 0, 0, {}}},
{2U, librbd::SnapInfo{"snap2", cls::rbd::MirrorSnapshotNamespace{
cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY_DEMOTED,
{"remote mirror peer uuid"}, "local mirror uuid", 12U, true, 0, {}},
{}, "local mirror uuid", 12U, true, 0, {}},
0, {}, 0, 0, {}}},
{3U, librbd::SnapInfo{"snap3", cls::rbd::MirrorSnapshotNamespace{
cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY, {}, "", CEPH_NOSNAP, true, 0,
{}},
cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY, {"remote mirror peer uuid"},
"", CEPH_NOSNAP, true, 0, {}},
0, {}, 0, 0, {}}}
}, 0);
expect_is_refresh_required(mock_local_image_ctx, true);
@ -3010,8 +3067,8 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, RemoteFailover) {
{11U, librbd::SnapInfo{"snap1", cls::rbd::UserSnapshotNamespace{},
0, {}, 0, 0, {}}},
{12U, librbd::SnapInfo{"snap2", cls::rbd::MirrorSnapshotNamespace{
cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED, {}, "", CEPH_NOSNAP,
true, 0, {}},
cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED,
{"local mirror peer uuid"}, "", CEPH_NOSNAP, true, 0, {}},
0, {}, 0, 0, {}}},
{13U, librbd::SnapInfo{"snap3", cls::rbd::MirrorSnapshotNamespace{
cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY, {},
@ -3019,6 +3076,22 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, RemoteFailover) {
{{1, 11}, {2, 12}, {3, CEPH_NOSNAP}}},
0, {}, 0, 0, {}}},
}, 0);
expect_prune_mirror_snapshot(mock_local_image_ctx, 12, 0);
// idle
expect_load_image_meta(mock_image_meta, false, 0);
expect_is_refresh_required(mock_remote_image_ctx, false);
expect_is_refresh_required(mock_local_image_ctx, true);
expect_refresh(
mock_local_image_ctx, {
{11U, librbd::SnapInfo{"snap1", cls::rbd::UserSnapshotNamespace{},
0, {}, 0, 0, {}}},
{13U, librbd::SnapInfo{"snap3", cls::rbd::MirrorSnapshotNamespace{
cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY, {},
"remote mirror uuid", 3, true, 0,
{{1, 11}, {2, 12}, {3, CEPH_NOSNAP}}},
0, {}, 0, 0, {}}},
}, 0);
// wake-up replayer
update_watch_ctx->handle_notify();
@ -3065,8 +3138,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, UnlinkRemoteSnapshot) {
mock_remote_image_ctx,
mock_image_meta);
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
"local mirror uuid", &m_pool_meta_cache,
&mock_state_builder, &mock_replayer_listener};
"local mirror uuid", "local mirror peer uuid",
&m_pool_meta_cache, &mock_state_builder,
&mock_replayer_listener};
m_pool_meta_cache.set_remote_pool_meta(
m_remote_fsid, m_remote_io_ctx.get_id(),
{"remote mirror uuid", "remote mirror peer uuid"});
@ -3143,8 +3217,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, SkipImageSync) {
mock_remote_image_ctx,
mock_image_meta);
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
"local mirror uuid", &m_pool_meta_cache,
&mock_state_builder, &mock_replayer_listener};
"local mirror uuid", "local mirror peer uuid",
&m_pool_meta_cache, &mock_state_builder,
&mock_replayer_listener};
m_pool_meta_cache.set_remote_pool_meta(
m_remote_fsid, m_remote_io_ctx.get_id(),
{"remote mirror uuid", "remote mirror peer uuid"});
@ -3222,8 +3297,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, ImageNameUpdated) {
mock_remote_image_ctx,
mock_image_meta);
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
"local mirror uuid", &m_pool_meta_cache,
&mock_state_builder, &mock_replayer_listener};
"local mirror uuid", "local mirror peer uuid",
&m_pool_meta_cache, &mock_state_builder,
&mock_replayer_listener};
m_pool_meta_cache.set_remote_pool_meta(
m_remote_fsid, m_remote_io_ctx.get_id(),
{"remote mirror uuid", "remote mirror peer uuid"});
@ -3284,8 +3360,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, ApplyImageStatePendingShutdown) {
mock_remote_image_ctx,
mock_image_meta);
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
"local mirror uuid", &m_pool_meta_cache,
&mock_state_builder, &mock_replayer_listener};
"local mirror uuid", "local mirror peer uuid",
&m_pool_meta_cache, &mock_state_builder,
&mock_replayer_listener};
C_SaferCond shutdown_ctx;
m_pool_meta_cache.set_remote_pool_meta(
m_remote_fsid, m_remote_io_ctx.get_id(),
@ -3371,8 +3448,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, ApplyImageStateErrorPendingShutdow
mock_remote_image_ctx,
mock_image_meta);
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
"local mirror uuid", &m_pool_meta_cache,
&mock_state_builder, &mock_replayer_listener};
"local mirror uuid", "local mirror peer uuid",
&m_pool_meta_cache, &mock_state_builder,
&mock_replayer_listener};
C_SaferCond shutdown_ctx;
m_pool_meta_cache.set_remote_pool_meta(
m_remote_fsid, m_remote_io_ctx.get_id(),

View File

@ -178,9 +178,11 @@ struct StateBuilder<librbd::MockTestImageCtx> {
}
MOCK_METHOD1(close, void(Context*));
MOCK_METHOD5(create_replayer, Replayer*(Threads<librbd::MockTestImageCtx>*,
MOCK_METHOD6(create_replayer, Replayer*(Threads<librbd::MockTestImageCtx>*,
InstanceWatcher<librbd::MockTestImageCtx>*,
const std::string&, PoolMetaCache*,
const std::string&,
const std::string&,
PoolMetaCache*,
ReplayerListener*));
StateBuilder() {
@ -312,8 +314,8 @@ public:
void expect_create_replayer(MockStateBuilder& mock_state_builder,
MockReplayer& mock_replayer) {
EXPECT_CALL(mock_state_builder, create_replayer(_, _, _, _, _))
.WillOnce(WithArg<4>(
EXPECT_CALL(mock_state_builder, create_replayer(_, _, _, _, _, _))
.WillOnce(WithArg<5>(
Invoke([&mock_replayer]
(image_replayer::ReplayerListener* replayer_listener) {
mock_replayer.replayer_listener = replayer_listener;

View File

@ -431,6 +431,7 @@ void ImageReplayer<I>::start_replay() {
ceph_assert(m_replayer == nullptr);
m_replayer = m_state_builder->create_replayer(m_threads, m_instance_watcher,
m_local_mirror_uuid,
m_remote_image_peer.uuid,
m_pool_meta_cache,
m_replayer_listener);

View File

@ -116,7 +116,7 @@ struct Peer {
template <typename I>
std::ostream& operator<<(std::ostream& os, const Peer<I>& peer) {
return os << "uuid=" << peer.uuid << ", "
return os << "uuid=" << peer.uuid << ", remote_pool_meta="
<< peer.remote_pool_meta;
}

View File

@ -75,6 +75,7 @@ public:
Threads<ImageCtxT>* threads,
InstanceWatcher<ImageCtxT>* instance_watcher,
const std::string& local_mirror_uuid,
const std::string& local_mirror_peer_uuid,
PoolMetaCache* pool_meta_cache,
ReplayerListener* replayer_listener) = 0;

View File

@ -106,6 +106,7 @@ image_replayer::Replayer* StateBuilder<I>::create_replayer(
Threads<I>* threads,
InstanceWatcher<I>* instance_watcher,
const std::string& local_mirror_uuid,
const std::string& local_mirror_peer_uuid,
PoolMetaCache* pool_meta_cache,
ReplayerListener* replayer_listener) {
return Replayer<I>::create(

View File

@ -65,6 +65,7 @@ public:
Threads<ImageCtxT>* threads,
InstanceWatcher<ImageCtxT>* instance_watcher,
const std::string& local_mirror_uuid,
const std::string& local_mirror_peer_uuid,
PoolMetaCache* pool_meta_cache,
ReplayerListener* replayer_listener) override;

View File

@ -116,12 +116,14 @@ Replayer<I>::Replayer(
Threads<I>* threads,
InstanceWatcher<I>* instance_watcher,
const std::string& local_mirror_uuid,
const std::string& local_mirror_peer_uuid,
PoolMetaCache* pool_meta_cache,
StateBuilder<I>* state_builder,
ReplayerListener* replayer_listener)
: m_threads(threads),
m_instance_watcher(instance_watcher),
m_local_mirror_uuid(local_mirror_uuid),
m_local_mirror_peer_uuid(local_mirror_peer_uuid),
m_pool_meta_cache(pool_meta_cache),
m_state_builder(state_builder),
m_replayer_listener(replayer_listener),
@ -171,7 +173,9 @@ void Replayer<I>::init(Context* on_finish) {
}
m_remote_mirror_peer_uuid = remote_pool_meta.mirror_peer_uuid;
dout(10) << "remote_mirror_peer_uuid=" << m_remote_mirror_peer_uuid << dendl;
dout(10) << "local_mirror_peer_uuid=" << m_local_mirror_peer_uuid
<< ", remote_mirror_peer_uuid=" << m_remote_mirror_peer_uuid
<< dendl;
{
auto local_image_ctx = m_state_builder->local_image_ctx;
@ -539,6 +543,18 @@ void Replayer<I>::scan_local_mirror_snapshots(
}
} else if (mirror_ns->is_primary()) {
if (mirror_ns->complete) {
const auto& peer_uuids = mirror_ns->mirror_peer_uuids;
if (peer_uuids.empty() ||
(mirror_ns->state == cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED &&
peer_uuids.size() == 1 &&
peer_uuids.count(m_local_mirror_peer_uuid) == 1)) {
// After relocation, the primary snapshots on the new secondary become
// obsolete snapshots. They can be pruned if they are already unlinked.
// Additionally, in this case, a demoted primary snapshot that is linked
// to only a single remote (current primary) peer is safe to prune,
// because no other peer depends on it waiting for sync.
prune_snap_ids.insert(local_snap_id);
}
m_local_snap_id_start = local_snap_id;
ceph_assert(m_local_snap_id_end == CEPH_NOSNAP);
} else {
@ -564,8 +580,8 @@ void Replayer<I>::scan_local_mirror_snapshots(
locker->unlock();
auto prune_snap_id = *prune_snap_ids.begin();
dout(5) << "pruning unused non-primary snapshot " << prune_snap_id << dendl;
prune_non_primary_snapshot(prune_snap_id);
dout(5) << "pruning unused mirror snapshot " << prune_snap_id << dendl;
prune_mirror_snapshot(prune_snap_id);
return;
}
@ -798,7 +814,7 @@ void Replayer<I>::scan_remote_mirror_snapshots(
}
template <typename I>
void Replayer<I>::prune_non_primary_snapshot(uint64_t snap_id) {
void Replayer<I>::prune_mirror_snapshot(uint64_t snap_id) {
dout(10) << "snap_id=" << snap_id << dendl;
auto local_image_ctx = m_state_builder->local_image_ctx;
@ -825,18 +841,18 @@ void Replayer<I>::prune_non_primary_snapshot(uint64_t snap_id) {
}
auto ctx = create_context_callback<
Replayer<I>, &Replayer<I>::handle_prune_non_primary_snapshot>(this);
Replayer<I>, &Replayer<I>::handle_prune_mirror_snapshot>(this);
local_image_ctx->operations->snap_remove(snap_namespace, snap_name, ctx);
}
template <typename I>
void Replayer<I>::handle_prune_non_primary_snapshot(int r) {
void Replayer<I>::handle_prune_mirror_snapshot(int r) {
dout(10) << "r=" << r << dendl;
if (r < 0 && r != -ENOENT) {
derr << "failed to prune non-primary snapshot: " << cpp_strerror(r)
derr << "failed to prune mirror snapshot: " << cpp_strerror(r)
<< dendl;
handle_replay_complete(r, "failed to prune non-primary snapshot");
handle_replay_complete(r, "failed to prune mirror snapshot");
return;
}

View File

@ -47,17 +47,20 @@ public:
Threads<ImageCtxT>* threads,
InstanceWatcher<ImageCtxT>* instance_watcher,
const std::string& local_mirror_uuid,
const std::string& local_mirror_peer_uuid,
PoolMetaCache* pool_meta_cache,
StateBuilder<ImageCtxT>* state_builder,
ReplayerListener* replayer_listener) {
return new Replayer(threads, instance_watcher, local_mirror_uuid,
pool_meta_cache, state_builder, replayer_listener);
local_mirror_peer_uuid, pool_meta_cache, state_builder,
replayer_listener);
}
Replayer(
Threads<ImageCtxT>* threads,
InstanceWatcher<ImageCtxT>* instance_watcher,
const std::string& local_mirror_uuid,
const std::string& local_mirror_peer_uuid,
PoolMetaCache* pool_meta_cache,
StateBuilder<ImageCtxT>* state_builder,
ReplayerListener* replayer_listener);
@ -202,6 +205,7 @@ private:
Threads<ImageCtxT>* m_threads;
InstanceWatcher<ImageCtxT>* m_instance_watcher;
std::string m_local_mirror_uuid;
std::string m_local_mirror_peer_uuid;
PoolMetaCache* m_pool_meta_cache;
StateBuilder<ImageCtxT>* m_state_builder;
ReplayerListener* m_replayer_listener;
@ -271,8 +275,8 @@ private:
void scan_local_mirror_snapshots(std::unique_lock<ceph::mutex>* locker);
void scan_remote_mirror_snapshots(std::unique_lock<ceph::mutex>* locker);
void prune_non_primary_snapshot(uint64_t snap_id);
void handle_prune_non_primary_snapshot(int r);
void prune_mirror_snapshot(uint64_t snap_id);
void handle_prune_mirror_snapshot(int r);
void copy_snapshots();
void handle_copy_snapshots(int r);

View File

@ -105,11 +105,12 @@ image_replayer::Replayer* StateBuilder<I>::create_replayer(
Threads<I>* threads,
InstanceWatcher<I>* instance_watcher,
const std::string& local_mirror_uuid,
const std::string& local_mirror_peer_uuid,
PoolMetaCache* pool_meta_cache,
ReplayerListener* replayer_listener) {
return Replayer<I>::create(
threads, instance_watcher, local_mirror_uuid, pool_meta_cache, this,
replayer_listener);
threads, instance_watcher, local_mirror_uuid, local_mirror_peer_uuid,
pool_meta_cache, this, replayer_listener);
}
} // namespace snapshot

View File

@ -70,6 +70,7 @@ public:
Threads<ImageCtxT>* threads,
InstanceWatcher<ImageCtxT>* instance_watcher,
const std::string& local_mirror_uuid,
const std::string& local_mirror_peer_uuid,
PoolMetaCache* pool_meta_cache,
ReplayerListener* replayer_listener) override;