]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
ReplicatedPG: if we get ENOENT on clone, remove clone from snapset
authorSamuel Just <sam.just@inktank.com>
Fri, 18 Apr 2014 23:51:34 +0000 (16:51 -0700)
committerSamuel Just <sam.just@inktank.com>
Mon, 21 Apr 2014 22:11:04 +0000 (15:11 -0700)
Fixes: #7916
Signed-off-by: Samuel Just <sam.just@inktank.com>
src/osd/PG.cc
src/osd/PG.h
src/osd/ReplicatedPG.cc

index 5a79ab98ba95eb6e33ac6e047e3f1d0d917043a6..9c75ff100966b494aeed2e96fa38e491fc4019e9 100644 (file)
@@ -2860,18 +2860,18 @@ void PG::update_snap_map(
 /**
  * filter trimming|trimmed snaps out of snapcontext
  */
-void PG::filter_snapc(SnapContext& snapc)
+void PG::filter_snapc(vector<snapid_t> &snaps)
 {
   bool filtering = false;
   vector<snapid_t> newsnaps;
-  for (vector<snapid_t>::iterator p = snapc.snaps.begin();
-       p != snapc.snaps.end();
+  for (vector<snapid_t>::iterator p = snaps.begin();
+       p != snaps.end();
        ++p) {
     if (snap_trimq.contains(*p) || info.purged_snaps.contains(*p)) {
       if (!filtering) {
        // start building a new vector with what we've seen so far
-       dout(10) << "filter_snapc filtering " << snapc << dendl;
-       newsnaps.insert(newsnaps.begin(), snapc.snaps.begin(), p);
+       dout(10) << "filter_snapc filtering " << snaps << dendl;
+       newsnaps.insert(newsnaps.begin(), snaps.begin(), p);
        filtering = true;
       }
       dout(20) << "filter_snapc  removing trimq|purged snap " << *p << dendl;
@@ -2881,8 +2881,8 @@ void PG::filter_snapc(SnapContext& snapc)
     }
   }
   if (filtering) {
-    snapc.snaps.swap(newsnaps);
-    dout(10) << "filter_snapc  result " << snapc << dendl;
+    snaps.swap(newsnaps);
+    dout(10) << "filter_snapc  result " << snaps << dendl;
   }
 }
 
index 58585dfe12cac51b88b77376cb8a960afd43924b..fa5bccd1d20ff28afc8cd9eaa0459107debd7773 100644 (file)
@@ -2003,7 +2003,7 @@ public:
     vector<pg_log_entry_t> &log_entries,
     ObjectStore::Transaction& t);
 
-  void filter_snapc(SnapContext& snapc);
+  void filter_snapc(vector<snapid_t> &snaps);
 
   void log_weirdness();
 
index 3b4bb055f9d719235b51f3a978f8163d25802c5b..25bec4106a973f8ce3f3ecb1dab179bfecdc8549 100644 (file)
@@ -4734,7 +4734,7 @@ void ReplicatedPG::make_writeable(OpContext *ctx)
   }
 
   if (ctx->obs->exists)
-    filter_snapc(snapc);
+    filter_snapc(snapc.snaps);
   
   if ((ctx->obs->exists && !ctx->obs->oi.is_whiteout()) && // head exist(ed)
       snapc.snaps.size() &&                 // there are snaps
@@ -5768,6 +5768,42 @@ void ReplicatedPG::finish_promote(int r, OpRequestRef op,
     results->started_temp_obj = false;
   }
 
+  if (r == -ENOENT && soid.is_snap()) {
+    dout(10) << __func__
+            << ": enoent while trying to promote clone, " << soid
+            << " must have been trimmed, removing from snapset"
+            << dendl;
+    hobject_t head(soid.get_head());
+    ObjectContextRef obc = get_object_context(head, false);
+    assert(obc);
+    RepGather *repop = simple_repop_create(obc);
+    OpContext *tctx = repop->ctx;
+    tctx->at_version = get_next_version();
+    filter_snapc(tctx->new_snapset.snaps);
+    vector<snapid_t> new_clones(tctx->new_snapset.clones.size());
+    for (vector<snapid_t>::iterator i = tctx->new_snapset.clones.begin();
+        i != tctx->new_snapset.clones.end();
+        ++i) {
+      if (*i != soid.snap)
+       new_clones.push_back(*i);
+    }
+    tctx->new_snapset.clones.swap(new_clones);
+    tctx->new_snapset.clone_overlap.erase(soid.snap);
+    tctx->new_snapset.clone_size.erase(soid.snap);
+
+    // take RWWRITE lock for duration of our local write.  ignore starvation.
+    if (!obc->rwstate.take_write_lock()) {
+      assert(0 == "problem!");
+    }
+    tctx->lock_to_release = OpContext::W_LOCK;
+    dout(20) << __func__ << " took lock on obc, " << obc->rwstate << dendl;
+
+    finish_ctx(tctx, pg_log_entry_t::PROMOTE);
+
+    simple_repop_submit(repop);
+    return;
+  }
+
   bool whiteout = false;
   if (r == -ENOENT &&
       soid.snap == CEPH_NOSNAP &&