From: Sage Weil Date: Fri, 10 Aug 2018 13:50:42 +0000 (-0500) Subject: osd/PG: do not purge strays in premerge state X-Git-Tag: v14.0.1~371^2~4 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=ce53eb332931bee8b1528f9dbee96f5075db19db;p=ceph.git osd/PG: do not purge strays in premerge state The point of premerge is to ensure that the constituent parts of the target PG are fully clean. If there is an intervening PG migration and one of the halves finishes migrating before the other, one half could get removed and the final merge could result in an incomplete PG. In the worst case, the two halves (let's call them A and B) could have started out together on say [0,1,2], A moves to [3,4,5] and gets deleted from [0,1,2], and then the final merge happens such that *all* copies of the PG are incomplete. We could construct a clever check that does allow removal of strays when the sibling PG is also ready to go, but it would be complicated. Do the simple thing. In reality, this would be an extremely hard case to hit because the premerge window is generally very short. Signed-off-by: Sage Weil --- diff --git a/src/osd/PG.cc b/src/osd/PG.cc index ae881ad6307d..4fe7efb36f5b 100644 --- a/src/osd/PG.cc +++ b/src/osd/PG.cc @@ -2901,6 +2901,11 @@ void PG::cancel_recovery() void PG::purge_strays() { + if (is_premerge()) { + dout(10) << "purge_strays " << stray_set << " but premerge, doing nothing" + << dendl; + return; + } dout(10) << "purge_strays " << stray_set << dendl; bool removed = false; diff --git a/src/osd/PG.h b/src/osd/PG.h index a4a5142f1bdb..dc14dfb63ba7 100644 --- a/src/osd/PG.h +++ b/src/osd/PG.h @@ -2833,6 +2833,7 @@ protected: return state_test(PG_STATE_ACTIVE) || state_test(PG_STATE_PEERED); } bool is_recovering() const { return state_test(PG_STATE_RECOVERING); } + bool is_premerge() const { return state_test(PG_STATE_PREMERGE); } bool is_empty() const { return info.last_update == eversion_t(0,0); }