]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
osd: fix reference counting during tier_flush
authormyoungwon oh <ohmyoungwon@gmail.com>
Fri, 6 Nov 2020 09:52:53 +0000 (18:52 +0900)
committermyoungwon oh <ohmyoungwon@gmail.com>
Fri, 6 Nov 2020 09:58:11 +0000 (18:58 +0900)
When dealing with reference on manifest object including snapshot,
consider increment/decrement refcount between old and new chunk_map.
See the comment in this commit.

Signed-off-by: Myoungwon Oh <myoungwon.oh@samsumg.com>
src/osd/PrimaryLogPG.cc
src/osd/PrimaryLogPG.h
src/osd/osd_types.h

index 38ce39087d631fdbfc23ea025f1f5cec49285a05..47db8c5603d0e1a29b4087adc2e456fe5d42a58f 100644 (file)
@@ -10045,19 +10045,28 @@ int PrimaryLogPG::start_dedup(OpRequestRef op, ObjectContextRef obc)
       chunk.substr_of(bl, p.first, p.second);
       hobject_t target = get_fpoid_from_chunk(soid, chunk);
 
+      chunk_info_t chunk_info(0, p.second, target);
+      // chunks issued here are different with chunk_map newly generated
+      // because the same chunks in previous snap will not be issued
+      // So, we need two data structures; the first is the issued chunk list to track
+      // issued operations, and the second is the new chunk_map to update chunk_map after 
+      // all operations are finished
+      mop->new_chunk_map[p.first] = chunk_info;
       // skip if the same content exits in prev snap at same offset
       if (obc->ssc->snapset.clones.size()) {
        ObjectContextRef cobc = get_prev_clone_obc(obc);
        if (cobc) {
-         auto c = cobc->obs.oi.manifest.chunk_map.find(p.first);
-         if (c != cobc->obs.oi.manifest.chunk_map.end()) {
-           auto t = oi.manifest.chunk_map.find(p.first);
-           if (t != oi.manifest.chunk_map.end()) {
-             if (t->second == c->second) {
-               continue;
-             }
-           }
-         }
+         object_ref_delta_t refs;
+         object_manifest_t set_chunk;
+         set_chunk.chunk_map[p.first] = chunk_info;
+         set_chunk.calc_refs_to_inc_on_set(
+           &cobc->obs.oi.manifest,
+           nullptr,
+           refs);
+         if (refs.is_empty()) {
+           dout(15) << " found same chunk " << refs << dendl;
+           continue;
+         } 
        }
       }
        
@@ -10225,22 +10234,46 @@ void PrimaryLogPG::finish_set_dedup(hobject_t oid, int r, ceph_tid_t tid, uint64
     ctx->at_version = get_next_version();
     ctx->new_obs = obc->obs;
     ctx->new_obs.oi.clear_flag(object_info_t::FLAG_DIRTY);
-    for (auto p : mop->chunks) {
-      struct chunk_info_t info;
-      info.offset = 0;
-      info.length = p.second.second;
-      info.oid =  p.first;
-      ctx->new_obs.oi.manifest.chunk_map[p.second.first] = info;
-      // drop all references issued before
-      refs.dec_ref(p.first);
-    }
+
+    /* 
+    * Let's assume that there is a manifest snapshotted object, and we issue tier_flush() to head.
+    * head: [0, 2) aaa <-- tier_flush()
+    * 20:   [0, 2) ddd, [6, 2) bbb, [8, 2) ccc
+    * 
+    * In this case, if the new chunk_map is as follows,
+    * new_chunk_map : [0, 2) DDD, [6, 2) bbb, [8, 2) ccc
+    * we should drop aaa from head by using calc_refs_to_drop_on_removal().
+    * So, the precedure is 
+    *  1. calc_refs_to_drop_on_removal()
+    *  2. drop old references by dec_refcount()
+    *  3. update new chunk_map
+    */
+
+    ObjectCleanRegions c_regions = ctx->clean_regions;
+    ObjectContextRef cobc = get_prev_clone_obc(obc);
+    c_regions.mark_fully_dirty(); 
+    // CDC was done on entire range of manifest object,
+    // so the first thing we should do here is to drop the reference to old chunks
+    ObjectContextRef obc_l, obc_g;
+    get_adjacent_clones(ctx->obs->oi, ctx.get(), obc_l, obc_g);
+    // clear all old references
+    ctx->obs->oi.manifest.calc_refs_to_drop_on_removal(
+      obc_l ? &(obc_l->obs.oi.manifest) : nullptr,
+      obc_g ? &(obc_g->obs.oi.manifest) : nullptr,
+      refs);
     if (!refs.is_empty()) {
       ctx->register_on_commit(
         [oid, this, refs](){
           dec_refcount(oid, refs);
         });
     }
-  
+
+    // clear all regions
+    ctx->new_obs.oi.manifest.chunk_map.clear();
+
+    // set new references
+    ctx->new_obs.oi.manifest.chunk_map = mop->new_chunk_map;
+
     finish_ctx(ctx.get(), pg_log_entry_t::CLEAN);
     simple_opc_submit(std::move(ctx));
   }
index b30ee3fccd0cfa5956fdbde169ed15205d7d1ab9..1054617eb40f5123a07841d127e57243d55743dc 100644 (file)
@@ -265,6 +265,8 @@ public:
     std::map<uint64_t, ceph_tid_t> tids; 
     std::map<hobject_t, pair<uint64_t, uint64_t>> chunks;
     uint64_t num_chunks = 0;
+    std::map<uint64_t, chunk_info_t> new_chunk_map;
+    
 
     ManifestOp(RefCountCallback* cb, ceph_tid_t tid)
       : cb(cb), objecter_tid(tid) {}
index 0a879f6fcf8efeb058df7ff510d3d376c058ae47..c82b0d7d614920e8e8efe7b346f12a54b1e36340 100644 (file)
@@ -5571,6 +5571,8 @@ struct chunk_info_t {
   cflag_t flags;   // FLAG_*
 
   chunk_info_t() : offset(0), length(0), flags((cflag_t)0) { }
+  chunk_info_t(uint32_t offset, uint32_t length, hobject_t oid) : 
+    offset(offset), length(length), oid(oid), flags((cflag_t)0) { }
 
   static std::string get_flag_string(uint64_t flags) {
     std::string r;