From: Loic Dachary Date: Sat, 18 Feb 2017 21:20:04 +0000 (+0100) Subject: crush: parse "class XXX" after step take X-Git-Tag: v12.0.1~135^2~16 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=6c9cb09fe1af5e20aacc8fd4c59be11fe299784a;p=ceph.git crush: parse "class XXX" after step take 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 43d862db9e80..40cc9b37e550 100644 --- a/src/crush/CrushCompiler.cc +++ b/src/crush/CrushCompiler.cc @@ -52,6 +52,15 @@ static void print_item_class(ostream& out, int t, CrushWrapper &crush) out << " class " << c; } +static void print_class(ostream& out, int t, CrushWrapper &crush) +{ + const char *c = crush.get_class_name(t); + if (c) + out << " class " << c; + else + out << " # unexpected class " << t; +} + static void print_rule_name(ostream& out, int t, CrushWrapper &crush) { const char *name = crush.get_rule_name(t); @@ -270,7 +279,19 @@ int CrushCompiler::decompile(ostream &out) break; case CRUSH_RULE_TAKE: out << "\tstep take "; - print_item_name(out, crush.get_rule_arg1(i, j), crush); + { + int step_item = crush.get_rule_arg1(i, j); + int original_item; + int c; + int res = crush.split_id_class(step_item, &original_item, &c); + if (res < 0) + return res; + if (c >= 0) + step_item = original_item; + print_item_name(out, step_item, crush); + if (c >= 0) + print_class(out, c, crush); + } out << "\n"; break; case CRUSH_RULE_EMIT: @@ -658,7 +679,35 @@ int CrushCompiler::parse_rule(iter_t const& i) err << "in rule '" << rname << "' item '" << item << "' not defined" << std::endl; return -1; } - crush.set_rule_step_take(ruleno, step++, item_id[item]); + int id = item_id[item]; + int c = -1; + string class_name; + if (s->children.size() > 2) { + class_name = string_node(s->children[3]); + c = crush.get_class_id(class_name); + if (c < 0) + return c; + if (crush.class_bucket.count(id) == 0) { + err << "in rule '" << rname << "' step take " << item + << " has no class information" << std::endl; + return -EINVAL; + } + if (crush.class_bucket[id].count(c) == 0) { + err << "in rule '" << rname << "' step take " << item + << " no matching bucket for class " << class_name << std::endl; + return -EINVAL; + } + id = crush.class_bucket[id][c]; + } + if (verbose) { + err << "rule " << rname << " take " << item; + if (c < 0) + err << std::endl; + else + err << " remapped to " << crush.get_item_name(id) << std::endl; + } + + crush.set_rule_step_take(ruleno, step++, id); } break; diff --git a/src/crush/grammar.h b/src/crush/grammar.h index 66c010bb45f4..f6664bd2bb9d 100644 --- a/src/crush/grammar.h +++ b/src/crush/grammar.h @@ -124,7 +124,7 @@ struct crush_grammar : public grammar bucket = name >> name >> '{' >> !bucket_id >> bucket_alg >> *bucket_hash >> *bucket_item >> '}'; // rules - step_take = str_p("take") >> name; + step_take = str_p("take") >> name >> !( str_p("class") >> name ); step_set_choose_tries = str_p("set_choose_tries") >> posint; step_set_choose_local_tries = str_p("set_choose_local_tries") >> posint; step_set_choose_local_fallback_tries = str_p("set_choose_local_fallback_tries") >> posint; diff --git a/src/test/cli/crushtool/device-class.crush b/src/test/cli/crushtool/device-class.crush index 2d4a69a9ecae..be681593835f 100644 --- a/src/test/cli/crushtool/device-class.crush +++ b/src/test/cli/crushtool/device-class.crush @@ -51,11 +51,29 @@ root root { } # rules -rule data { +rule data-ssd { ruleset 1 type replicated min_size 2 max_size 2 + step take root class ssd + step chooseleaf firstn 0 type rack + step emit +} +rule data-hdd { + ruleset 2 + type replicated + min_size 2 + max_size 2 + step take root class hdd + step chooseleaf firstn 0 type rack + step emit +} +rule data { + ruleset 3 + type replicated + min_size 2 + max_size 2 step take root step chooseleaf firstn 0 type rack step emit diff --git a/src/test/cli/osdmaptool/crush.t b/src/test/cli/osdmaptool/crush.t index d2f27ef736d3..048285df551e 100644 --- a/src/test/cli/osdmaptool/crush.t +++ b/src/test/cli/osdmaptool/crush.t @@ -6,5 +6,5 @@ osdmaptool: exported crush map to oc $ osdmaptool --import-crush oc myosdmap osdmaptool: osdmap file 'myosdmap' - osdmaptool: imported 492 byte crush map from oc + osdmaptool: imported 504 byte crush map from oc osdmaptool: writing epoch 3 to myosdmap