From: Samuel Just Date: Wed, 27 May 2015 18:00:54 +0000 (-0700) Subject: ReplicatedPG: start_flush: use filtered snapset X-Git-Tag: v9.0.2~86^2~1 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=6051e255ac062985ada1989edb7f23cd750915e2;p=ceph.git ReplicatedPG: start_flush: use filtered snapset Otherwise, we might send our deletes based on deleted snaps. This is problematic since we may have trimmed the clones to which those snaps belong, causing us to send them at an earlier snap than we used before. The specific situation was 78:[78, 70, 63, 5a, 58, 57]:[64(63), 58(58, 57)] with 58 already clean. To flush 64, we send: delete@58 delete@59 copyfrom@62 Then, snap 63 is trimmed leaving us with a snapset of: 78:[78, 70, 63, 5a, 58, 57]:[58(58, 57)] since trim_object doesn't filter the head object snapset snaps. This isn't really a bug since in general all snapset users must be aware that there may be trimmed snaps in snapset::snaps. However, here it becomes a problem when we go to flush head: delete@58 -- ignored due to snapc delete@59 -- ignored due to snapc copyfrom@78 -- not ignored The base pool head is at snap seq 62, so it clones that value into clone 78(78, 70) instead of forgetting it. What should have happened is that we should have based our flushes on filtered snapset: 78:[78, 70, 58, 57]:[58(58, 57)] Causing us to instead send: delete@58 -- ignored due to snapc delete@69 -- not ignored, causes no clone to be made copyfrom@78 -- not ignored, updates head such that a subsequent clone will leave 70 out of the clone snaps vector. Fixes: 11787 Signed-off-by: Samuel Just --- diff --git a/src/osd/ReplicatedPG.cc b/src/osd/ReplicatedPG.cc index 4c549a5fd3d3..bdcfd20e47ff 100644 --- a/src/osd/ReplicatedPG.cc +++ b/src/osd/ReplicatedPG.cc @@ -6824,8 +6824,10 @@ int ReplicatedPG::start_flush( << " " << (blocking ? "blocking" : "non-blocking/best-effort") << dendl; + // get a filtered snapset, need to remove removed snaps + SnapSet snapset = obc->ssc->snapset.get_filtered(pool.info); + // verify there are no (older) check for dirty clones - SnapSet& snapset = obc->ssc->snapset; { dout(20) << " snapset " << snapset << dendl; vector::reverse_iterator p = snapset.clones.rbegin(); diff --git a/src/osd/osd_types.cc b/src/osd/osd_types.cc index a73b46fbffd8..7ba24e1764ad 100644 --- a/src/osd/osd_types.cc +++ b/src/osd/osd_types.cc @@ -4078,6 +4078,25 @@ uint64_t SnapSet::get_clone_bytes(snapid_t clone) const return size; } +void SnapSet::filter(const pg_pool_t &pinfo) +{ + vector oldsnaps; + oldsnaps.swap(snaps); + for (vector::const_iterator i = oldsnaps.begin(); + i != oldsnaps.end(); + ++i) { + if (!pinfo.is_removed_snap(*i)) + snaps.push_back(*i); + } +} + +SnapSet SnapSet::get_filtered(const pg_pool_t &pinfo) const +{ + SnapSet ss = *this; + ss.filter(pinfo); + return ss; +} + // -- watch_info_t -- void watch_info_t::encode(bufferlist& bl) const diff --git a/src/osd/osd_types.h b/src/osd/osd_types.h index 18f540250196..f7525bb5ea76 100644 --- a/src/osd/osd_types.h +++ b/src/osd/osd_types.h @@ -2767,6 +2767,9 @@ struct SnapSet { } return max; } + + SnapSet get_filtered(const pg_pool_t &pinfo) const; + void filter(const pg_pool_t &pinfo); }; WRITE_CLASS_ENCODER(SnapSet)