]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
osd/ReplicatedPG: infer snaps from head when promoting oldest clean clone
authorSage Weil <sage@inktank.com>
Mon, 30 Dec 2013 20:57:28 +0000 (12:57 -0800)
committerSage Weil <sage@inktank.com>
Tue, 14 Jan 2014 00:19:47 +0000 (16:19 -0800)
Consider:

 - base and cache have same object foo; marked clean in cache pool
 - modify + clone foo in cache pool.  foo clone is clean.
 - foo clone is evicted
 - foo clone is read, and promoted
 - we read foo@something from base pool, and get the head's content

copy-get does not provide us with a snaps list.  Instead, we use the
snap_seq from the head to infer what the snaps vector was in the cache
pool and will be in the base pool when we flush the updates to the object.

Signed-off-by: Sage Weil <sage@inktank.com>
src/osd/ReplicatedPG.cc

index e370e3feede2453edc8d3187685436d7ab7badf4..ea862ccb700543a8e9e4eb79fbca900be919edae 100644 (file)
@@ -5144,7 +5144,29 @@ void ReplicatedPG::finish_promote(int r, OpRequestRef op,
     tctx->delta_stats.num_bytes += results->object_size;
     tctx->new_obs.oi.category = results->category;
     tctx->new_obs.oi.user_version = results->user_version;
-    tctx->new_obs.oi.snaps = results->snaps;
+
+    if (soid.snap != CEPH_NOSNAP) {
+      if (!results->snaps.empty()) {
+       tctx->new_obs.oi.snaps = results->snaps;
+      } else {
+       // we must have read "snap" content from the head object in
+       // the base pool.  use snap_seq to construct what snaps should
+       // be for this clone (what is was before we evicted the clean
+       // clone from this pool, and what it will be when we flush and
+       // the clone eventually happens in the base pool).
+       SnapSet& snapset = obc->ssc->snapset;
+       vector<snapid_t>::iterator p = snapset.snaps.begin();
+       while (p != snapset.snaps.end() && *p > soid.snap)
+         ++p;
+       assert(p != snapset.snaps.end() && *p == soid.snap);
+       do {
+         tctx->new_obs.oi.snaps.push_back(*p);
+         ++p;
+       } while (p != snapset.snaps.end() && *p > results->snap_seq);
+      }
+      dout(20) << __func__ << " snaps " << tctx->new_obs.oi.snaps << dendl;
+      assert(!tctx->new_obs.oi.snaps.empty());
+    }
   }
 
   if (results->mirror_snapset) {