]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
crush: implement remove_unused_root
authorLoic Dachary <ldachary@redhat.com>
Sat, 18 Feb 2017 21:40:55 +0000 (22:40 +0100)
committerLoic Dachary <ldachary@redhat.com>
Wed, 1 Mar 2017 16:24:08 +0000 (17:24 +0100)
Refs: http://tracker.ceph.com/issues/18943

Signed-off-by: Loic Dachary <ldachary@redhat.com>
src/crush/CrushWrapper.cc
src/crush/CrushWrapper.h
src/test/crush/CrushWrapper.cc

index 0cab66d28f4263f0937ee3a8a3e7d679ec184901..3be8a11c237770aad4d40b8f083dfaa1c3c7a225 100644 (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;
index f424b32f043e7eb99219b33139f0b2a4bce21234..15a781bef2d6e45949f31bba6e3b001ad70f786f 100644 (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
    *
index f30538b28a3d180cb2b1eecc2bd21fc8331b3443..72842798c3574aa49275463827cac7bdf89180aa 100644 (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);