]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
osd: fix ObjectContextRef reference leak 44439/head
authormyoungwon oh <ohmyoungwon@gmail.com>
Mon, 3 Jan 2022 11:13:33 +0000 (20:13 +0900)
committermyoungwon oh <ohmyoungwon@gmail.com>
Mon, 21 Feb 2022 01:03:43 +0000 (10:03 +0900)
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>
src/osd/PrimaryLogPG.cc
src/osd/PrimaryLogPG.h

index 3023b6376f1979f036b898869ba435df131e0729..9e4cf1b449e0c89e7a22fa9f430c25e00b630a32 100644 (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);
index b92c46bf4a9265d11af87de36426a5d84fa1b1ab..2605c992bca332f6939ca0aed1a5e4cd4bd0b83b 100644 (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;