]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
osd/ReplicatedPG: handle promote that races with snap deletion
authorSage Weil <sage@inktank.com>
Mon, 6 Jan 2014 00:02:19 +0000 (16:02 -0800)
committerSage Weil <sage@inktank.com>
Tue, 14 Jan 2014 00:19:48 +0000 (16:19 -0800)
If we are promoting a clone and realize that the object is no longer
defined for any snaps, abort the copy and delete any temp object.

If the defined snaps have changed, make sure they are updated in memory
so that on promote completion the snapshot metadata is correct.

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

index d7674a54df561c3917dcf1d4700eff68be63497b..01c7704708de228c2beb903814b5983bc51c009e 100644 (file)
@@ -4975,6 +4975,29 @@ void ReplicatedPG::process_copy_chunk(hobject_t oid, tid_t tid, int r)
 
   assert(cop->rval >= 0);
 
+  if (oid.snap < CEPH_NOSNAP) {
+    // verify snap hasn't been deleted
+    vector<snapid_t>::iterator p = cop->results.snaps.begin();
+    while (p != cop->results.snaps.end()) {
+      if (pool.info.is_removed_snap(*p)) {
+       dout(10) << __func__ << " clone snap " << *p << " has been deleted"
+                << dendl;
+       for (vector<snapid_t>::iterator q = p + 1;
+            q != cop->results.snaps.end();
+            ++q)
+         *(q - 1) = *q;
+       cop->results.snaps.resize(cop->results.snaps.size() - 1);
+      } else {
+       ++p;
+      }
+    }
+    if (cop->results.snaps.empty()) {
+      dout(10) << __func__ << " no more snaps for " << oid << dendl;
+      r = -ENOENT;
+      goto out;
+    }
+  }
+
   if (!cop->cursor.is_complete()) {
     // write out what we have so far
     if (cop->temp_cursor.is_initial()) {
@@ -5115,8 +5138,20 @@ void ReplicatedPG::finish_promote(int r, OpRequestRef op,
     return;
   }
 
+  if (r == -ENOENT && results->started_temp_obj) {
+    dout(10) << __func__ << " abort; will clean up partial work" << dendl;
+    ObjectContextRef tempobc = get_object_context(results->temp_oid, true);
+    RepGather *repop = simple_repop_create(tempobc);
+    repop->ctx->op_t.remove(results->temp_coll, results->temp_oid);
+    repop->ctx->discard_temp_oid = results->temp_oid;
+    pgbackend->clear_temp_obj(results->temp_oid);
+    simple_repop_submit(repop);
+    results->started_temp_obj = false;
+  }
+
   bool whiteout = false;
   if (r == -ENOENT &&
+      soid.snap == CEPH_NOSNAP &&
       (pool.info.cache_mode == pg_pool_t::CACHEMODE_WRITEBACK ||
        pool.info.cache_mode == pg_pool_t::CACHEMODE_READONLY)) {
     dout(10) << __func__ << " whiteout " << soid << dendl;