]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
crush: update device classes where relevant
authorLoic Dachary <ldachary@redhat.com>
Sat, 18 Feb 2017 22:42:59 +0000 (23:42 +0100)
committerLoic Dachary <ldachary@redhat.com>
Wed, 1 Mar 2017 16:24:09 +0000 (17:24 +0100)
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 <ldachary@redhat.com>
src/crush/CrushCompiler.cc
src/crush/CrushWrapper.cc

index 2d46f04c2ed09c312166852035a8dc91fe933b77..8957ed7bd847b83997bf4b84d06e2dfc5b65d1fe 100644 (file)
@@ -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;
index 35c320f2757dd1959da94e4a3c2ecd3aa1be0d53..6f3b306ad542689ea63f14a631af5e2f63e2b1c7 100644 (file)
@@ -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();
   }