]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
move the OSDUtilizationDumper code into OSDMap
authorGreg Farnum <gfarnum@redhat.com>
Sun, 11 Jun 2017 18:09:10 +0000 (11:09 -0700)
committerGreg Farnum <gfarnum@redhat.com>
Thu, 15 Jun 2017 00:02:45 +0000 (17:02 -0700)
Signed-off-by: Greg Farnum <gfarnum@redhat.com>
src/mon/OSDMonitor.cc
src/osd/OSDMap.cc
src/osd/OSDMap.h

index 1d2483ba7fcebbe39072034caedd31c1f4c0d2ec..8188dd33b75e6f8abef19ca4219a1b25947bbfc7 100644 (file)
@@ -571,323 +571,6 @@ void OSDMonitor::update_logger()
   mon->cluster_logger->set(l_cluster_osd_epoch, osdmap.get_epoch());
 }
 
-template <typename F>
-class OSDUtilizationDumper : public CrushTreeDumper::Dumper<F> {
-public:
-  typedef CrushTreeDumper::Dumper<F> Parent;
-
-  OSDUtilizationDumper(const CrushWrapper *crush, const OSDMap *osdmap_,
-                      const PGStatService *pgs_, bool tree_) :
-    Parent(crush),
-    osdmap(osdmap_),
-    pgs(pgs_),
-    tree(tree_),
-    average_util(average_utilization()),
-    min_var(-1),
-    max_var(-1),
-    stddev(0),
-    sum(0) {
-  }
-
-protected:
-  void dump_stray(F *f) {
-    for (int i = 0; i < osdmap->get_max_osd(); i++) {
-      if (osdmap->exists(i) && !this->is_touched(i))
-       dump_item(CrushTreeDumper::Item(i, 0, 0), f);
-    }
-  }
-
-  void dump_item(const CrushTreeDumper::Item &qi, F *f) override {
-    if (!tree && qi.is_bucket())
-      return;
-
-    float reweight = qi.is_bucket() ? -1 : osdmap->get_weightf(qi.id);
-    int64_t kb = 0, kb_used = 0, kb_avail = 0;
-    double util = 0;
-    if (get_bucket_utilization(qi.id, &kb, &kb_used, &kb_avail))
-      if (kb_used && kb)
-        util = 100.0 * (double)kb_used / (double)kb;
-
-    double var = 1.0;
-    if (average_util)
-      var = util / average_util;
-
-    size_t num_pgs = qi.is_bucket() ? 0 : pgs->get_num_pg_by_osd(qi.id);
-
-    dump_item(qi, reweight, kb, kb_used, kb_avail, util, var, num_pgs, f);
-
-    if (!qi.is_bucket() && reweight > 0) {
-      if (min_var < 0 || var < min_var)
-       min_var = var;
-      if (max_var < 0 || var > max_var)
-       max_var = var;
-
-      double dev = util - average_util;
-      dev *= dev;
-      stddev += reweight * dev;
-      sum += reweight;
-    }
-  }
-
-  virtual void dump_item(const CrushTreeDumper::Item &qi,
-                        float &reweight,
-                        int64_t kb,
-                        int64_t kb_used,
-                        int64_t kb_avail,
-                        double& util,
-                        double& var,
-                        const size_t num_pgs,
-                        F *f) = 0;
-
-  double dev() {
-    return sum > 0 ? sqrt(stddev / sum) : 0;
-  }
-
-  double average_utilization() {
-    int64_t kb = 0, kb_used = 0;
-    for (int i = 0; i < osdmap->get_max_osd(); i++) {
-      if (!osdmap->exists(i) || osdmap->get_weight(i) == 0)
-       continue;
-      int64_t kb_i, kb_used_i, kb_avail_i;
-      if (get_osd_utilization(i, &kb_i, &kb_used_i, &kb_avail_i)) {
-       kb += kb_i;
-       kb_used += kb_used_i;
-      }
-    }
-    return kb > 0 ? 100.0 * (double)kb_used / (double)kb : 0;
-  }
-
-  bool get_osd_utilization(int id, int64_t* kb, int64_t* kb_used,
-                          int64_t* kb_avail) const {
-    const osd_stat_t *p = pgs->get_osd_stat(id);
-    if (!p) return false;
-    *kb = p->kb;
-    *kb_used = p->kb_used;
-    *kb_avail = p->kb_avail;
-    return *kb > 0;
-  }
-
-  bool get_bucket_utilization(int id, int64_t* kb, int64_t* kb_used,
-                             int64_t* kb_avail) const {
-    if (id >= 0) {
-      if (osdmap->is_out(id)) {
-        *kb = 0;
-        *kb_used = 0;
-        *kb_avail = 0;
-        return true;
-      }
-      return get_osd_utilization(id, kb, kb_used, kb_avail);
-    }
-
-    *kb = 0;
-    *kb_used = 0;
-    *kb_avail = 0;
-
-    for (int k = osdmap->crush->get_bucket_size(id) - 1; k >= 0; k--) {
-      int item = osdmap->crush->get_bucket_item(id, k);
-      int64_t kb_i = 0, kb_used_i = 0, kb_avail_i = 0;
-      if (!get_bucket_utilization(item, &kb_i, &kb_used_i, &kb_avail_i))
-       return false;
-      *kb += kb_i;
-      *kb_used += kb_used_i;
-      *kb_avail += kb_avail_i;
-    }
-    return *kb > 0;
-  }
-
-protected:
-  const OSDMap *osdmap;
-  const PGStatService *pgs;
-  bool tree;
-  double average_util;
-  double min_var;
-  double max_var;
-  double stddev;
-  double sum;
-};
-
-class OSDUtilizationPlainDumper : public OSDUtilizationDumper<TextTable> {
-public:
-  typedef OSDUtilizationDumper<TextTable> Parent;
-
-  OSDUtilizationPlainDumper(const CrushWrapper *crush, const OSDMap *osdmap,
-                    const PGStatService *pgs, bool tree) :
-    Parent(crush, osdmap, pgs, tree) {}
-
-  void dump(TextTable *tbl) {
-    tbl->define_column("ID", TextTable::LEFT, TextTable::RIGHT);
-    tbl->define_column("WEIGHT", TextTable::LEFT, TextTable::RIGHT);
-    tbl->define_column("REWEIGHT", TextTable::LEFT, TextTable::RIGHT);
-    tbl->define_column("SIZE", TextTable::LEFT, TextTable::RIGHT);
-    tbl->define_column("USE", TextTable::LEFT, TextTable::RIGHT);
-    tbl->define_column("AVAIL", TextTable::LEFT, TextTable::RIGHT);
-    tbl->define_column("%USE", TextTable::LEFT, TextTable::RIGHT);
-    tbl->define_column("VAR", TextTable::LEFT, TextTable::RIGHT);
-    tbl->define_column("PGS", TextTable::LEFT, TextTable::RIGHT);
-    if (tree)
-      tbl->define_column("TYPE NAME", TextTable::LEFT, TextTable::LEFT);
-
-    Parent::dump(tbl);
-
-    dump_stray(tbl);
-
-    *tbl << "" << "" << "TOTAL"
-        << si_t(pgs->get_osd_sum().kb << 10)
-        << si_t(pgs->get_osd_sum().kb_used << 10)
-        << si_t(pgs->get_osd_sum().kb_avail << 10)
-        << lowprecision_t(average_util)
-        << ""
-        << TextTable::endrow;
-  }
-
-protected:
-  struct lowprecision_t {
-    float v;
-    explicit lowprecision_t(float _v) : v(_v) {}
-  };
-  friend std::ostream &operator<<(ostream& out, const lowprecision_t& v);
-
-  using OSDUtilizationDumper<TextTable>::dump_item;
-  void dump_item(const CrushTreeDumper::Item &qi,
-                        float &reweight,
-                        int64_t kb,
-                        int64_t kb_used,
-                        int64_t kb_avail,
-                        double& util,
-                        double& var,
-                        const size_t num_pgs,
-                        TextTable *tbl) override {
-    *tbl << qi.id
-        << weightf_t(qi.weight)
-        << weightf_t(reweight)
-        << si_t(kb << 10)
-        << si_t(kb_used << 10)
-        << si_t(kb_avail << 10)
-        << lowprecision_t(util)
-        << lowprecision_t(var);
-
-    if (qi.is_bucket()) {
-      *tbl << "-";
-    } else {
-      *tbl << num_pgs;
-    }
-
-    if (tree) {
-      ostringstream name;
-      for (int k = 0; k < qi.depth; k++)
-       name << "    ";
-      if (qi.is_bucket()) {
-       int type = crush->get_bucket_type(qi.id);
-       name << crush->get_type_name(type) << " "
-            << crush->get_item_name(qi.id);
-      } else {
-       name << "osd." << qi.id;
-      }
-      *tbl << name.str();
-    }
-
-    *tbl << TextTable::endrow;
-  }
-
-public:
-  string summary() {
-    ostringstream out;
-    out << "MIN/MAX VAR: " << lowprecision_t(min_var)
-       << "/" << lowprecision_t(max_var) << "  "
-       << "STDDEV: " << lowprecision_t(dev());
-    return out.str();
-  }
-};
-
-ostream& operator<<(ostream& out,
-                   const OSDUtilizationPlainDumper::lowprecision_t& v)
-{
-  if (v.v < -0.01) {
-    return out << "-";
-  } else if (v.v < 0.001) {
-    return out << "0";
-  } else {
-    std::streamsize p = out.precision();
-    return out << std::fixed << std::setprecision(2) << v.v << std::setprecision(p);
-  }
-}
-
-class OSDUtilizationFormatDumper : public OSDUtilizationDumper<Formatter> {
-public:
-  typedef OSDUtilizationDumper<Formatter> Parent;
-
-  OSDUtilizationFormatDumper(const CrushWrapper *crush, const OSDMap *osdmap,
-                            const PGStatService *pgs, bool tree) :
-    Parent(crush, osdmap, pgs, tree) {}
-
-  void dump(Formatter *f) {
-    f->open_array_section("nodes");
-    Parent::dump(f);
-    f->close_section();
-
-    f->open_array_section("stray");
-    dump_stray(f);
-    f->close_section();
-  }
-
-protected:
-  using OSDUtilizationDumper<Formatter>::dump_item;
-  void dump_item(const CrushTreeDumper::Item &qi,
-                        float &reweight,
-                        int64_t kb,
-                        int64_t kb_used,
-                        int64_t kb_avail,
-                        double& util,
-                        double& var,
-                        const size_t num_pgs,
-                        Formatter *f) override {
-    f->open_object_section("item");
-    CrushTreeDumper::dump_item_fields(crush, qi, f);
-    f->dump_float("reweight", reweight);
-    f->dump_int("kb", kb);
-    f->dump_int("kb_used", kb_used);
-    f->dump_int("kb_avail", kb_avail);
-    f->dump_float("utilization", util);
-    f->dump_float("var", var);
-    f->dump_unsigned("pgs", num_pgs);
-    CrushTreeDumper::dump_bucket_children(crush, qi, f);
-    f->close_section();
-  }
-
-public:
-  void summary(Formatter *f) {
-    f->open_object_section("summary");
-    f->dump_int("total_kb", pgs->get_osd_sum().kb);
-    f->dump_int("total_kb_used", pgs->get_osd_sum().kb_used);
-    f->dump_int("total_kb_avail", pgs->get_osd_sum().kb_avail);
-    f->dump_float("average_utilization", average_util);
-    f->dump_float("min_var", min_var);
-    f->dump_float("max_var", max_var);
-    f->dump_float("dev", dev());
-    f->close_section();
-  }
-};
-
-void OSDMonitor::print_utilization(ostream &out, Formatter *f, bool tree) const
-{
-  const CrushWrapper *crush = osdmap.crush.get();
-
-  if (f) {
-    f->open_object_section("df");
-    OSDUtilizationFormatDumper d(crush, &osdmap, mon->pgservice, tree);
-    d.dump(f);
-    d.summary(f);
-    f->close_section();
-    f->flush(out);
-  } else {
-    OSDUtilizationPlainDumper d(crush, &osdmap, mon->pgservice, tree);
-    TextTable tbl;
-    d.dump(&tbl);
-    out << tbl
-       << d.summary() << "\n";
-  }
-}
-
 void OSDMonitor::create_pending()
 {
   pending_inc = OSDMap::Incremental(osdmap.epoch+1);
@@ -4243,7 +3926,8 @@ bool OSDMonitor::preprocess_command(MonOpRequestRef op)
   } else if (prefix == "osd df") {
     string method;
     cmd_getval(g_ceph_context, cmdmap, "output_method", method);
-    print_utilization(ds, f ? f.get() : NULL, method == "tree");
+    print_osd_utilization(osdmap, mon->pgservice, ds,
+                         f ? f.get() : NULL, method == "tree");
     rdata.append(ds);
   } else if (prefix == "osd getmaxosd") {
     if (f) {
index c63bc6d04eac0d830758f65c14b3cc266c4bf6cb..67f9e5cd1d7f132b98a3e3f251ec4097b0d7054f 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "crush/CrushTreeDumper.h"
 #include "common/Clock.h"
+#include "mon/PGStatService.h"
  
 #define dout_subsys ceph_subsys_osd
 
@@ -3908,3 +3909,323 @@ int OSDMap::get_osds_by_bucket_name(const string &name, set<int> *osds) const
 {
   return crush->get_leaves(name, osds);
 }
+
+template <typename F>
+class OSDUtilizationDumper : public CrushTreeDumper::Dumper<F> {
+public:
+  typedef CrushTreeDumper::Dumper<F> Parent;
+
+  OSDUtilizationDumper(const CrushWrapper *crush, const OSDMap *osdmap_,
+                      const PGStatService *pgs_, bool tree_) :
+    Parent(crush),
+    osdmap(osdmap_),
+    pgs(pgs_),
+    tree(tree_),
+    average_util(average_utilization()),
+    min_var(-1),
+    max_var(-1),
+    stddev(0),
+    sum(0) {
+  }
+
+protected:
+  void dump_stray(F *f) {
+    for (int i = 0; i < osdmap->get_max_osd(); i++) {
+      if (osdmap->exists(i) && !this->is_touched(i))
+       dump_item(CrushTreeDumper::Item(i, 0, 0), f);
+    }
+  }
+
+  void dump_item(const CrushTreeDumper::Item &qi, F *f) override {
+    if (!tree && qi.is_bucket())
+      return;
+
+    float reweight = qi.is_bucket() ? -1 : osdmap->get_weightf(qi.id);
+    int64_t kb = 0, kb_used = 0, kb_avail = 0;
+    double util = 0;
+    if (get_bucket_utilization(qi.id, &kb, &kb_used, &kb_avail))
+      if (kb_used && kb)
+        util = 100.0 * (double)kb_used / (double)kb;
+
+    double var = 1.0;
+    if (average_util)
+      var = util / average_util;
+
+    size_t num_pgs = qi.is_bucket() ? 0 : pgs->get_num_pg_by_osd(qi.id);
+
+    dump_item(qi, reweight, kb, kb_used, kb_avail, util, var, num_pgs, f);
+
+    if (!qi.is_bucket() && reweight > 0) {
+      if (min_var < 0 || var < min_var)
+       min_var = var;
+      if (max_var < 0 || var > max_var)
+       max_var = var;
+
+      double dev = util - average_util;
+      dev *= dev;
+      stddev += reweight * dev;
+      sum += reweight;
+    }
+  }
+
+  virtual void dump_item(const CrushTreeDumper::Item &qi,
+                        float &reweight,
+                        int64_t kb,
+                        int64_t kb_used,
+                        int64_t kb_avail,
+                        double& util,
+                        double& var,
+                        const size_t num_pgs,
+                        F *f) = 0;
+
+  double dev() {
+    return sum > 0 ? sqrt(stddev / sum) : 0;
+  }
+
+  double average_utilization() {
+    int64_t kb = 0, kb_used = 0;
+    for (int i = 0; i < osdmap->get_max_osd(); i++) {
+      if (!osdmap->exists(i) || osdmap->get_weight(i) == 0)
+       continue;
+      int64_t kb_i, kb_used_i, kb_avail_i;
+      if (get_osd_utilization(i, &kb_i, &kb_used_i, &kb_avail_i)) {
+       kb += kb_i;
+       kb_used += kb_used_i;
+      }
+    }
+    return kb > 0 ? 100.0 * (double)kb_used / (double)kb : 0;
+  }
+
+  bool get_osd_utilization(int id, int64_t* kb, int64_t* kb_used,
+                          int64_t* kb_avail) const {
+    const osd_stat_t *p = pgs->get_osd_stat(id);
+    if (!p) return false;
+    *kb = p->kb;
+    *kb_used = p->kb_used;
+    *kb_avail = p->kb_avail;
+    return *kb > 0;
+  }
+
+  bool get_bucket_utilization(int id, int64_t* kb, int64_t* kb_used,
+                             int64_t* kb_avail) const {
+    if (id >= 0) {
+      if (osdmap->is_out(id)) {
+        *kb = 0;
+        *kb_used = 0;
+        *kb_avail = 0;
+        return true;
+      }
+      return get_osd_utilization(id, kb, kb_used, kb_avail);
+    }
+
+    *kb = 0;
+    *kb_used = 0;
+    *kb_avail = 0;
+
+    for (int k = osdmap->crush->get_bucket_size(id) - 1; k >= 0; k--) {
+      int item = osdmap->crush->get_bucket_item(id, k);
+      int64_t kb_i = 0, kb_used_i = 0, kb_avail_i = 0;
+      if (!get_bucket_utilization(item, &kb_i, &kb_used_i, &kb_avail_i))
+       return false;
+      *kb += kb_i;
+      *kb_used += kb_used_i;
+      *kb_avail += kb_avail_i;
+    }
+    return *kb > 0;
+  }
+
+protected:
+  const OSDMap *osdmap;
+  const PGStatService *pgs;
+  bool tree;
+  double average_util;
+  double min_var;
+  double max_var;
+  double stddev;
+  double sum;
+};
+
+
+class OSDUtilizationPlainDumper : public OSDUtilizationDumper<TextTable> {
+public:
+  typedef OSDUtilizationDumper<TextTable> Parent;
+
+  OSDUtilizationPlainDumper(const CrushWrapper *crush, const OSDMap *osdmap,
+                    const PGStatService *pgs, bool tree) :
+    Parent(crush, osdmap, pgs, tree) {}
+
+  void dump(TextTable *tbl) {
+    tbl->define_column("ID", TextTable::LEFT, TextTable::RIGHT);
+    tbl->define_column("WEIGHT", TextTable::LEFT, TextTable::RIGHT);
+    tbl->define_column("REWEIGHT", TextTable::LEFT, TextTable::RIGHT);
+    tbl->define_column("SIZE", TextTable::LEFT, TextTable::RIGHT);
+    tbl->define_column("USE", TextTable::LEFT, TextTable::RIGHT);
+    tbl->define_column("AVAIL", TextTable::LEFT, TextTable::RIGHT);
+    tbl->define_column("%USE", TextTable::LEFT, TextTable::RIGHT);
+    tbl->define_column("VAR", TextTable::LEFT, TextTable::RIGHT);
+    tbl->define_column("PGS", TextTable::LEFT, TextTable::RIGHT);
+    if (tree)
+      tbl->define_column("TYPE NAME", TextTable::LEFT, TextTable::LEFT);
+
+    Parent::dump(tbl);
+
+    dump_stray(tbl);
+
+    *tbl << "" << "" << "TOTAL"
+        << si_t(pgs->get_osd_sum().kb << 10)
+        << si_t(pgs->get_osd_sum().kb_used << 10)
+        << si_t(pgs->get_osd_sum().kb_avail << 10)
+        << lowprecision_t(average_util)
+        << ""
+        << TextTable::endrow;
+  }
+
+protected:
+  struct lowprecision_t {
+    float v;
+    explicit lowprecision_t(float _v) : v(_v) {}
+  };
+  friend std::ostream &operator<<(ostream& out, const lowprecision_t& v);
+
+  using OSDUtilizationDumper<TextTable>::dump_item;
+  void dump_item(const CrushTreeDumper::Item &qi,
+                        float &reweight,
+                        int64_t kb,
+                        int64_t kb_used,
+                        int64_t kb_avail,
+                        double& util,
+                        double& var,
+                        const size_t num_pgs,
+                        TextTable *tbl) override {
+    *tbl << qi.id
+        << weightf_t(qi.weight)
+        << weightf_t(reweight)
+        << si_t(kb << 10)
+        << si_t(kb_used << 10)
+        << si_t(kb_avail << 10)
+        << lowprecision_t(util)
+        << lowprecision_t(var);
+
+    if (qi.is_bucket()) {
+      *tbl << "-";
+    } else {
+      *tbl << num_pgs;
+    }
+
+    if (tree) {
+      ostringstream name;
+      for (int k = 0; k < qi.depth; k++)
+       name << "    ";
+      if (qi.is_bucket()) {
+       int type = crush->get_bucket_type(qi.id);
+       name << crush->get_type_name(type) << " "
+            << crush->get_item_name(qi.id);
+      } else {
+       name << "osd." << qi.id;
+      }
+      *tbl << name.str();
+    }
+
+    *tbl << TextTable::endrow;
+  }
+
+public:
+  string summary() {
+    ostringstream out;
+    out << "MIN/MAX VAR: " << lowprecision_t(min_var)
+       << "/" << lowprecision_t(max_var) << "  "
+       << "STDDEV: " << lowprecision_t(dev());
+    return out.str();
+  }
+};
+
+ostream& operator<<(ostream& out,
+                   const OSDUtilizationPlainDumper::lowprecision_t& v)
+{
+  if (v.v < -0.01) {
+    return out << "-";
+  } else if (v.v < 0.001) {
+    return out << "0";
+  } else {
+    std::streamsize p = out.precision();
+    return out << std::fixed << std::setprecision(2) << v.v << std::setprecision(p);
+  }
+}
+
+class OSDUtilizationFormatDumper : public OSDUtilizationDumper<Formatter> {
+public:
+  typedef OSDUtilizationDumper<Formatter> Parent;
+
+  OSDUtilizationFormatDumper(const CrushWrapper *crush, const OSDMap *osdmap,
+                            const PGStatService *pgs, bool tree) :
+    Parent(crush, osdmap, pgs, tree) {}
+
+  void dump(Formatter *f) {
+    f->open_array_section("nodes");
+    Parent::dump(f);
+    f->close_section();
+
+    f->open_array_section("stray");
+    dump_stray(f);
+    f->close_section();
+  }
+
+protected:
+  using OSDUtilizationDumper<Formatter>::dump_item;
+  void dump_item(const CrushTreeDumper::Item &qi,
+                        float &reweight,
+                        int64_t kb,
+                        int64_t kb_used,
+                        int64_t kb_avail,
+                        double& util,
+                        double& var,
+                        const size_t num_pgs,
+                        Formatter *f) override {
+    f->open_object_section("item");
+    CrushTreeDumper::dump_item_fields(crush, qi, f);
+    f->dump_float("reweight", reweight);
+    f->dump_int("kb", kb);
+    f->dump_int("kb_used", kb_used);
+    f->dump_int("kb_avail", kb_avail);
+    f->dump_float("utilization", util);
+    f->dump_float("var", var);
+    f->dump_unsigned("pgs", num_pgs);
+    CrushTreeDumper::dump_bucket_children(crush, qi, f);
+    f->close_section();
+  }
+
+public:
+  void summary(Formatter *f) {
+    f->open_object_section("summary");
+    f->dump_int("total_kb", pgs->get_osd_sum().kb);
+    f->dump_int("total_kb_used", pgs->get_osd_sum().kb_used);
+    f->dump_int("total_kb_avail", pgs->get_osd_sum().kb_avail);
+    f->dump_float("average_utilization", average_util);
+    f->dump_float("min_var", min_var);
+    f->dump_float("max_var", max_var);
+    f->dump_float("dev", dev());
+    f->close_section();
+  }
+};
+
+void print_osd_utilization(const OSDMap& osdmap,
+                          const PGStatService *pgstat,
+                          ostream& out,
+                          Formatter *f,
+                          bool tree)
+{
+  const CrushWrapper *crush = osdmap.crush.get();
+  if (f) {
+    f->open_object_section("df");
+    OSDUtilizationFormatDumper d(crush, &osdmap, pgstat, tree);
+    d.dump(f);
+    d.summary(f);
+    f->close_section();
+    f->flush(out);
+  } else {
+    OSDUtilizationPlainDumper d(crush, &osdmap, pgstat, tree);
+    TextTable tbl;
+    d.dump(&tbl);
+    out << tbl << d.summary() << "\n";
+  }
+}
index 5178132abbb9b02028672cf647e1da76d122f7c3..84bcf2fb75669570924e707e63c314c38afc5644 100644 (file)
@@ -1299,5 +1299,12 @@ inline ostream& operator<<(ostream& out, const OSDMap& m) {
   return out;
 }
 
+class PGStatService;
+
+void print_osd_utilization(const OSDMap& osdmap,
+                          const PGStatService *pgstat,
+                          ostream& out,
+                          Formatter *f,
+                          bool tree);
 
 #endif