From: Sage Weil Date: Tue, 4 Feb 2014 00:19:07 +0000 (-0800) Subject: osdmaptool: add --test-map-pgs mode X-Git-Tag: v0.78~219^2~5 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=7f1b12f2ef97822e579425b9403b500c3c38ba2a;p=ceph.git osdmaptool: add --test-map-pgs mode This command will map all pgs from all pools (or just one pool) to osds and summarize the placement and calculate the actual standard deviation and the expected value. Signed-off-by: Sage Weil --- diff --git a/src/osd/OSDMap.h b/src/osd/OSDMap.h index a3acc0259cb8..b44b28617669 100644 --- a/src/osd/OSDMap.h +++ b/src/osd/OSDMap.h @@ -712,6 +712,11 @@ public: bool crush_ruleset_in_use(int ruleset) const; + void clear_temp() { + pg_temp->clear(); + primary_temp->clear(); + } + private: void print_osd_line(int cur, ostream *out, Formatter *f) const; public: diff --git a/src/tools/osdmaptool.cc b/src/tools/osdmaptool.cc index 71485729eb70..1d803830d4b9 100644 --- a/src/tools/osdmaptool.cc +++ b/src/tools/osdmaptool.cc @@ -34,6 +34,9 @@ void usage() cout << " usage: [--print] [--createsimple [--clobber] [--pg_bits ]] " << std::endl; cout << " --export-crush write osdmap's crush map to " << std::endl; cout << " --import-crush replace osdmap's crush map with " << std::endl; + cout << " --test-map-pgs map all pgs" << std::endl; + cout << " --mark-up-in mark osds up and in (but do not persist)" << std::endl; + cout << " --clear-temp clear pg_temp and primary_temp" << std::endl; cout << " --test-map-pg map a pgid to osds" << std::endl; cout << " --test-map-object [--pool ] map an object to osds" << std::endl; @@ -68,6 +71,10 @@ int main(int argc, const char **argv) int range_first = -1; int range_last = -1; int pool = 0; + bool mark_up_in = false; + bool clear_temp = false; + bool test_map_pgs = false; + int test_pool = -1; std::string val; std::ostringstream err; @@ -90,6 +97,13 @@ int main(int argc, const char **argv) createsimple = true; } else if (ceph_argparse_flag(args, i, "--create-from-conf", (char*)NULL)) { create_from_conf = true; + } else if (ceph_argparse_flag(args, i, "--mark-up-in", (char*)NULL)) { + mark_up_in = true; + } else if (ceph_argparse_flag(args, i, "--clear-temp", (char*)NULL)) { + clear_temp = true; + } else if (ceph_argparse_flag(args, i, "--test-map-pgs", (char*)NULL)) { + test_map_pgs = true; + } else if (ceph_argparse_withint(args, i, &test_pool, &err, "--pool", (char*)NULL)) { } else if (ceph_argparse_flag(args, i, "--clobber", (char*)NULL)) { clobber = true; } else if (ceph_argparse_withint(args, i, &pg_bits, &err, "--pg_bits", (char*)NULL)) { @@ -197,6 +211,20 @@ int main(int argc, const char **argv) modified = true; } + if (mark_up_in) { + cout << "marking all OSDs up and in" << std::endl; + int n = osdmap.get_max_osd(); + for (int i=0; iadjust_item_weightf(g_ceph_context, i, 1.0); + } + } + if (clear_temp) { + cout << "clearing pg/primary temp" << std::endl; + osdmap.clear_temp(); + } + if (!import_crush.empty()) { bufferlist cbl; std::string error; @@ -275,6 +303,97 @@ int main(int argc, const char **argv) << ") acting (" << acting << ", p" << acting_primary << ")" << std::endl; } + if (test_map_pgs) { + int n = osdmap.get_max_osd(); + vector count(n, 0); + vector first_count(n, 0); + vector primary_count(n, 0); + vector size(30, 0); + const map& pools = osdmap.get_pools(); + for (map::const_iterator p = pools.begin(); + p != pools.end(); ++p) { + if (test_pool >= 0 && p->first != test_pool) + continue; + cout << "pool " << p->first + << " pg_num " << p->second.get_pg_num() << std::endl; + for (unsigned i = 0; i < p->second.get_pg_num(); ++i) { + pg_t pgid = pg_t(i, p->first); + + vector osds; + int primary; + osdmap.pg_to_acting_osds(pgid, &osds, &primary); + size[osds.size()]++; + + for (unsigned i=0; i= 0) + primary_count[primary]++; + } + } + + uint64_t total = 0; + int in = 0; + int min_osd = -1; + int max_osd = -1; + cout << "#osd\tcount\tfirst\tprimary\tc wt\twt\n"; + for (int i=0; iget_item_weight(i) <= 0) + continue; + in++; + cout << "osd." << i + << "\t" << count[i] + << "\t" << first_count[i] + << "\t" << primary_count[i] + << "\t" << osdmap.crush->get_item_weightf(i) + << "\t" << osdmap.get_weightf(i) + << std::endl; + total += count[i]; + if (count[i] && + (min_osd < 0 || + count[i] < count[min_osd])) + min_osd = i; + if (count[i] && + (max_osd < 0 || + count[i] > count[max_osd])) + max_osd = i; + + } + uint64_t avg = total / in; + double dev = 0; + for (int i=0; iget_item_weight(i) <= 0) + continue; + dev += (avg - count[i]) * (avg - count[i]); + } + dev /= in; + dev = sqrt(dev); + + //double edev = sqrt(pgavg) * (double)avg / pgavg; + double edev = sqrt((double)total / (double)in * (1.0 - (1.0 / (double)in))); + cout << " in " << in << std::endl; + cout << " avg " << avg + << " stddev " << dev + << " (" << (dev/avg) << "x)" + << " (expected " << edev << " " << (edev/avg) << "x))" + << std::endl; + + if (min_osd >= 0) + cout << " min osd." << min_osd << " " << count[min_osd] << std::endl; + if (max_osd >= 0) + cout << " max osd." << max_osd << " " << count[max_osd] << std::endl; + + for (int i=0; i<4; i++) { + cout << "size " << i << "\t" << size[i] << std::endl; + } + } if (test_crush) { int pass = 0; while (1) { @@ -308,7 +427,8 @@ int main(int argc, const char **argv) if (!print && !print_json && !tree && !modified && export_crush.empty() && import_crush.empty() && - test_map_pg.empty() && test_map_object.empty()) { + test_map_pg.empty() && test_map_object.empty() && + !test_map_pgs) { cerr << me << ": no action specified?" << std::endl; usage(); }