crush: implement trim_roots_with_class

Refs: http://tracker.ceph.com/issues/18943

Signed-off-by: Loic Dachary <ldachary@redhat.com>
This commit is contained in:
Loic Dachary 2017-02-18 23:18:49 +01:00
parent 09e4d4029f
commit c68c0c64ce
3 changed files with 59 additions and 0 deletions

View File

@ -1000,6 +1000,26 @@ int CrushWrapper::get_immediate_parent_id(int id, int *parent)
return -ENOENT;
}
int CrushWrapper::trim_roots_with_class()
{
set<int> takes;
find_takes(takes);
set<int> roots;
find_roots(roots);
for (auto &r : roots) {
if (r >= 0)
continue;
if (!id_has_class(r))
continue;
int res = remove_unused_root(r);
if (res)
return res;
}
// there is no need to reweight because we only remove from the
// root and down
return 0;
}
void CrushWrapper::reweight(CephContext *cct)
{
set<int> roots;

View File

@ -397,6 +397,13 @@ public:
name_rmap[name] = i;
return 0;
}
bool id_has_class(int i) {
int idout;
int classout;
if (split_id_class(i, &idout, &classout) != 0)
return false;
return classout != -1;
}
int split_id_class(int i, int *idout, int *classout) const;
bool class_exists(const string& name) const {
@ -1082,6 +1089,8 @@ public:
}
int device_class_clone(int original, int device_class, int *clone);
/* remove unused roots generated for class devices */
int trim_roots_with_class();
void start_choose_profile() {
free(crush->choose_tries);
/*

View File

@ -972,6 +972,36 @@ TEST(CrushWrapper, remove_unused_root) {
ASSERT_FALSE(c.name_exists("r12"));
}
TEST(CrushWrapper, trim_roots_with_class) {
CrushWrapper c;
c.create();
c.set_type_name(1, "root");
int weight = 1;
map<string,string> loc;
loc["root"] = "default";
int item = 1;
c.insert_item(g_ceph_context, item, weight, "osd.1", loc);
int cl = c.get_or_create_class_id("ssd");
c.class_map[item] = cl;
int root_id = c.get_item_id("default");
int clone_id;
ASSERT_EQ(c.device_class_clone(root_id, cl, &clone_id), 0);
ASSERT_TRUE(c.name_exists("default"));
ASSERT_TRUE(c.name_exists("default~ssd"));
c.trim_roots_with_class(); // do nothing because still in use
ASSERT_TRUE(c.name_exists("default"));
ASSERT_TRUE(c.name_exists("default~ssd"));
c.class_bucket.clear();
c.trim_roots_with_class(); // do nothing because still in use
ASSERT_TRUE(c.name_exists("default"));
ASSERT_FALSE(c.name_exists("default~ssd"));
}
TEST(CrushWrapper, device_class_clone) {
CrushWrapper c;
c.create();