]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
crush: parse "class XXX" after bucket id
authorLoic Dachary <ldachary@redhat.com>
Mon, 27 Feb 2017 10:41:59 +0000 (11:41 +0100)
committerLoic Dachary <ldachary@redhat.com>
Wed, 1 Mar 2017 16:24:08 +0000 (17:24 +0100)
Refs: http://tracker.ceph.com/issues/18943

Signed-off-by: Loic Dachary <ldachary@redhat.com>
src/crush/CrushCompiler.cc
src/crush/CrushWrapper.cc
src/crush/CrushWrapper.h
src/crush/grammar.h
src/test/cli/crushtool/device-class.crush

index 40cc9b37e55060b79d6dc0e6830785576695b6b8..2d46f04c2ed09c312166852035a8dc91fe933b77 100644 (file)
@@ -45,6 +45,20 @@ static void print_item_name(ostream& out, int t, CrushWrapper &crush)
     out << "bucket" << (-1-t);
 }
 
+static void print_bucket_class_ids(ostream& out, int t, CrushWrapper &crush)
+{
+  if (crush.class_bucket.count(t) == 0)
+    return;
+  auto &class_to_id = crush.class_bucket[t];
+  for (auto &i : class_to_id) {
+    int c = i.first;
+    int cid = i.second;
+    const char* class_name = crush.get_class_name(c);
+    assert(class_name);
+    out << "\tid " << cid << " class " << class_name << "\t\t# do not change unnecessarily\n";
+  }
+}
+
 static void print_item_class(ostream& out, int t, CrushWrapper &crush)
 {
   const char *c = crush.get_item_class(t);
@@ -79,12 +93,16 @@ static void print_fixedpoint(ostream& out, int i)
 
 int CrushCompiler::decompile_bucket_impl(int i, ostream &out)
 {
+  const char *name = crush.get_item_name(i);
+  if (name && !crush.is_valid_crush_name(name))
+    return 0;
   int type = crush.get_bucket_type(i);
   print_type_name(out, type, crush);
   out << " ";
   print_item_name(out, i, crush);
   out << " {\n";
   out << "\tid " << i << "\t\t# do not change unnecessarily\n";
+  print_bucket_class_ids(out, i, crush);
 
   out << "\t# weight ";
   print_fixedpoint(out, crush.get_bucket_weight(i));
@@ -473,14 +491,33 @@ int CrushCompiler::parse_bucket(iter_t const& i)
   int hash = 0;
   set<int> used_items;
   int size = 0;
+  map<int32_t, int32_t> class_id;
   
   for (unsigned p=3; p<i->children.size()-1; p++) {
     iter_t sub = i->children.begin() + p;
     string tag = string_node(sub->children[0]);
     //err << "tag " << tag << std::endl;
-    if (tag == "id") 
-      id = int_node(sub->children[1]);
-    else if (tag == "alg") {
+    if (tag == "id") {
+      int maybe_id = int_node(sub->children[1]);
+      if (verbose) err << "bucket " << name << " id " << maybe_id;
+      if (sub->children.size() > 2) {
+        string class_name = string_node(sub->children[3]);
+        if (!crush.class_exists(class_name)) {
+          err << " unknown device class '" << class_name << "'" << std::endl;
+          return -EINVAL;
+        }
+        int cid = crush.get_class_id(class_name);
+        if (class_id.count(cid) != 0) {
+          err << "duplicate device class " << class_name << " for bucket " << name << std::endl;
+          return -ERANGE;
+        }
+        class_id[cid] = maybe_id;
+        if (verbose) err << " class" << " '" << class_name << "'" << std::endl;
+      } else {
+        id = maybe_id;
+        if (verbose) err << std::endl;
+      }
+    } else if (tag == "alg") {
       string a = string_node(sub->children[1]);
       if (a == "uniform")
        alg = CRUSH_BUCKET_UNIFORM;
@@ -609,6 +646,9 @@ int CrushCompiler::parse_bucket(iter_t const& i)
     //err << "assigned id " << id << std::endl;
   }
 
+  for (auto &i : class_id)
+    crush.class_bucket[id][i.first] = i.second;
+
   if (verbose) err << "bucket " << name << " (" << id << ") " << size << " items and weight "
                   << (float)bucketweight / (float)0x10000 << std::endl;
   id_item[id] = name;
index 34b41269624fc1cf064462ad80ab0caada2ba867..196a44ccd7eca491ffc39a41d49d8f9d0931389a 100644 (file)
@@ -1223,6 +1223,7 @@ void CrushWrapper::encode(bufferlist& bl, uint64_t features) const
   // device classes
   ::encode(class_map, bl);
   ::encode(class_name, bl);
+  ::encode(class_bucket, bl);
 }
 
 static void decode_32_or_64_string_map(map<int32_t,string>& m, bufferlist::iterator& blp)
@@ -1320,6 +1321,7 @@ void CrushWrapper::decode(bufferlist::iterator& blp)
       ::decode(class_name, blp);
       for (auto &c : class_name)
        class_rname[c.second] = c.first;
+      ::decode(class_bucket, blp);
     }
     finalize();
   }
index 6dd35bfd9b6253b7b7cf677b62b573e37ada26d3..abd901e12e4b8e07917095f4aa04f52d2ce861a6 100644 (file)
@@ -57,6 +57,7 @@ public:
   std::map<int32_t, int32_t> class_map; /* item id -> class id */
   std::map<int32_t, string> class_name; /* class id -> class name */
   std::map<string, int32_t> class_rname; /* class name -> class id */
+  std::map<int32_t, map<int32_t, int32_t> > class_bucket; /* bucket[id][class] == id */
 
 private:
   struct crush_map *crush;
index f6664bd2bb9d632b53551a45c20e9b3b1114d998..910e74d6f42d5695892cb1fc527d627c197baa3a 100644 (file)
@@ -114,14 +114,14 @@ struct crush_grammar : public grammar<crush_grammar>
       bucket_type = str_p("type") >> posint >> name;
 
       // buckets
-      bucket_id = str_p("id") >> negint;
+      bucket_id = str_p("id") >> negint >> !( str_p("class") >> name );
       bucket_alg = str_p("alg") >> name;
       bucket_hash = str_p("hash") >> ( integer |
                                       str_p("rjenkins1") );
       bucket_item = str_p("item") >> name
                                  >> !( str_p("weight") >> real_p )
                                  >> !( str_p("pos") >> posint );
-      bucket = name >> name >> '{' >> !bucket_id >> bucket_alg >> *bucket_hash >> *bucket_item >> '}';
+      bucket = name >> name >> '{' >> *bucket_id >> bucket_alg >> *bucket_hash >> *bucket_item >> '}';
 
       // rules
       step_take = str_p("take") >> name >> !( str_p("class") >> name );
index be681593835f75f135c6a46603092a23832de502..702000638c1f7966fe99d793d03f4f07df525c90 100644 (file)
@@ -14,6 +14,8 @@ type 3 root
 # buckets
 host host0 {
        id -1           # do not change unnecessarily
+       id -6 class ssd         # do not change unnecessarily
+       id -11 class hdd                # do not change unnecessarily
        # weight 1.000
        alg straw
        hash 0  # rjenkins1
@@ -21,6 +23,8 @@ host host0 {
 }
 host host1 {
        id -2           # do not change unnecessarily
+       id -7 class ssd         # do not change unnecessarily
+       id -12 class hdd                # do not change unnecessarily
        # weight 1.000
        alg straw
        hash 0  # rjenkins1
@@ -28,6 +32,8 @@ host host1 {
 }
 host host2 {
        id -5           # do not change unnecessarily
+       id -8 class ssd         # do not change unnecessarily
+       id -13 class hdd                # do not change unnecessarily
        # weight 1.000
        alg straw
        hash 0  # rjenkins1
@@ -35,6 +41,8 @@ host host2 {
 }
 rack rack0 {
        id -3           # do not change unnecessarily
+       id -9 class ssd         # do not change unnecessarily
+       id -14 class hdd                # do not change unnecessarily
        # weight 3.000
        alg straw
        hash 0  # rjenkins1
@@ -44,6 +52,8 @@ rack rack0 {
 }
 root root {
        id -4           # do not change unnecessarily
+       id -10 class ssd                # do not change unnecessarily
+       id -15 class hdd                # do not change unnecessarily
        # weight 4.000
        alg straw
        hash 0  # rjenkins1