From: Kefu Chai Date: Sat, 30 Jan 2016 08:35:27 +0000 (+0800) Subject: rados: add "list-inconsistent-obj" cmd X-Git-Tag: v10.1.0~303^2~1 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=8018eab344ff7c8e96715c1a873128f31d9fcea3;p=ceph.git rados: add "list-inconsistent-obj" cmd to list inconsistent objects of a given PG, this command exposes get_inconsistent_objects() rados API to user. Signed-off-by: Kefu Chai --- diff --git a/src/tools/rados/rados.cc b/src/tools/rados/rados.cc index d5848859d683..4d314ebe1f34 100644 --- a/src/tools/rados/rados.cc +++ b/src/tools/rados/rados.cc @@ -145,6 +145,7 @@ void usage(ostream& out) "\n" "SCRUB AND REPAIR:\n" " list-inconsistent-pg list inconsistent PGs in given pool\n" +" list-inconsistent-obj list inconsistent objects in given pg\n" "\n" "CACHE POOLS: (for testing/development only)\n" " cache-flush flush cache pool object (blocking)\n" @@ -1240,6 +1241,151 @@ static int do_get_inconsistent_pg_cmd(const std::vector &nargs, return 0; } +static void dump_shard(const shard_info_t& shard, + const inconsistent_obj_t& inc, + Formatter &f) +{ + f.dump_bool("missing", shard.has_shard_missing()); + if (shard.has_shard_missing()) { + return; + } + f.dump_bool("read_error", shard.has_read_error()); + f.dump_bool("data_digest_mismatch", shard.has_data_digest_mismatch()); + f.dump_bool("omap_digest_mismatch", shard.has_omap_digest_mismatch()); + f.dump_bool("size_mismatch", shard.has_size_mismatch()); + if (!shard.has_read_error()) { + f.dump_bool("data_digest_mismatch_oi", shard.has_data_digest_mismatch_oi()); + f.dump_bool("omap_digest_mismatch_oi", shard.has_omap_digest_mismatch_oi()); + f.dump_bool("size_mismatch_oi", shard.has_size_mismatch_oi()); + } + f.dump_unsigned("size", shard.size); + if (shard.omap_digest_present) { + f.dump_format("omap_digest", "0x%08x", shard.omap_digest); + } + if (shard.data_digest_present) { + f.dump_format("data_digest", "0x%08x", shard.data_digest); + } + if (inc.has_attr_mismatch()) { + f.open_object_section("attrs"); + for (auto kv : shard.attrs) { + f.open_object_section("attr"); + f.dump_string("name", kv.first); + bufferlist b64; + kv.second.encode_base64(b64); + string v(b64.c_str(), b64.length()); + f.dump_string("value", v); + f.close_section(); + } + f.close_section(); + } +} + +static void dump_object_id(const object_id_t& object, + Formatter &f) +{ + f.dump_string("name", object.name); + f.dump_string("nspace", object.nspace); + f.dump_string("locator", object.locator); + switch (object.snap) { + case CEPH_NOSNAP: + f.dump_string("snap", "head"); + break; + case CEPH_SNAPDIR: + f.dump_string("snap", "snapdir"); + break; + default: + f.dump_format("snap", "0x%08x", object.snap); + break; + } +} + +static void dump_inconsistent(const inconsistent_obj_t& inc, + Formatter &f) +{ + f.open_object_section("object"); + dump_object_id(inc.object, f); + f.close_section(); + f.dump_bool("missing", inc.has_shard_missing()); + f.dump_bool("stat_err", inc.has_stat_error()); + f.dump_bool("read_err", inc.has_read_error()); + f.dump_bool("data_digest_mismatch", inc.has_data_digest_mismatch()); + f.dump_bool("omap_digest_mismatch", inc.has_omap_digest_mismatch()); + f.dump_bool("size_mismatch", inc.has_size_mismatch()); + f.dump_bool("attr_mismatch", inc.has_attr_mismatch()); + f.open_array_section("shards"); + for (auto osd_shard : inc.shards) { + f.open_object_section("shard"); + f.dump_int("osd", osd_shard.first); + dump_shard(osd_shard.second, inc, f); + f.close_section(); + } + f.close_section(); + f.close_section(); +} + +// dispatch the call by type +static int do_get_inconsistent(Rados& rados, + const PlacementGroup& pg, + const librados::object_id_t &start, + unsigned max_return, + AioCompletion *c, + std::vector* objs, + uint32_t* interval) +{ + return rados.get_inconsistent_objects(pg, start, max_return, c, + objs, interval); +} + +template +static int do_get_inconsistent_cmd(const std::vector &nargs, + Rados& rados, + Formatter& formatter) +{ + if (nargs.size() < 2) { + usage_exit(); + } + PlacementGroup pg; + int ret = 0; + ret = pg.parse(nargs[1]); + if (!ret) { + cerr << "bad pg: " << nargs[1] << std::endl; + return ret; + } + + uint32_t interval = 0; + const unsigned max_item_num = 32; + for (librados::object_id_t start;;) { + std::vector items; + auto completion = librados::Rados::aio_create_completion(); + ret = do_get_inconsistent(rados, pg, start, max_item_num, completion, + &items, &interval); + completion->wait_for_safe(); + ret = completion->get_return_value(); + completion->release(); + if (ret == -EAGAIN) { + cerr << "interval#" << interval << " expired." << std::endl; + break; + } + if (start.name.empty()) { + formatter.open_array_section("inconsistents"); + } + for (auto& inc : items) { + formatter.open_object_section("inconsistent"); + dump_inconsistent(inc, formatter); + } + if (items.size() < max_item_num) { + formatter.close_section(); + break; + } + if (!items.empty()) { + start = items.back().object; + } + items.clear(); + } + formatter.flush(cout); + return ret; +} + /********************************************** **********************************************/ @@ -2865,6 +3011,11 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts, formatter = new JSONFormatter(pretty_format); } ret = do_get_inconsistent_pg_cmd(nargs, rados, *formatter); + } else if (strcmp(nargs[0], "list-inconsistent-obj") == 0) { + if (!formatter) { + formatter = new JSONFormatter(pretty_format); + } + ret = do_get_inconsistent_cmd(nargs, rados, *formatter); } else if (strcmp(nargs[0], "cache-flush") == 0) { if (!pool_name || nargs.size() < 2) usage_exit();