diff --git a/src/osd/OSDMap.h b/src/osd/OSDMap.h index a3acc0259cb..b44b2861766 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 71485729eb7..1d803830d4b 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(); }