]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
osd/OSDMap: upmap: behave when current rule does not touch all osds
authorSage Weil <sage@redhat.com>
Mon, 1 May 2017 22:29:24 +0000 (17:29 -0500)
committerSage Weil <sage@redhat.com>
Mon, 1 May 2017 22:29:24 +0000 (17:29 -0500)
Previously we relied on identifying target osds of interest by seeing
which ones were touched by at least one PG.  We also assumed that their
target weight was their crush weight, which might not be the case if
multiple pool using different rules were in play.

Address this by using the get_rule_weight_osd_map.  This isn't perfect
as the PGs might be different "sizes," so one should still only calculate
upmap for multiple pools when the pools have "equivlanet" PGs.

Signed-off-by: Sage Weil <sage@redhat.com>
src/osd/OSDMap.cc

index 16f3774918a405f475c8dccc694619c467fb5756..1f69ac706444e17241bfa245429ee71e38e766fc 100644 (file)
@@ -3407,15 +3407,25 @@ int OSDMap::calc_pg_upmaps(
   CephContext *cct,
   float max_deviation,
   int max,
-  const set<int64_t>& only_pools,
+  const set<int64_t>& only_pools_orig,
   OSDMap::Incremental *pending_inc)
 {
+  set<int64_t> only_pools;
+  if (only_pools_orig.empty()) {
+    for (auto& i : pools) {
+      only_pools.insert(i.first);
+    }
+  } else {
+    only_pools = only_pools_orig;
+  }
   OSDMap tmp;
   tmp.deepish_copy_from(*this);
   int num_changed = 0;
   while (true) {
     map<int,set<pg_t>> pgs_by_osd;
     int total_pgs = 0;
+    float osd_weight_total = 0;
+    map<int,float> osd_weight;
     for (auto& i : pools) {
       if (!only_pools.empty() && !only_pools.count(i.first))
        continue;
@@ -3429,18 +3439,29 @@ int OSDMap::calc_pg_upmaps(
        }
       }
       total_pgs += i.second.get_size() * i.second.get_pg_num();
+
+      map<int,float> pmap;
+      int ruleno = tmp.crush->find_rule(i.second.get_crush_ruleset(),
+                                       i.second.get_type(),
+                                       i.second.get_size());
+      tmp.crush->get_rule_weight_osd_map(ruleno, &pmap);
+      ldout(cct,30) << __func__ << " pool " << i.first << " ruleno " << ruleno << dendl;
+      for (auto p : pmap) {
+       osd_weight[p.first] += p.second;
+       osd_weight_total += p.second;
+      }
     }
-    float osd_weight_total = 0;
-    map<int,float> osd_weight;
-    for (auto& i : pgs_by_osd) {
-      float w = crush->get_item_weightf(i.first);
-      osd_weight[i.first] = w;
-      osd_weight_total += w;
-      ldout(cct, 20) << " osd." << i.first << " weight " << w
-                    << " pgs " << i.second.size() << dendl;
+    for (auto& i : osd_weight) {
+      int pgs = 0;
+      auto p = pgs_by_osd.find(i.first);
+      if (p != pgs_by_osd.end())
+       pgs = p->second.size();
+      else
+       pgs_by_osd.emplace(i.first, set<pg_t>());
+      ldout(cct, 20) << " osd." << i.first << " weight " << i.second
+                    << " pgs " << pgs << dendl;
     }
 
-    // NOTE: we assume we touch all osds with CRUSH!
     float pgs_per_weight = total_pgs / osd_weight_total;
     ldout(cct, 10) << " osd_weight_total " << osd_weight_total << dendl;
     ldout(cct, 10) << " pgs_per_weight " << pgs_per_weight << dendl;