mirror of
https://github.com/ceph/ceph
synced 2025-01-03 01:22:53 +00:00
crush: parse "class XXX" after device
Refs: http://tracker.ceph.com/issues/18943 Signed-off-by: Loic Dachary <ldachary@redhat.com>
This commit is contained in:
parent
3955caca28
commit
eb5a7c3805
@ -45,6 +45,13 @@ static void print_item_name(ostream& out, int t, CrushWrapper &crush)
|
||||
out << "bucket" << (-1-t);
|
||||
}
|
||||
|
||||
static void print_item_class(ostream& out, int t, CrushWrapper &crush)
|
||||
{
|
||||
const char *c = crush.get_item_class(t);
|
||||
if (c)
|
||||
out << " class " << c;
|
||||
}
|
||||
|
||||
static void print_rule_name(ostream& out, int t, CrushWrapper &crush)
|
||||
{
|
||||
const char *name = crush.get_rule_name(t);
|
||||
@ -208,6 +215,7 @@ int CrushCompiler::decompile(ostream &out)
|
||||
for (int i=0; i<crush.get_max_devices(); i++) {
|
||||
out << "device " << i << " ";
|
||||
print_item_name(out, i, crush);
|
||||
print_item_class(out, i, crush);
|
||||
out << "\n";
|
||||
}
|
||||
|
||||
@ -361,7 +369,15 @@ int CrushCompiler::parse_device(iter_t const& i)
|
||||
item_id[name] = id;
|
||||
id_item[id] = name;
|
||||
|
||||
if (verbose) err << "device " << id << " '" << name << "'" << std::endl;
|
||||
if (verbose) err << "device " << id << " '" << name << "'";
|
||||
|
||||
if (i->children.size() > 3) {
|
||||
string c = string_node(i->children[4]);
|
||||
crush.set_item_class(id, c);
|
||||
if (verbose) err << " class" << " '" << c << "'" << std::endl;
|
||||
} else {
|
||||
if (verbose) err << std::endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1219,6 +1219,10 @@ void CrushWrapper::encode(bufferlist& bl, uint64_t features) const
|
||||
if (features & CEPH_FEATURE_CRUSH_TUNABLES5) {
|
||||
::encode(crush->chooseleaf_stable, bl);
|
||||
}
|
||||
|
||||
// device classes
|
||||
::encode(class_map, bl);
|
||||
::encode(class_name, bl);
|
||||
}
|
||||
|
||||
static void decode_32_or_64_string_map(map<int32_t,string>& m, bufferlist::iterator& blp)
|
||||
@ -1311,6 +1315,12 @@ void CrushWrapper::decode(bufferlist::iterator& blp)
|
||||
if (!blp.end()) {
|
||||
::decode(crush->chooseleaf_stable, blp);
|
||||
}
|
||||
if (!blp.end()) {
|
||||
::decode(class_map, blp);
|
||||
::decode(class_name, blp);
|
||||
for (auto &c : class_name)
|
||||
class_rname[c.second] = c.first;
|
||||
}
|
||||
finalize();
|
||||
}
|
||||
catch (...) {
|
||||
@ -1436,6 +1446,9 @@ void CrushWrapper::dump(Formatter *f) const
|
||||
sprintf(name, "device%d", i);
|
||||
f->dump_string("name", name);
|
||||
}
|
||||
const char *device_class = get_item_class(i);
|
||||
if (device_class != NULL)
|
||||
f->dump_string("class", device_class);
|
||||
f->close_section();
|
||||
}
|
||||
f->close_section();
|
||||
|
@ -54,6 +54,9 @@ public:
|
||||
std::map<int32_t, string> type_map; /* bucket/device type names */
|
||||
std::map<int32_t, string> name_map; /* bucket/device names */
|
||||
std::map<int32_t, string> rule_name_map;
|
||||
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 */
|
||||
|
||||
private:
|
||||
struct crush_map *crush;
|
||||
@ -394,6 +397,44 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *get_class_name(int i) const {
|
||||
std::map<int,string>::const_iterator p = class_name.find(i);
|
||||
if (p != class_name.end())
|
||||
return p->second.c_str();
|
||||
return 0;
|
||||
}
|
||||
int get_class_id(const string& name) const {
|
||||
std::map<string,int>::const_iterator p = class_rname.find(name);
|
||||
if (p != class_rname.end())
|
||||
return p->second;
|
||||
else
|
||||
return -EINVAL;
|
||||
}
|
||||
int get_or_create_class_id(const string& name) {
|
||||
int c = get_class_id(name);
|
||||
if (c < 0) {
|
||||
int i = class_name.size();
|
||||
class_name[i] = name;
|
||||
class_rname[name] = i;
|
||||
return i;
|
||||
} else {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
const char *get_item_class(int t) const {
|
||||
std::map<int,int>::const_iterator p = class_map.find(t);
|
||||
if (p == class_map.end())
|
||||
return 0;
|
||||
return get_class_name(p->second);
|
||||
}
|
||||
int set_item_class(int i, const string& name) {
|
||||
if (!is_valid_crush_name(name))
|
||||
return -EINVAL;
|
||||
class_map[i] = get_or_create_class_id(name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int can_rename_item(const string& srcname,
|
||||
const string& dstname,
|
||||
ostream *ss) const;
|
||||
|
@ -108,7 +108,7 @@ struct crush_grammar : public grammar<crush_grammar>
|
||||
tunable = str_p("tunable") >> name >> posint;
|
||||
|
||||
// devices
|
||||
device = str_p("device") >> posint >> name;
|
||||
device = str_p("device") >> posint >> name >> !( str_p("class") >> name );
|
||||
|
||||
// bucket types
|
||||
bucket_type = str_p("type") >> posint >> name;
|
||||
|
64
src/test/cli/crushtool/device-class.crush
Normal file
64
src/test/cli/crushtool/device-class.crush
Normal file
@ -0,0 +1,64 @@
|
||||
# begin crush map
|
||||
|
||||
# devices
|
||||
device 0 device0 class ssd
|
||||
device 1 device1 class ssd
|
||||
device 2 device2 class hdd
|
||||
|
||||
# types
|
||||
type 0 device
|
||||
type 1 host
|
||||
type 2 rack
|
||||
type 3 root
|
||||
|
||||
# buckets
|
||||
host host0 {
|
||||
id -1 # do not change unnecessarily
|
||||
# weight 1.000
|
||||
alg straw
|
||||
hash 0 # rjenkins1
|
||||
item device0 weight 1.000
|
||||
}
|
||||
host host1 {
|
||||
id -2 # do not change unnecessarily
|
||||
# weight 1.000
|
||||
alg straw
|
||||
hash 0 # rjenkins1
|
||||
item device1 weight 1.000
|
||||
}
|
||||
host host2 {
|
||||
id -5 # do not change unnecessarily
|
||||
# weight 1.000
|
||||
alg straw
|
||||
hash 0 # rjenkins1
|
||||
item device2 weight 1.000
|
||||
}
|
||||
rack rack0 {
|
||||
id -3 # do not change unnecessarily
|
||||
# weight 3.000
|
||||
alg straw
|
||||
hash 0 # rjenkins1
|
||||
item host0 weight 1.000
|
||||
item host1 weight 1.000
|
||||
item host2 weight 1.000
|
||||
}
|
||||
root root {
|
||||
id -4 # do not change unnecessarily
|
||||
# weight 4.000
|
||||
alg straw
|
||||
hash 0 # rjenkins1
|
||||
item rack0 weight 4.000
|
||||
}
|
||||
|
||||
# rules
|
||||
rule data {
|
||||
ruleset 1
|
||||
type replicated
|
||||
min_size 2
|
||||
max_size 2
|
||||
step take root
|
||||
step chooseleaf firstn 0 type rack
|
||||
step emit
|
||||
}
|
||||
|
||||
# end crush map
|
6
src/test/cli/crushtool/device-class.t
Normal file
6
src/test/cli/crushtool/device-class.t
Normal file
@ -0,0 +1,6 @@
|
||||
$ cp "$TESTDIR/device-class.crush" .
|
||||
$ crushtool -c device-class.crush -o device-class.compiled
|
||||
$ crushtool -d device-class.compiled -o device-class.conf
|
||||
$ crushtool -c device-class.conf -o device-class.recompiled
|
||||
$ cmp device-class.crush device-class.conf
|
||||
$ cmp device-class.compiled device-class.recompiled
|
Loading…
Reference in New Issue
Block a user