From 7e80fa068e335db186398c57177844ae7eceeaeb Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Sun, 5 Jan 2014 16:02:19 -0800 Subject: [PATCH] osd/ReplicatedPG: handle promote that races with snap deletion 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 --- src/osd/ReplicatedPG.cc | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/osd/ReplicatedPG.cc b/src/osd/ReplicatedPG.cc index d7674a54df56..01c7704708de 100644 --- a/src/osd/ReplicatedPG.cc +++ b/src/osd/ReplicatedPG.cc @@ -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::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::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; -- 2.47.3