From: Loic Dachary Date: Mon, 27 Feb 2017 10:41:59 +0000 (+0100) Subject: crush: parse "class XXX" after bucket id X-Git-Tag: v12.0.1~135^2~15 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=09e26cb3701f584d0cefdd599d03f0ddc5bbe0c5;p=ceph.git crush: parse "class XXX" after bucket id Refs: http://tracker.ceph.com/issues/18943 Signed-off-by: Loic Dachary --- diff --git a/src/crush/CrushCompiler.cc b/src/crush/CrushCompiler.cc index 40cc9b37e55..2d46f04c2ed 100644 --- a/src/crush/CrushCompiler.cc +++ b/src/crush/CrushCompiler.cc @@ -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 used_items; int size = 0; + map class_id; for (unsigned p=3; pchildren.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; diff --git a/src/crush/CrushWrapper.cc b/src/crush/CrushWrapper.cc index 34b41269624..196a44ccd7e 100644 --- a/src/crush/CrushWrapper.cc +++ b/src/crush/CrushWrapper.cc @@ -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& 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(); } diff --git a/src/crush/CrushWrapper.h b/src/crush/CrushWrapper.h index 6dd35bfd9b6..abd901e12e4 100644 --- a/src/crush/CrushWrapper.h +++ b/src/crush/CrushWrapper.h @@ -57,6 +57,7 @@ public: std::map class_map; /* item id -> class id */ std::map class_name; /* class id -> class name */ std::map class_rname; /* class name -> class id */ + std::map > class_bucket; /* bucket[id][class] == id */ private: struct crush_map *crush; diff --git a/src/crush/grammar.h b/src/crush/grammar.h index f6664bd2bb9..910e74d6f42 100644 --- a/src/crush/grammar.h +++ b/src/crush/grammar.h @@ -114,14 +114,14 @@ struct crush_grammar : public 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 ); diff --git a/src/test/cli/crushtool/device-class.crush b/src/test/cli/crushtool/device-class.crush index be681593835..702000638c1 100644 --- a/src/test/cli/crushtool/device-class.crush +++ b/src/test/cli/crushtool/device-class.crush @@ -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