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 <myoungwon.oh@samsung.com>
This commit is contained in:
myoungwon oh 2022-01-03 20:13:33 +09:00
parent ac826d1665
commit 4fd423ff04
2 changed files with 9 additions and 12 deletions

View File

@ -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<ManifestOp>());
ManifestOpRef mop(std::make_shared<ManifestOp>(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<OSDOp>& ops)
// start
ctx->op_finishers[ctx->current_osd_subop_num].reset(
new SetManifestFinisher(osd_op));
ManifestOpRef mop = std::make_shared<ManifestOp>(new RefCountCallback(ctx, osd_op));
ManifestOpRef mop = std::make_shared<ManifestOp>(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<ManifestOp>());
ManifestOpRef mop(std::make_shared<ManifestOp>(obc, nullptr));
// cdc
std::map<uint64_t, bufferlist> 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);

View File

@ -281,11 +281,12 @@ public:
std::map<hobject_t, std::pair<uint64_t, uint64_t>> 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<ManifestOp> ManifestOpRef;
std::map<hobject_t, ManifestOpRef> manifest_ops;