From: Sage Weil Date: Fri, 2 Mar 2018 03:30:07 +0000 (-0600) Subject: osd/PG: MissingLoc: track location counts by upset and other X-Git-Tag: v13.1.0~565^2~6 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=eddf510e734b8bdded271350c0b00428669559ff;p=ceph.git osd/PG: MissingLoc: track location counts by upset and other For every object in missing_loc, calculate how many known locations are in the upset and all others, and call that loc_count_t. Keep a map of loc_count_t to the number of missing objects with that distribution. Signed-off-by: Sage Weil Signed-off-by: David Zafman --- diff --git a/src/osd/PG.cc b/src/osd/PG.cc index ee65daf2a3a..f6a6292c7f0 100644 --- a/src/osd/PG.cc +++ b/src/osd/PG.cc @@ -588,6 +588,9 @@ bool PG::search_for_missing( return found_missing; } + +// MissingLoc + bool PG::MissingLoc::readable_with_acting( const hobject_t &hoid, const set &acting) const { @@ -626,7 +629,16 @@ void PG::MissingLoc::add_batch_sources_info( } if (i->second.is_delete()) continue; + + auto p = missing_loc.find(i->first); + if (p == missing_loc.end()) { + p = missing_loc.emplace(i->first, set()).first; + } else { + _dec_count(p->second); + } missing_loc[i->first].insert(sources.begin(), sources.end()); + _inc_count(p->second); + if (!sources_updated) { missing_loc_sources.insert(sources.begin(), sources.end()); sources_updated = true; @@ -695,7 +707,17 @@ bool PG::MissingLoc::add_source_info( ldout(pg->cct, 10) << "search_for_missing " << soid << " " << need << " is on osd." << fromosd << dendl; - missing_loc[soid].insert(fromosd); + { + auto p = missing_loc.find(soid); + if (p == missing_loc.end()) { + p = missing_loc.emplace(soid, set()).first; + } else { + _dec_count(p->second); + } + p->second.insert(fromosd); + _inc_count(p->second); + } + if (!sources_updated) { missing_loc_sources.insert(fromosd); sources_updated = true; @@ -708,6 +730,55 @@ bool PG::MissingLoc::add_source_info( return found_missing; } +void PG::MissingLoc::check_recovery_sources(const OSDMapRef& osdmap) +{ + set now_down; + for (set::iterator p = missing_loc_sources.begin(); + p != missing_loc_sources.end(); + ) { + if (osdmap->is_up(p->osd)) { + ++p; + continue; + } + ldout(pg->cct, 10) << __func__ << " source osd." << *p << " now down" << dendl; + now_down.insert(*p); + missing_loc_sources.erase(p++); + } + + if (now_down.empty()) { + ldout(pg->cct, 10) << __func__ << " no source osds (" << missing_loc_sources << ") went down" << dendl; + } else { + ldout(pg->cct, 10) << __func__ << " sources osds " << now_down << " now down, remaining sources are " + << missing_loc_sources << dendl; + + // filter missing_loc + map>::iterator p = missing_loc.begin(); + while (p != missing_loc.end()) { + set::iterator q = p->second.begin(); + bool changed = false; + while (q != p->second.end()) { + if (now_down.count(*q)) { + if (!changed) { + changed = true; + _dec_count(p->second); + } + p->second.erase(q++); + } else { + ++q; + } + } + if (p->second.empty()) { + missing_loc.erase(p++); + } else { + if (changed) { + _inc_count(p->second); + } + ++p; + } + } + } +} + void PG::discover_all_missing(map > &query_map) { auto &missing = pg_log.get_missing(); @@ -1838,6 +1909,7 @@ void PG::activate(ObjectStore::Transaction& t, complete_shards.insert(*i); } } + // If necessary, create might_have_unfound to help us find our unfound objects. // NOTE: It's important that we build might_have_unfound before trimming the // past intervals. @@ -5808,6 +5880,9 @@ ostream& operator<<(ostream& out, const PG& pg) out << " u=" << unfound; } } + if (!pg.is_clean()) { + out << " mbc=" << pg.missing_loc.get_missing_by_count(); + } if (!pg.snap_trimq.empty()) { out << " trimq="; // only show a count if the set is large diff --git a/src/osd/PG.h b/src/osd/PG.h index a167e75bbe0..ca89dcff038 100644 --- a/src/osd/PG.h +++ b/src/osd/PG.h @@ -24,6 +24,7 @@ #include #include #include +#include #include "include/memory.h" #include "include/mempool.h" @@ -602,17 +603,72 @@ protected: } ghobject_t pgmeta_oid; + // ------------------ + // MissingLoc + class MissingLoc { + public: + // a loc_count indicates how many locations we know in each of + // these distinct sets + struct loc_count_t { + int up = 0; //< up + int other = 0; //< other + + friend bool operator<(const loc_count_t& l, + const loc_count_t& r) { + return (l.up < r.up || + (l.up == r.up && + (l.other < r.other))); + } + friend ostream& operator<<(ostream& out, const loc_count_t& l) { + assert(l.up >= 0); + assert(l.other >= 0); + return out << "(" << l.up << "+" << l.other << ")"; + } + }; + + + private: + + loc_count_t _get_count(const set& shards) { + loc_count_t r; + for (auto s : shards) { + if (pg->upset.count(s)) { + r.up++; + } else { + r.other++; + } + } + return r; + } + map needs_recovery_map; map > missing_loc; set missing_loc_sources; + + // for every entry in missing_loc, we count how many of each type of shard we have, + // and maintain totals here. The sum of the values for this map will always equal + // missing_loc.size(). + map missing_by_count; + + void _inc_count(const set& s) { + ++missing_by_count[_get_count(s)]; + } + void _dec_count(const set& s) { + auto p = missing_by_count.find(_get_count(s)); + assert(p != missing_by_count.end()); + if (--p->second == 0) { + missing_by_count.erase(p); + } + } + PG *pg; set empty_set; public: boost::scoped_ptr is_readable; boost::scoped_ptr is_recoverable; explicit MissingLoc(PG *pg) - : pg(pg) {} + : pg(pg) { } void set_backend_predicates( IsPGReadablePredicate *_is_readable, IsPGRecoverablePredicate *_is_recoverable) { @@ -683,13 +739,26 @@ protected: needs_recovery_map.clear(); missing_loc.clear(); missing_loc_sources.clear(); + missing_by_count.clear(); } void add_location(const hobject_t &hoid, pg_shard_t location) { - missing_loc[hoid].insert(location); + auto p = missing_loc.find(hoid); + if (p == missing_loc.end()) { + p = missing_loc.emplace(hoid, set()).first; + } else { + _dec_count(p->second); + } + p->second.insert(location); + _inc_count(p->second); } void remove_location(const hobject_t &hoid, pg_shard_t location) { - missing_loc[hoid].erase(location); + auto p = missing_loc.find(hoid); + if (p != missing_loc.end()) { + _dec_count(p->second); + p->second.erase(location); + _inc_count(p->second); + } } void add_active_missing(const pg_missing_t &missing) { for (map::const_iterator i = @@ -738,7 +807,11 @@ protected: /// Call when hoid is no longer missing in acting set void recovered(const hobject_t &hoid) { needs_recovery_map.erase(hoid); - missing_loc.erase(hoid); + auto p = missing_loc.find(hoid); + if (p != missing_loc.end()) { + _dec_count(p->second); + missing_loc.erase(p); + } } /// Call to update structures for hoid after a change @@ -788,6 +861,7 @@ protected: !i.second.is_missing(hoid)) mliter->second.insert(i.first); } + _inc_count(mliter->second); } const set &get_locations(const hobject_t &hoid) const { @@ -800,6 +874,9 @@ protected: const map &get_needs_recovery() const { return needs_recovery_map; } + const map &get_missing_by_count() const { + return missing_by_count; + } } missing_loc; PastIntervals past_intervals; diff --git a/src/osd/PrimaryLogPG.cc b/src/osd/PrimaryLogPG.cc index 874f61c0bfd..44f0f0a1a02 100644 --- a/src/osd/PrimaryLogPG.cc +++ b/src/osd/PrimaryLogPG.cc @@ -11829,46 +11829,6 @@ void PrimaryLogPG::check_recovery_sources(const OSDMapRef& osdmap) } } -void PG::MissingLoc::check_recovery_sources(const OSDMapRef& osdmap) -{ - set now_down; - for (set::iterator p = missing_loc_sources.begin(); - p != missing_loc_sources.end(); - ) { - if (osdmap->is_up(p->osd)) { - ++p; - continue; - } - ldout(pg->cct, 10) << __func__ << " source osd." << *p << " now down" << dendl; - now_down.insert(*p); - missing_loc_sources.erase(p++); - } - - if (now_down.empty()) { - ldout(pg->cct, 10) << __func__ << " no source osds (" << missing_loc_sources << ") went down" << dendl; - } else { - ldout(pg->cct, 10) << __func__ << " sources osds " << now_down << " now down, remaining sources are " - << missing_loc_sources << dendl; - - // filter missing_loc - map>::iterator p = missing_loc.begin(); - while (p != missing_loc.end()) { - set::iterator q = p->second.begin(); - while (q != p->second.end()) - if (now_down.count(*q)) { - p->second.erase(q++); - } else { - ++q; - } - if (p->second.empty()) - missing_loc.erase(p++); - else - ++p; - } - } -} - - bool PrimaryLogPG::start_recovery_ops( uint64_t max, ThreadPool::TPHandle &handle,