From: myoungwon oh Date: Sun, 10 Oct 2021 03:07:12 +0000 (+0900) Subject: tools/ceph_dedup_tool: add repair command X-Git-Tag: v17.1.0~362^2~3 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=62bfc8ba71ca488df3c95dec8b8cc2c07c116972;p=ceph.git tools/ceph_dedup_tool: add repair command Until now, ceph-dedup-tool only provides chunk-scrub ,which reports how many dangling references the object has, but there is no cli command to fix the reference mismach. Therefore, this commit adds repair command to correct detected reference mismatch. Signed-off-by: Myoungwon Oh --- diff --git a/src/tools/ceph_dedup_tool.cc b/src/tools/ceph_dedup_tool.cc index 2c117529e0f..99e36e0347e 100644 --- a/src/tools/ceph_dedup_tool.cc +++ b/src/tools/ceph_dedup_tool.cc @@ -133,7 +133,7 @@ ceph::mutex glock = ceph::make_mutex("glock"); void usage() { - cout << " usage: [--op ] [--pool ] " << std::endl; + cout << " usage: [--op ] [--pool ] " << std::endl; cout << " --object " << std::endl; cout << " --chunk-size chunk-size (byte) " << std::endl; cout << " --chunk-algorithm " << std::endl; @@ -767,7 +767,8 @@ int chunk_scrub_common(const std::map < std::string, std::string > &opts, } if (op_name == "chunk-get-ref" || - op_name == "chunk-put-ref") { + op_name == "chunk-put-ref" || + op_name == "chunk-repair") { string target_object_name; uint64_t pool_id; i = opts.find("object"); @@ -801,17 +802,83 @@ int chunk_scrub_common(const std::map < std::string, std::string > &opts, } hobject_t oid(sobject_t(target_object_name, CEPH_NOSNAP), "", hash, pool_id, ""); + auto run_op = [] (ObjectWriteOperation& op, hobject_t& oid, + string& object_name, IoCtx& chunk_io_ctx) -> int { + int ret = chunk_io_ctx.operate(object_name, &op); + if (ret < 0) { + cerr << " operate fail : " << cpp_strerror(ret) << std::endl; + } + return ret; + }; + ObjectWriteOperation op; if (op_name == "chunk-get-ref") { cls_cas_chunk_get_ref(op, oid); - } else { + ret = run_op(op, oid, object_name, chunk_io_ctx); + } else if (op_name == "chunk-put-ref") { cls_cas_chunk_put_ref(op, oid); + ret = run_op(op, oid, object_name, chunk_io_ctx); + } else if (op_name == "chunk-repair") { + ret = rados.ioctx_create2(pool_id, io_ctx); + if (ret < 0) { + cerr << oid << " ref " << pool_id + << ": referencing pool does not exist" << std::endl; + return ret; + } + int chunk_ref = -1, base_ref = -1; + // read object on chunk pool to know how many reference the object has + bufferlist t; + ret = chunk_io_ctx.getxattr(object_name, CHUNK_REFCOUNT_ATTR, t); + if (ret < 0) { + return ret; + } + chunk_refs_t refs; + auto p = t.cbegin(); + decode(refs, p); + if (refs.get_type() != chunk_refs_t::TYPE_BY_OBJECT) { + cerr << " does not supported chunk type " << std::endl; + return -1; + } + chunk_ref = + static_cast(refs.r.get())->by_object.count(oid); + if (chunk_ref < 0) { + cerr << object_name << " has no reference of " << target_object_name + << std::endl; + return chunk_ref; + } + cout << object_name << " has " << chunk_ref << " references for " + << target_object_name << std::endl; + + // read object on base pool to know the number of chunk object's references + base_ref = cls_cas_references_chunk(io_ctx, target_object_name, object_name); + if (base_ref < 0) { + if (base_ref == -ENOENT || base_ref == -ENOLINK) { + base_ref = 0; + } else { + return base_ref; + } + } + cout << target_object_name << " has " << base_ref << " references for " + << object_name << std::endl; + if (chunk_ref != base_ref) { + if (base_ref > chunk_ref) { + cerr << "error : " << target_object_name << "'s ref. < " << object_name + << "' ref. " << std::endl; + return -EINVAL; + } + cout << " fix dangling reference from " << chunk_ref << " to " << base_ref + << std::endl; + while (base_ref != chunk_ref) { + ObjectWriteOperation op; + cls_cas_chunk_put_ref(op, oid); + chunk_ref--; + ret = run_op(op, oid, object_name, chunk_io_ctx); + if (ret < 0) { + return ret; + } + } + } } - ret = chunk_io_ctx.operate(object_name, &op); - if (ret < 0) { - cerr << " operate fail : " << cpp_strerror(ret) << std::endl; - } - return ret; } else if (op_name == "dump-chunk-refs") { @@ -945,12 +1012,11 @@ int main(int argc, const char **argv) if (op_name == "estimate") { return estimate_dedup_ratio(opts, args); - } else if (op_name == "chunk-scrub") { - return chunk_scrub_common(opts, args); - } else if (op_name == "chunk-get-ref" || - op_name == "chunk-put-ref") { - return chunk_scrub_common(opts, args); - } else if (op_name == "dump-chunk-refs") { + } else if (op_name == "chunk-scrub" || + op_name == "chunk-get-ref" || + op_name == "chunk-put-ref" || + op_name == "chunk-repair" || + op_name == "dump-chunk-refs") { return chunk_scrub_common(opts, args); } else { cerr << "unrecognized op " << op_name << std::endl;