From ea749df517f72c1c46b373ba712ed2373272bed3 Mon Sep 17 00:00:00 2001 From: myoungwon oh Date: Sun, 1 May 2022 22:48:14 +0900 Subject: [PATCH] osd/,rados/: modify TIER_FLUSH to implicitly make an object a manifest object 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 --- qa/workunits/rados/test_dedup_tool.sh | 11 ++++++ src/include/rados/librados.hpp | 7 ++-- src/osd/PrimaryLogPG.cc | 22 +++++++----- src/osd/PrimaryLogPG.h | 3 +- src/tools/ceph_dedup_tool.cc | 48 ++------------------------- 5 files changed, 33 insertions(+), 58 deletions(-) diff --git a/qa/workunits/rados/test_dedup_tool.sh b/qa/workunits/rados/test_dedup_tool.sh index ecfaeb1411e..a42ace542c6 100755 --- a/qa/workunits/rados/test_dedup_tool.sh +++ b/qa/workunits/rados/test_dedup_tool.sh @@ -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 diff --git a/src/include/rados/librados.hpp b/src/include/rados/librados.hpp index 712a5da824b..cb8261af12d 100644 --- a/src/include/rados/librados.hpp +++ b/src/include/rados/librados.hpp @@ -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(); /** diff --git a/src/osd/PrimaryLogPG.cc b/src/osd/PrimaryLogPG.cc index 4fee24bb090..1f23145570c 100644 --- a/src/osd/PrimaryLogPG.cc +++ b/src/osd/PrimaryLogPG.cc @@ -7388,13 +7388,9 @@ int PrimaryLogPG::do_osd_ops(OpContext *ctx, vector& 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> &&on_flush) + std::optional> &&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) diff --git a/src/osd/PrimaryLogPG.h b/src/osd/PrimaryLogPG.h index 2605c992bca..ca65cabfc40 100644 --- a/src/osd/PrimaryLogPG.h +++ b/src/osd/PrimaryLogPG.h @@ -1356,7 +1356,8 @@ protected: int start_flush( OpRequestRef op, ObjectContextRef obc, bool blocking, hobject_t *pmissing, - std::optional> &&on_flush); + std::optional> &&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 *tids); diff --git a/src/tools/ceph_dedup_tool.cc b/src/tools/ceph_dedup_tool.cc index 55e645fa79c..1402c0f5bf7 100644 --- a/src/tools/ceph_dedup_tool.cc +++ b/src/tools/ceph_dedup_tool.cc @@ -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 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(); -- 2.39.5