From 4fd423ff04412f7160ccdf4565ef77e709a87518 Mon Sep 17 00:00:00 2001 From: myoungwon oh Date: Mon, 3 Jan 2022 20:13:33 +0900 Subject: [PATCH] osd: fix ObjectContextRef reference leak After start_dedup() is called on the object, several CREATE_OR_GET_REFs are sent. In the meantime, the ObjectContextRef can be evicted from the cache while the deduplication is in progress. To avoid this situation, this commit adds ObjectContextRef to ManifestOp as FlushOp works. Signed-off-by: Myoungwon Oh --- src/osd/PrimaryLogPG.cc | 14 +++++--------- src/osd/PrimaryLogPG.h | 7 ++++--- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/src/osd/PrimaryLogPG.cc b/src/osd/PrimaryLogPG.cc index 3023b6376f1..9e4cf1b449e 100644 --- a/src/osd/PrimaryLogPG.cc +++ b/src/osd/PrimaryLogPG.cc @@ -3590,7 +3590,7 @@ bool PrimaryLogPG::inc_refcount_by_set(OpContext* ctx, object_manifest_t& set_ch refs); bool need_inc_ref = false; if (!refs.is_empty()) { - ManifestOpRef mop(std::make_shared()); + ManifestOpRef mop(std::make_shared(ctx->obc, nullptr)); for (auto c : set_chunk.chunk_map) { auto p = refs.find(c.second.oid); if (p == refs.end()) { @@ -7113,7 +7113,7 @@ int PrimaryLogPG::do_osd_ops(OpContext *ctx, vector& ops) // start ctx->op_finishers[ctx->current_osd_subop_num].reset( new SetManifestFinisher(osd_op)); - ManifestOpRef mop = std::make_shared(new RefCountCallback(ctx, osd_op)); + ManifestOpRef mop = std::make_shared(ctx->obc, new RefCountCallback(ctx, osd_op)); auto* fin = new C_SetManifestRefCountDone(this, soid, 0); ceph_tid_t tid = refcount_manifest(soid, target, refcount_t::INCREMENT_REF, fin, std::nullopt); @@ -10463,7 +10463,7 @@ int PrimaryLogPG::start_dedup(OpRequestRef op, ObjectContextRef obc) * The operations to make dedup chunks are tracked by a ManifestOp. * This op will be finished if all the operations are completed. */ - ManifestOpRef mop(std::make_shared()); + ManifestOpRef mop(std::make_shared(obc, nullptr)); // cdc std::map chunks; @@ -10619,12 +10619,8 @@ int PrimaryLogPG::finish_set_dedup(hobject_t oid, int r, ceph_tid_t tid, uint64_ // there are on-going works return -EINPROGRESS; } - ObjectContextRef obc = get_object_context(oid, false); - if (!obc) { - if (mop->op) - osd->reply_op_error(mop->op, -EINVAL); - return -EINVAL; - } + ObjectContextRef obc = mop->obc; + ceph_assert(obc); ceph_assert(obc->is_blocked()); obc->stop_block(); kick_object_context_blocked(obc); diff --git a/src/osd/PrimaryLogPG.h b/src/osd/PrimaryLogPG.h index b92c46bf4a9..2605c992bca 100644 --- a/src/osd/PrimaryLogPG.h +++ b/src/osd/PrimaryLogPG.h @@ -281,11 +281,12 @@ public: std::map> chunks; uint64_t num_chunks = 0; object_manifest_t new_manifest; + ObjectContextRef obc; - ManifestOp(RefCountCallback* cb) - : cb(cb) {} - ManifestOp() = default; + ManifestOp(ObjectContextRef obc, RefCountCallback* cb) + : cb(cb), obc(obc) {} + ManifestOp() = delete; }; typedef std::shared_ptr ManifestOpRef; std::map manifest_ops; -- 2.39.5