From 7a9652b58ea70f9a484a135bde20d872616c5947 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Sun, 11 May 2014 13:36:03 -0700 Subject: [PATCH] mon: include 'max avail' in df output Include an estimate of the maximum writeable space for each pool. Note that this value is a conservative estimate for that pool based on the most-full OSD. It is also potentially misleading as it is the available space if *all* new data were written to this pool; one cannot (generally) add up the available space for all pools. Signed-off-by: Sage Weil --- src/mon/PGMonitor.cc | 59 +++++++++++++++++++++++++++++++++++++++++--- src/mon/PGMonitor.h | 6 ++++- 2 files changed, 61 insertions(+), 4 deletions(-) diff --git a/src/mon/PGMonitor.cc b/src/mon/PGMonitor.cc index 0e87c637e30aa..078202d0cbd20 100644 --- a/src/mon/PGMonitor.cc +++ b/src/mon/PGMonitor.cc @@ -1215,11 +1215,13 @@ inline string percentify(const float& a) { //void PGMonitor::dump_object_stat_sum(stringstream& ss, Formatter *f, void PGMonitor::dump_object_stat_sum(TextTable &tbl, Formatter *f, - object_stat_sum_t &sum, bool verbose) + object_stat_sum_t &sum, uint64_t avail, + bool verbose) { if (f) { f->dump_int("kb_used", SHIFT_ROUND_UP(sum.num_bytes, 10)); f->dump_int("bytes_used", sum.num_bytes); + f->dump_unsigned("max_avail", avail); f->dump_int("objects", sum.num_objects); if (verbose) { f->dump_int("dirty", sum.num_objects_dirty); @@ -1232,6 +1234,7 @@ void PGMonitor::dump_object_stat_sum(TextTable &tbl, Formatter *f, tbl << stringify(si_t(sum.num_bytes)); int64_t kb_used = SHIFT_ROUND_UP(sum.num_bytes, 10); tbl << percentify(((float)kb_used / pg_map.osd_sum.kb)*100); + tbl << si_t(avail); tbl << sum.num_objects; if (verbose) { tbl << stringify(si_t(sum.num_objects_dirty)) @@ -1241,6 +1244,22 @@ void PGMonitor::dump_object_stat_sum(TextTable &tbl, Formatter *f, } } +int64_t PGMonitor::get_rule_avail(OSDMap& osdmap, int ruleno) +{ + map wm; + int r = osdmap.crush->get_rule_weight_map(ruleno, &wm); + if (r < 0) + return r; + int64_t min = -1; + for (map::iterator p = wm.begin(); p != wm.end(); ++p) { + int64_t proj = (float)(pg_map.osd_sum.kb_avail * 1024ull) / + (double)p->second; + if (min < 0 || proj < min) + min = proj; + } + return min; +} + void PGMonitor::dump_pool_stats(stringstream &ss, Formatter *f, bool verbose) { TextTable tbl; @@ -1254,6 +1273,7 @@ void PGMonitor::dump_pool_stats(stringstream &ss, Formatter *f, bool verbose) tbl.define_column("CATEGORY", TextTable::LEFT, TextTable::LEFT); tbl.define_column("USED", TextTable::LEFT, TextTable::RIGHT); tbl.define_column("%%USED", TextTable::LEFT, TextTable::RIGHT); + tbl.define_column("MAX AVAIL", TextTable::LEFT, TextTable::RIGHT); tbl.define_column("OBJECTS", TextTable::LEFT, TextTable::RIGHT); if (verbose) { tbl.define_column("DIRTY", TextTable::LEFT, TextTable::RIGHT); @@ -1262,6 +1282,7 @@ void PGMonitor::dump_pool_stats(stringstream &ss, Formatter *f, bool verbose) } } + map avail_by_rule; OSDMap &osdmap = mon->osdmon()->osdmap; for (map::const_iterator p = osdmap.get_pools().begin(); p != osdmap.get_pools().end(); ++p) { @@ -1271,6 +1292,38 @@ void PGMonitor::dump_pool_stats(stringstream &ss, Formatter *f, bool verbose) string pool_name = osdmap.get_pool_name(pool_id); pool_stat_t &stat = pg_map.pg_pool_sum[pool_id]; + const pg_pool_t *pool = osdmap.get_pg_pool(pool_id); + int ruleno = osdmap.crush->find_rule(pool->get_crush_ruleset(), + pool->get_type(), + pool->get_size()); + uint64_t avail; + if (avail_by_rule.count(ruleno) == 0) { + avail = get_rule_avail(osdmap, ruleno); + avail_by_rule[ruleno] = avail; + } else { + avail = avail_by_rule[ruleno]; + } + switch (pool->get_type()) { + case pg_pool_t::TYPE_REPLICATED: + avail /= pool->get_size(); + break; + case pg_pool_t::TYPE_ERASURE: + { + const map& ecp = + osdmap.get_erasure_code_profile(pool->erasure_code_profile); + map::const_iterator pm = ecp.find("m"); + map::const_iterator pk = ecp.find("k"); + if (pm != ecp.end() && pk != ecp.end()) { + int k = atoi(pk->second.c_str()); + int m = atoi(pm->second.c_str()); + avail = avail * k / (m + k); + } + } + break; + default: + assert(0 == "unrecognized pool type"); + } + if (f) { f->open_object_section("pool"); f->dump_string("name", pool_name); @@ -1282,7 +1335,7 @@ void PGMonitor::dump_pool_stats(stringstream &ss, Formatter *f, bool verbose) if (verbose) tbl << "-"; } - dump_object_stat_sum(tbl, f, stat.stats.sum, verbose); + dump_object_stat_sum(tbl, f, stat.stats.sum, avail, verbose); if (f) f->close_section(); // stats else @@ -1301,7 +1354,7 @@ void PGMonitor::dump_pool_stats(stringstream &ss, Formatter *f, bool verbose) << "" << it->first; } - dump_object_stat_sum(tbl, f, it->second, verbose); + dump_object_stat_sum(tbl, f, it->second, avail, verbose); if (f) f->close_section(); // category name else diff --git a/src/mon/PGMonitor.h b/src/mon/PGMonitor.h index 09dd00946ac6c..f0073789bb5bd 100644 --- a/src/mon/PGMonitor.h +++ b/src/mon/PGMonitor.h @@ -146,7 +146,11 @@ class PGMonitor : public PaxosService { vector& args) const; void dump_object_stat_sum(TextTable &tbl, Formatter *f, - object_stat_sum_t &sum, bool verbose); + object_stat_sum_t &sum, + uint64_t avail, + bool verbose); + + int64_t get_rule_avail(OSDMap& osdmap, int ruleno); public: PGMonitor(Monitor *mn, Paxos *p, const string& service_name)