From: Loic Dachary Date: Sat, 18 Feb 2017 22:42:59 +0000 (+0100) Subject: crush: update device classes where relevant X-Git-Tag: v12.0.1~135^2~2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=f9eb20694387437bce7b27e17868fbe17ec5c18a;p=ceph.git crush: update device classes where relevant The device classes are implemented by modifying: - the argument of step TAKE in rules - cloning bucket trees when required by a rule step This happens (via populate_classes): - before compiling a rule step TAKE When the crush map is encoded, the device class information is stored with it, independently from the rules and the buckets, as a map of classes for each device & bucket and a map of classes for each rule step TAKE. The extra buckets created but not used by any rule do not need to be preserved and they are removed (via cleanup_classes): - before decompilation - after compilation - after decoding The client and daemons that are not aware of the device classes are compatible because the crushmap modified with the new buckets is fully functional. The invalid names used in the for the generated buckets (bucket~class) can be CrushWrapper::decode by any existing client because there is no verification of the name validity during decoding. It can also be CrushWrapper::dump or CrushCompiler::decompile via ceph osd dump or crushtool. It cannot, however, be compiled again because CrushCompiler::compile will try to set the name with CrushWrapper::set_item_name and it will fail with EINVAL because of the ~. Fixes: http://tracker.ceph.com/issues/18943 Signed-off-by: Loic Dachary --- diff --git a/src/crush/CrushCompiler.cc b/src/crush/CrushCompiler.cc index 2d46f04c2ed..8957ed7bd84 100644 --- a/src/crush/CrushCompiler.cc +++ b/src/crush/CrushCompiler.cc @@ -217,6 +217,8 @@ int CrushCompiler::decompile_bucket(int cur, int CrushCompiler::decompile(ostream &out) { + crush.cleanup_classes(); + out << "# begin crush map\n"; // only dump tunables if they differ from the defaults @@ -670,6 +672,8 @@ int CrushCompiler::parse_bucket(iter_t const& i) int CrushCompiler::parse_rule(iter_t const& i) { + crush.populate_classes(); + int start; // rule name is optional! string rname = string_node(i->children[1]); @@ -878,6 +882,7 @@ int CrushCompiler::parse_crush(iter_t const& i) } //err << "max_devices " << crush.get_max_devices() << std::endl; + crush.cleanup_classes(); crush.finalize(); return 0; diff --git a/src/crush/CrushWrapper.cc b/src/crush/CrushWrapper.cc index 35c320f2757..6f3b306ad54 100644 --- a/src/crush/CrushWrapper.cc +++ b/src/crush/CrushWrapper.cc @@ -1488,6 +1488,7 @@ void CrushWrapper::decode(bufferlist::iterator& blp) for (auto &c : class_name) class_rname[c.second] = c.first; ::decode(class_bucket, blp); + cleanup_classes(); } finalize(); }