}();
bufferlist in;
if (fp_oid != tgt_soid.oid) {
+ // TODO: don't retain reference to dirty extents
// decrement old chunk's reference count
ObjectOperation dec_op;
cls_cas_chunk_put_ref_op put_call;
}
}
-void PrimaryLogPG::refcount_manifest(ObjectContextRef obc, object_locator_t oloc, hobject_t soid,
- SnapContext snapc, bool get, RefCountCallback *cb, uint64_t offset)
+void PrimaryLogPG::dec_refcount_non_intersection(ObjectContextRef obc, const object_info_t& oi,
+ set<uint64_t> intersection_set)
+{
+ for (auto c : oi.manifest.chunk_map) {
+ auto iter = intersection_set.find(c.first);
+ if (intersection_set.end() == iter) {
+ dout(10) << __func__ << " need dereference. " << " offset: " << c.first
+ << " length: " << c.second.length << " oid: " << c.second.oid << dendl;
+ object_locator_t target_oloc(c.second.oid);
+ refcount_manifest(obc, obc->obs.oi.soid, target_oloc, c.second.oid,
+ SnapContext(), refcount_t::DECREMENT_REF, NULL);
+ }
+ }
+}
+
+void PrimaryLogPG::dec_all_refcount_head_manifest(object_info_t& oi, OpContext* ctx)
+{
+ SnapSetContext* ssc = ctx->obc->ssc;
+ ceph_assert(oi.has_manifest());
+ ceph_assert(oi.soid.is_head());
+ // has snapshot
+ if (ssc && ssc->snapset.clones.size() > 0) {
+ dout(15) << __func__ << " has snapset " << dendl;
+ interval_set<uint64_t> &newest_overlap =
+ ssc->snapset.clone_overlap.rbegin()->second;
+ set<uint64_t> refs;
+ ceph_assert(oi.manifest.is_chunked());
+ ceph_assert(!oi.manifest.is_redirect());
+
+ hobject_t clone_oid = oi.soid;
+ clone_oid.snap = ssc->snapset.clone_overlap.rbegin()->first;
+ ObjectContextRef cobc = get_object_context(clone_oid, false, NULL);
+ if (!cobc) {
+ dout(0) << __func__ << ": Can not find clone obc " << clone_oid << dendl;;
+ return;
+ }
+ object_info_t& coi = cobc->obs.oi;
+ oi.manifest.build_intersection_set(coi.manifest.chunk_map, refs, &newest_overlap);
+
+ ctx->register_on_commit(
+ [oi, ctx, this, refs](){
+ dec_refcount_non_intersection(ctx->obc, oi, refs);
+ });
+ return;
+ }
+
+ // no snapshot
+ if ((oi.flags & object_info_t::FLAG_REDIRECT_HAS_REFERENCE) && oi.manifest.is_redirect()) {
+ ctx->register_on_commit(
+ [oi, ctx, this](){
+ object_locator_t target_oloc(oi.manifest.redirect_target);
+ refcount_manifest(ctx->obc, oi.soid, target_oloc, oi.manifest.redirect_target,
+ SnapContext(), refcount_t::DECREMENT_REF, NULL);
+ });
+ } else if (oi.manifest.is_chunked()) {
+ ctx->register_on_commit(
+ [oi, ctx, this](){
+ for (auto p : oi.manifest.chunk_map) {
+ if (p.second.has_reference()) {
+ object_locator_t target_oloc(p.second.oid);
+ refcount_manifest(ctx->obc, oi.soid, target_oloc, p.second.oid,
+ SnapContext(), refcount_t::DECREMENT_REF, NULL);
+ }
+ }
+ });
+ } else {
+ ceph_abort_msg("unrecognized manifest type");
+ }
+}
+
+void PrimaryLogPG::refcount_manifest(ObjectContextRef obc, hobject_t src_soid, object_locator_t oloc,
+ hobject_t tgt_soid, SnapContext snapc, refcount_t type, RefCountCallback* cb)
{
unsigned flags = CEPH_OSD_FLAG_IGNORE_CACHE | CEPH_OSD_FLAG_IGNORE_OVERLAY |
CEPH_OSD_FLAG_RWORDERED;
- dout(10) << __func__ << " Start refcount for " << soid << dendl;
+ dout(10) << __func__ << " Start refcount from " << src_soid
+ << " to " << tgt_soid << dendl;
ObjectOperation obj_op;
bufferlist in;
- if (get) {
+ if (type == refcount_t::INCREMENT_REF) {
cls_cas_chunk_get_ref_op call;
- call.source = obc->obs.oi.soid;
+ call.source = src_soid;
::encode(call, in);
obj_op.call("cas", "chunk_get_ref", in);
- } else {
+ } else if (type == refcount_t::DECREMENT_REF) {
cls_cas_chunk_put_ref_op call;
- call.source = obc->obs.oi.soid;
+ call.source = src_soid;
::encode(call, in);
obj_op.call("cas", "chunk_put_ref", in);
}
}
auto tid = osd->objecter->mutate(
- soid.oid, oloc, obj_op, snapc,
+ tgt_soid.oid, oloc, obj_op, snapc,
ceph::real_clock::from_ceph_timespec(obc->obs.oi.mtime),
flags, c);
if (cb) {
ctx->delta_stats.num_object_clones--;
if (coi.is_cache_pinned())
ctx->delta_stats.num_objects_pinned--;
- if (coi.has_manifest())
+ if (coi.has_manifest()) {
+ set<uint64_t> refs;
+ for (auto p : snapset.clones) {
+ hobject_t clone_oid = coid;
+ if (clone_oid.snap == p) {
+ continue;
+ }
+ clone_oid.snap = p;
+ ObjectContextRef cobc = get_object_context(clone_oid, false, NULL);
+ if (!cobc) {
+ close_op_ctx(ctx.release());
+ dout(0) << __func__ << ": Can not find obc " << coid << dendl;;
+ return -ENOENT;
+ }
+
+ // check if the references is still used
+ object_info_t& oi = cobc->obs.oi;
+ if (oi.has_manifest()) {
+ coi.manifest.build_intersection_set(oi.manifest.chunk_map, refs, NULL);
+ }
+ }
+
+ dec_refcount_non_intersection(head_obc, coi, refs);
ctx->delta_stats.num_objects_manifest--;
+ }
obc->obs.exists = false;
snapset.clones.erase(p);
if (oi.is_cache_pinned()) {
ctx->delta_stats.num_objects_pinned--;
}
- if (coi.has_manifest())
+ if (oi.has_manifest()) {
ctx->delta_stats.num_objects_manifest--;
+ dec_all_refcount_head_manifest(oi, ctx.get());
+ }
head_obc->obs.exists = false;
head_obc->obs.oi = object_info_t(head_oid);
t->remove(head_oid);
result = 0;
tracepoint(osd, do_osd_op_pre_delete, soid.oid.name.c_str(), soid.snap.val);
{
- if (oi.has_manifest()) {
- if ((oi.flags & object_info_t::FLAG_REDIRECT_HAS_REFERENCE) && oi.manifest.is_redirect()) {
- ctx->register_on_commit(
- [oi, ctx, this](){
- object_locator_t target_oloc(oi.manifest.redirect_target);
- refcount_manifest(ctx->obc, target_oloc, oi.manifest.redirect_target,
- SnapContext(), false, NULL, 0);
- });
- } else if (oi.manifest.is_chunked()) {
- ctx->register_on_commit(
- [oi, ctx, this](){
- for (auto p : oi.manifest.chunk_map) {
- if (p.second.has_reference()) {
- object_locator_t target_oloc(p.second.oid);
- refcount_manifest(ctx->obc, target_oloc, p.second.oid,
- SnapContext(), false, NULL, p.first);
- }
- }
- });
- }
- }
result = _delete_oid(ctx, false, ctx->ignore_cache);
}
break;
ctx->op_finishers[ctx->current_osd_subop_num].reset(
new SetManifestFinisher(osd_op));
RefCountCallback *fin = new RefCountCallback(ctx, osd_op);
- refcount_manifest(ctx->obc, target_oloc, target, SnapContext(),
- true, fin, 0);
+ refcount_manifest(ctx->obc, ctx->obc->obs.oi.soid, target_oloc, target,
+ SnapContext(), refcount_t::INCREMENT_REF, fin);
result = -EINPROGRESS;
} else {
// finish
result = -EOPNOTSUPP;
break;
}
+ if (soid.has_snapset()) {
+ result = -EOPNOTSUPP;
+ break;
+ }
object_locator_t tgt_oloc;
uint64_t src_offset, src_length, tgt_offset;
ctx->op_finishers[ctx->current_osd_subop_num].reset(
new SetManifestFinisher(osd_op));
RefCountCallback *fin = new RefCountCallback(ctx, osd_op);
- refcount_manifest(ctx->obc, tgt_oloc, target, SnapContext(),
- true, fin, src_offset);
+ refcount_manifest(ctx->obc, ctx->obc->obs.oi.soid, tgt_oloc, target,
+ SnapContext(), refcount_t::INCREMENT_REF, fin);
result = -EINPROGRESS;
} else {
if (op_finisher) {
chunk_info.set_flag(chunk_info_t::FLAG_MISSING);
chunk_info.oid = target;
chunk_info.offset = tgt_offset;
- chunk_info.length= src_length;
+ chunk_info.length = src_length;
oi.manifest.chunk_map[src_offset] = chunk_info;
if (!oi.has_manifest() && !oi.manifest.is_chunked())
ctx->delta_stats.num_objects_manifest++;
if (obs.oi.manifest.is_chunked()) {
src_hoid = obs.oi.soid;
- cb = new PromoteManifestCallback(ctx->obc, this, ctx);
} else if (obs.oi.manifest.is_redirect()) {
object_locator_t src_oloc(obs.oi.manifest.redirect_target);
my_oloc = src_oloc;
src_hoid = obs.oi.manifest.redirect_target;
- cb = new PromoteManifestCallback(ctx->obc, this, ctx);
} else {
ceph_abort_msg("unrecognized manifest type");
}
+ cb = new PromoteManifestCallback(ctx->obc, this, ctx);
ctx->op_finishers[ctx->current_osd_subop_num].reset(
new PromoteFinisher(cb));
unsigned flags = CEPH_OSD_COPY_FROM_FLAG_IGNORE_OVERLAY |
break;
}
- if (oi.manifest.is_redirect()) {
- if ((oi.flags & object_info_t::FLAG_REDIRECT_HAS_REFERENCE)) {
- ctx->register_on_commit(
- [oi, ctx, this](){
- object_locator_t target_oloc(oi.manifest.redirect_target);
- refcount_manifest(ctx->obc, target_oloc, oi.manifest.redirect_target,
- SnapContext(), false, NULL, 0);
- });
- }
- } else if (oi.manifest.is_chunked()) {
- ctx->register_on_commit(
- [oi, ctx, this](){
- for (auto p : oi.manifest.chunk_map) {
- if (p.second.flags & chunk_info_t::FLAG_HAS_REFERENCE) {
- object_locator_t target_oloc(p.second.oid);
- refcount_manifest(ctx->obc, target_oloc, p.second.oid,
- SnapContext(), false, NULL, p.first);
- }
- }
- });
- } else {
- ceph_abort_msg("unrecognized manifest type");
- }
+ dec_all_refcount_head_manifest(oi, ctx);
oi.clear_flag(object_info_t::FLAG_MANIFEST);
oi.manifest = object_manifest_t();
dout(20) << __func__ << " setting whiteout on " << soid << dendl;
oi.set_flag(object_info_t::FLAG_WHITEOUT);
ctx->delta_stats.num_whiteouts++;
+ if (oi.has_manifest()) {
+ ctx->delta_stats.num_objects_manifest--;
+ dec_all_refcount_head_manifest(oi, ctx);
+ }
t->create(soid);
osd->logger->inc(l_osd_tier_whiteout);
return 0;
}
if (oi.has_manifest()) {
ctx->delta_stats.num_objects_manifest--;
+ dec_all_refcount_head_manifest(oi, ctx);
}
obs.exists = false;
return 0;
if (pool.info.is_erasure())
ctx->clone_obc->attr_cache = ctx->obc->attr_cache;
snap_oi = &ctx->clone_obc->obs.oi;
+ if (ctx->obc->obs.oi.has_manifest()) {
+ if ((ctx->obc->obs.oi.flags & object_info_t::FLAG_REDIRECT_HAS_REFERENCE) &&
+ ctx->obc->obs.oi.manifest.is_redirect()) {
+ snap_oi->set_flag(object_info_t::FLAG_MANIFEST);
+ snap_oi->manifest.type = object_manifest_t::TYPE_REDIRECT;
+ snap_oi->manifest.redirect_target = ctx->obc->obs.oi.manifest.redirect_target;
+ } else if (ctx->obc->obs.oi.manifest.is_chunked()) {
+ snap_oi->set_flag(object_info_t::FLAG_MANIFEST);
+ snap_oi->manifest.type = object_manifest_t::TYPE_CHUNKED;
+ snap_oi->manifest.chunk_map = ctx->obc->obs.oi.manifest.chunk_map;
+ } else {
+ ceph_abort_msg("unrecognized manifest type");
+ }
+ }
bool got = ctx->lock_manager.get_write_greedy(
coid,
ctx->clone_obc,
ObjectOperation op;
op.dup(sub_cop->chunk_ops);
- dout(20) << __func__ << " tgt_oid: " << soid.oid << " tgt_offset: "
- << manifest->chunk_map[iter->first].offset
- << " length: " << length << " pool id: " << oloc.pool << dendl;
-
if (cop->results.user_version) {
op.assert_version(cop->results.user_version);
} else {
sub_cop->results.user_version ? NULL : &sub_cop->results.user_version);
fin->tid = tid;
sub_cop->objecter_tid = tid;
+
+ dout(20) << __func__ << " tgt_oid: " << soid.oid << " tgt_offset: "
+ << manifest->chunk_map[iter->first].offset
+ << " length: " << length << " pool id: " << oloc.pool
+ << " tid: " << tid << dendl;
+
if (last_offset < iter->first) {
break;
}