From: Sage Weil Date: Wed, 6 Sep 2017 02:46:48 +0000 (-0400) Subject: mon/OSDMonitor: improve crush map validation X-Git-Tag: v12.2.2~117^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=refs%2Fpull%2F17805%2Fhead;p=ceph.git mon/OSDMonitor: improve crush map validation - move into OSDMap method - ensure that rules exist for each pool - ensure pool type matches rule type - ensure rule mask min/max size cover the pool size Signed-off-by: Sage Weil (cherry picked from commit 8f8f0b25058ff7319ec9d023f0eceb5832d0ecff) --- diff --git a/src/mon/OSDMonitor.cc b/src/mon/OSDMonitor.cc index 831dd0cb2ede..d92443c159ff 100644 --- a/src/mon/OSDMonitor.cc +++ b/src/mon/OSDMonitor.cc @@ -7655,16 +7655,9 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op, goto reply; } - const auto& osdmap_pools = osdmap.get_pools(); - for (auto pit = osdmap_pools.begin(); pit != osdmap_pools.end(); ++pit) { - const int64_t pool_id = pit->first; - const pg_pool_t &pool = pit->second; - int ruleno = pool.get_crush_rule(); - if (!crush.rule_exists(ruleno)) { - ss << " the crush rule no "<< ruleno << " for pool id " << pool_id << " is in use"; - err = -EINVAL; - goto reply; - } + err = osdmap.validate_crush_rules(&crush, &ss); + if (err < 0) { + goto reply; } if (g_conf->mon_osd_crush_smoke_test) { diff --git a/src/osd/OSDMap.cc b/src/osd/OSDMap.cc index e8b1d5667669..4d98b2e07261 100644 --- a/src/osd/OSDMap.cc +++ b/src/osd/OSDMap.cc @@ -3293,6 +3293,37 @@ bool OSDMap::crush_rule_in_use(int rule_id) const return false; } +int OSDMap::validate_crush_rules(CrushWrapper *newcrush, + ostream *ss) const +{ + for (auto& i : pools) { + auto& pool = i.second; + int ruleno = pool.get_crush_rule(); + if (!newcrush->rule_exists(ruleno)) { + *ss << "pool " << i.first << " references crush_rule " << ruleno + << " but it is not present"; + return -EINVAL; + } + if (newcrush->get_rule_mask_ruleset(ruleno) != ruleno) { + *ss << "rule " << ruleno << " mask ruleset does not match rule id"; + return -EINVAL; + } + if (newcrush->get_rule_mask_type(ruleno) != (int)pool.get_type()) { + *ss << "pool " << i.first << " type does not match rule " << ruleno; + return -EINVAL; + } + if (pool.get_size() < (int)newcrush->get_rule_mask_min_size(ruleno) || + pool.get_size() > (int)newcrush->get_rule_mask_max_size(ruleno)) { + *ss << "pool " << i.first << " size " << pool.get_size() << " does not" + << " fall within rule " << ruleno + << " min_size " << newcrush->get_rule_mask_min_size(ruleno) + << " and max_size " << newcrush->get_rule_mask_max_size(ruleno); + return -EINVAL; + } + } + return 0; +} + int OSDMap::build_simple_optioned(CephContext *cct, epoch_t e, uuid_d &fsid, int nosd, int pg_bits, int pgp_bits, bool default_pool) diff --git a/src/osd/OSDMap.h b/src/osd/OSDMap.h index 65348d5d3a67..6ba56511823d 100644 --- a/src/osd/OSDMap.h +++ b/src/osd/OSDMap.h @@ -1344,6 +1344,8 @@ public: bool crush_rule_in_use(int rule_id) const; + int validate_crush_rules(CrushWrapper *crush, ostream *ss) const; + void clear_temp() { pg_temp->clear(); primary_temp->clear();