diff --git a/qa/standalone/osd/pg-split-merge.sh b/qa/standalone/osd/pg-split-merge.sh index 97583da048b..ad697a9fc3c 100755 --- a/qa/standalone/osd/pg-split-merge.sh +++ b/qa/standalone/osd/pg-split-merge.sh @@ -58,19 +58,30 @@ function TEST_a_merge_empty() { wait_for_clean || return 1 - # now 1.0 is there but 1.1 is not + # osd.2: now 1.0 is there but 1.1 is not + + # instantiate 1.1 on osd.2 with last_update=0'0 ('empty'), which is + # the problematic state... then let it merge with 1.0 ceph tell osd.2 config set osd_debug_no_acting_change true ceph osd out 0 1 ceph osd pool set foo pg_num 1 sleep 5 ceph tell osd.2 config set osd_debug_no_acting_change false + + # go back to osd.1 being primary, and 3x so the osd.2 copy doesn't get + # removed ceph osd in 0 1 ceph osd pool set foo size 3 wait_for_clean || return 1 + + # scrub to ensure the osd.3 copy of 1.0 was incomplete (vs missing + # half of its objects). ceph pg scrub 1.0 - sleep 5 - ceph -s | grep inconsistent || return 1 + sleep 10 + ceph log last debug + ceph pg ls + ceph pg ls | grep ' active.clean ' || return 1 } function TEST_import_after_merge_and_gap() { diff --git a/src/osd/PG.cc b/src/osd/PG.cc index 0fce841bafd..f68c4ba8ce0 100644 --- a/src/osd/PG.cc +++ b/src/osd/PG.cc @@ -2718,6 +2718,18 @@ void PG::merge_from(map& sources, RecoveryCtx *rctx, dout(10) << __func__ << " target incomplete" << dendl; incomplete = true; } + if (info.pgid.pgid != last_pg_merge_meta.source_pgid.get_parent()) { + dout(10) << __func__ << " target doesn't match expected parent " + << last_pg_merge_meta.source_pgid.get_parent() + << " of source_pgid " << last_pg_merge_meta.source_pgid + << dendl; + incomplete = true; + } + if (info.last_update != last_pg_merge_meta.target_version) { + dout(10) << __func__ << " target version doesn't match expected " + << last_pg_merge_meta.target_version << dendl; + incomplete = true; + } PGLogEntryHandler handler{this, rctx->transaction}; pg_log.roll_forward(&handler); @@ -2741,6 +2753,17 @@ void PG::merge_from(map& sources, RecoveryCtx *rctx, << dendl; incomplete = true; } + if (source->info.pgid.pgid != last_pg_merge_meta.source_pgid) { + dout(10) << __func__ << " source " << source->info.pgid.pgid + << " doesn't match expected source pgid " + << last_pg_merge_meta.source_pgid << dendl; + incomplete = true; + } + if (source->info.last_update != last_pg_merge_meta.source_version) { + dout(10) << __func__ << " source version doesn't match expected " + << last_pg_merge_meta.target_version << dendl; + incomplete = true; + } // prepare log PGLogEntryHandler handler{source.get(), rctx->transaction};