/**
* 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;
}
}
if (filtering) {
- snapc.snaps.swap(newsnaps);
- dout(10) << "filter_snapc result " << snapc << dendl;
+ snaps.swap(newsnaps);
+ dout(10) << "filter_snapc result " << snaps << dendl;
}
}
}
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
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 &&