]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
osd/,rados/: modify TIER_FLUSH to implicitly make an object a manifest object
authormyoungwon oh <ohmyoungwon@gmail.com>
Sun, 1 May 2022 13:48:14 +0000 (22:48 +0900)
committermyoungwon oh <ohmyoungwon@gmail.com>
Thu, 28 Jul 2022 01:22:11 +0000 (10:22 +0900)
Existing object-dedup command always creates temporary object and
perform set-chunk to make the input object manifest---this is because
current tier-flush, which is called by object-dedup, works only if
the target object is manifest, otherwise it just return 0.

So, object-dedup may not work if the target is already manifest.
Moreover, it causes unnecessary overhead if the target object is not manifest.

To solve these, this commit makes existing tier-flush to
change object's state to manifest implicitly.

With this change, the only required operation when calling object-dedup
is a tier-flush and object-dedup can work with the manifest object.

Signed-off-by: Myoungwon Oh <myoungwon.oh@samsung.com>
qa/workunits/rados/test_dedup_tool.sh
src/include/rados/librados.hpp
src/osd/PrimaryLogPG.cc
src/osd/PrimaryLogPG.h
src/tools/ceph_dedup_tool.cc

index ecfaeb1411e0ca8dfc626b7ccb9eee2d33c34815..a42ace542c665fc4da520480d7be34362e80cf5e 100755 (executable)
@@ -316,6 +316,17 @@ function test_dedup_object()
     die "Scrub failed expecting bar is removed"
   fi
 
+  CHUNK_OID=$(echo -n "There HIHIHI" | sha1sum | awk '{print $1}')
+  RESULT=$($DEDUP_TOOL --op dump-chunk-refs --chunk-pool $CHUNK_POOL --object $CHUNK_OID | grep bar)
+  if [ -z "$RESULT" ] ; then
+    $CEPH_TOOL osd pool delete $POOL $POOL --yes-i-really-really-mean-it
+    $CEPH_TOOL osd pool delete $CHUNK_POOL $CHUNK_POOL --yes-i-really-really-mean-it
+    die "Scrub failed expecting bar is removed"
+  fi
+  # rerun tier-flush
+
+  RESULT=$($DEDUP_TOOL --pool $POOL --op object-dedup --object bar --chunk-pool $CHUNK_POOL --fingerprint-algorithm sha1 --dedup-cdc-chunk-size 4096)
+
   CHUNK_OID=$(echo -n "There HIHIHI" | sha1sum | awk '{print $1}')
   RESULT=$($DEDUP_TOOL --op dump-chunk-refs --chunk-pool $CHUNK_POOL --object $CHUNK_OID | grep bar)
   if [ -z "$RESULT" ] ; then
index 712a5da824bc9b88c4c67c41e0039319acfd63f9..cb8261af12d24b244c4d33856a5dfd6b8df3dea5 100644 (file)
@@ -758,8 +758,11 @@ inline namespace v14_2_0 {
     void set_chunk(uint64_t src_offset, uint64_t src_length, const IoCtx& tgt_ioctx,
                    std::string tgt_oid, uint64_t tgt_offset, int flag = 0);
     /**
-     * flush a manifest tier object to backing tier; will block racing
-     * updates.
+     * flush a manifest tier object to backing tier, performing deduplication;
+     * will block racing updates.
+     *
+     * Invoking tier_flush() implicitly makes a manifest object even if
+     * the target object is not manifest. 
      */
     void tier_flush();
     /**
index 4fee24bb090fccf9ce8397101faf4d68e286b75b..1f23145570c7ca82ef3dceea1a6899280c0ec561 100644 (file)
@@ -7388,13 +7388,9 @@ int PrimaryLogPG::do_osd_ops(OpContext *ctx, vector<OSDOp>& ops)
          result = -EOPNOTSUPP;
          break;
        }
-       if (!obs.oi.has_manifest()) {
-         result = 0;
-         break;
-       }
 
-       if (oi.is_dirty()) {
-         result = start_flush(ctx->op, ctx->obc, true, NULL, std::nullopt);
+       if (oi.is_dirty() || !obs.oi.has_manifest()) {
+         result = start_flush(ctx->op, ctx->obc, true, NULL, std::nullopt, true);
          if (result == -EINPROGRESS)
            result = -EAGAIN;
        } else {
@@ -10675,6 +10671,11 @@ int PrimaryLogPG::finish_set_dedup(hobject_t oid, int r, ceph_tid_t tid, uint64_
     ctx->new_obs = obc->obs;
     ctx->new_obs.oi.clear_flag(object_info_t::FLAG_DIRTY);
     --ctx->delta_stats.num_objects_dirty;
+    if (!ctx->obs->oi.has_manifest()) {
+      ctx->delta_stats.num_objects_manifest++;
+      ctx->new_obs.oi.set_flag(object_info_t::FLAG_MANIFEST);
+      ctx->new_obs.oi.manifest.type = object_manifest_t::TYPE_CHUNKED;
+    }
 
     /* 
     * Let's assume that there is a manifest snapshotted object, and we issue tier_flush() to head.
@@ -10756,7 +10757,8 @@ int PrimaryLogPG::finish_set_manifest_refcount(hobject_t oid, int r, ceph_tid_t
 int PrimaryLogPG::start_flush(
   OpRequestRef op, ObjectContextRef obc,
   bool blocking, hobject_t *pmissing,
-  std::optional<std::function<void()>> &&on_flush)
+  std::optional<std::function<void()>> &&on_flush,
+  bool force_dedup)
 {
   const object_info_t& oi = obc->obs.oi;
   const hobject_t& soid = oi.soid;
@@ -10778,7 +10780,8 @@ int PrimaryLogPG::start_flush(
     snapset = obc->ssc->snapset;
   }
 
-  if (obc->obs.oi.has_manifest() && obc->obs.oi.manifest.is_chunked()) {
+  if ((obc->obs.oi.has_manifest() && obc->obs.oi.manifest.is_chunked())
+      || force_dedup) {
     // current dedup tier only supports blocking operation
     if (!blocking) {
       return -EOPNOTSUPP;
@@ -10854,7 +10857,8 @@ int PrimaryLogPG::start_flush(
     osd->objecter->op_cancel(tids, -ECANCELED);
   }
 
-  if (obc->obs.oi.has_manifest() && obc->obs.oi.manifest.is_chunked()) {
+  if ((obc->obs.oi.has_manifest() && obc->obs.oi.manifest.is_chunked())
+      || force_dedup) {
     int r = start_dedup(op, obc);
     if (r != -EINPROGRESS) {
       if (blocking)
index 2605c992bca332f6939ca0aed1a5e4cd4bd0b83b..ca65cabfc40c255d25c08ef5781c4056eee0dc98 100644 (file)
@@ -1356,7 +1356,8 @@ protected:
   int start_flush(
     OpRequestRef op, ObjectContextRef obc,
     bool blocking, hobject_t *pmissing,
-    std::optional<std::function<void()>> &&on_flush);
+    std::optional<std::function<void()>> &&on_flush,
+    bool force_dedup = false);
   void finish_flush(hobject_t oid, ceph_tid_t tid, int r);
   int try_flush_mark_clean(FlushOpRef fop);
   void cancel_flush(FlushOpRef fop, bool requeue, std::vector<ceph_tid_t> *tids);
index 55e645fa79c6fd07f84b2306ccdf06a23c7b3999..1402c0f5bf783a58c7364f4823d6723f658fd72f 100644 (file)
@@ -1126,61 +1126,17 @@ int make_dedup_object(const po::variables_map &opts)
       return ret;
     }
 
-    /*
-     * TODO: add a better way to make an object a manifest object.  
-     * We're using set_chunk with an incorrect object here simply to make 
-     * the object a manifest object, the tier_flush() will remove
-     * it and replace it with the real contents.
-     */
-    // convert object to manifest object
     auto create_new_deduped_object =
-      [&chunk_io_ctx, &io_ctx](string object_name) -> int {
-
-      int ret = 0;
-      ObjectWriteOperation op;
-      bufferlist temp;
-      temp.append("temp");
-      op.write_full(temp);
-
-      auto gen_r_num = [] () -> string {
-       std::random_device rd;
-       std::mt19937 gen(rd());
-       std::uniform_int_distribution<uint64_t> dist;
-       uint64_t r_num = dist(gen);
-       return to_string(r_num);
-      };
-      string temp_oid = gen_r_num();
-      // create temp chunk object for set-chunk
-      ret = chunk_io_ctx.operate(temp_oid, &op);
-      if (ret == -EEXIST) {
-       // one more try
-       temp_oid = gen_r_num();
-       ret = chunk_io_ctx.operate(temp_oid, &op);
-      }
-      if (ret < 0) {
-       cerr << " operate fail : " << cpp_strerror(ret) << std::endl;
-       return ret;
-      }
-
-      // set-chunk to make manifest object
-      ObjectReadOperation chunk_op;
-      chunk_op.set_chunk(0, 4, chunk_io_ctx, temp_oid, 0,
-       CEPH_OSD_OP_FLAG_WITH_REFERENCE);
-      ret = io_ctx.operate(object_name, &chunk_op, NULL);
-      if (ret < 0) {
-       cerr << " set_chunk fail : " << cpp_strerror(ret) << std::endl;
-       return ret;
-      }
+      [&io_ctx](string object_name) -> int {
 
       // tier-flush to perform deduplication
       ObjectReadOperation flush_op;
       flush_op.tier_flush();
-      ret = io_ctx.operate(object_name, &flush_op, NULL);
+      int ret = io_ctx.operate(object_name, &flush_op, NULL);
       if (ret < 0) {
        cerr << " tier_flush fail : " << cpp_strerror(ret) << std::endl;
        return ret;
       }
-
       // tier-evict
       ObjectReadOperation evict_op;
       evict_op.tier_evict();