]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
ReplicatedPG: start_flush: use filtered snapset
authorSamuel Just <sjust@redhat.com>
Wed, 27 May 2015 18:00:54 +0000 (11:00 -0700)
committerSamuel Just <sjust@redhat.com>
Wed, 27 May 2015 18:30:27 +0000 (11:30 -0700)
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 <sjust@redhat.com>
src/osd/ReplicatedPG.cc
src/osd/osd_types.cc
src/osd/osd_types.h

index 4c549a5fd3d39bbaca0b7adc821744054b473115..bdcfd20e47ff7d4aadba8c1d55627ef5ea606f35 100644 (file)
@@ -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<snapid_t>::reverse_iterator p = snapset.clones.rbegin();
index a73b46fbffd8bfc5bc713e6cf2f7937f6ca687fe..7ba24e1764ad47e741a9711597ee339031ba08a1 100644 (file)
@@ -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<snapid_t> oldsnaps;
+  oldsnaps.swap(snaps);
+  for (vector<snapid_t>::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
index 18f5402501966d1233676b4c25258001a4ded4ee..f7525bb5ea7619f9407bcce607f6a39aaf487a3b 100644 (file)
@@ -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)