crush: implement remove_unused_root

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 22:40:55 +01:00
parent df33e70d42
commit 93c0e10033
3 changed files with 65 additions and 0 deletions

View File

@ -235,6 +235,31 @@ bool CrushWrapper::_maybe_remove_last_instance(CephContext *cct, int item, bool
return true;
}
int CrushWrapper::remove_unused_root(int item)
{
if (_bucket_is_in_use(item))
return 0;
crush_bucket *b = get_bucket(item);
if (IS_ERR(b))
return -ENOENT;
for (unsigned n = 0; n < b->size; n++) {
if (b->items[n] >= 0)
continue;
int r = remove_unused_root(b->items[n]);
if (r < 0)
return r;
}
crush_remove_bucket(crush, b);
name_map.erase(item);
have_rmaps = false;
if (class_bucket.count(item) != 0)
class_bucket.erase(item);
return 0;
}
int CrushWrapper::remove_item(CephContext *cct, int item, bool unlink_only)
{
ldout(cct, 5) << "remove_item " << item << (unlink_only ? " unlink_only":"") << dendl;

View File

@ -671,6 +671,15 @@ public:
*/
int remove_item(CephContext *cct, int id, bool unlink_only);
/**
* recursively remove buckets starting at item and stop removing
* when a bucket is in use.
*
* @param item id to remove
* @return 0 on success, negative on error
*/
int remove_unused_root(int item);
/**
* remove all instances of an item nested beneath a certain point from the map
*

View File

@ -941,6 +941,37 @@ TEST(CrushWrapper, distance) {
ASSERT_EQ(1, c.get_common_ancestor_distance(g_ceph_context, 3, p));
}
TEST(CrushWrapper, remove_unused_root) {
CrushWrapper c;
c.create();
c.set_type_name(1, "host");
c.set_type_name(2, "rack");
c.set_type_name(3, "root");
int weight = 1;
map<string,string> loc;
loc["host"] = "b1";
loc["rack"] = "r11";
loc["root"] = "default";
int item = 1;
c.insert_item(g_ceph_context, item, weight, "osd.1", loc);
item = 2;
loc["host"] = "b2";
loc["rack"] = "r12";
loc["root"] = "default";
c.insert_item(g_ceph_context, item, weight, "osd.2", loc);
assert(c.add_simple_ruleset("rule1", "r11", "host", "firstn", pg_pool_t::TYPE_ERASURE) >= 0);
ASSERT_TRUE(c.name_exists("default"));
ASSERT_TRUE(c.name_exists("r11"));
ASSERT_TRUE(c.name_exists("r12"));
ASSERT_EQ(c.remove_unused_root(c.get_item_id("default")), 0);
ASSERT_FALSE(c.name_exists("default"));
ASSERT_TRUE(c.name_exists("r11"));
ASSERT_FALSE(c.name_exists("r12"));
}
int main(int argc, char **argv) {
vector<const char*> args;
argv_to_vec(argc, (const char **)argv, args);