From: xie xingguo Date: Sat, 5 Aug 2017 10:25:21 +0000 (+0800) Subject: crush: automatically kill dead classes X-Git-Tag: v12.1.3~55^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=87952fc68d171f0a550e8cdb1635c4bd53e102ab;p=ceph.git crush: automatically kill dead classes If a class is no more referenced by any devices or crush rules, it shall be considered as dead. This patch makes Ceph automatically recycles those dead classes, so user does not to explicitly call 'class rm', which is unsafe and annoying. Signed-off-by: xie xingguo --- diff --git a/qa/standalone/crush/crush-classes.sh b/qa/standalone/crush/crush-classes.sh index 6090835fb36f..24696fcd3193 100755 --- a/qa/standalone/crush/crush-classes.sh +++ b/qa/standalone/crush/crush-classes.sh @@ -162,19 +162,21 @@ function TEST_mon_classes() { ceph osd crush tree --show-shadow | grep -q '~ccc' || return 1 ceph osd crush rm-device-class 0 || return 1 ceph osd tree | grep -q 'aaa' && return 1 - ceph osd crush class ls | grep -q 'aaa' || return 1 + ceph osd crush class ls | grep -q 'aaa' && return 1 # class 'aaa' should gone ceph osd crush rm-device-class 1 || return 1 ceph osd tree | grep -q 'bbb' && return 1 - ceph osd crush class ls | grep -q 'bbb' || return 1 + ceph osd crush class ls | grep -q 'bbb' && return 1 # class 'bbb' should gone ceph osd crush rm-device-class 2 || return 1 ceph osd tree | grep -q 'ccc' && return 1 - ceph osd crush class ls | grep -q 'ccc' || return 1 + ceph osd crush class ls | grep -q 'ccc' && return 1 # class 'ccc' should gone ceph osd crush set-device-class asdf all || return 1 ceph osd tree | grep -q 'asdf' || return 1 ceph osd crush dump | grep -q '~asdf' || return 1 ceph osd crush tree --show-shadow | grep -q '~asdf' || return 1 + ceph osd crush rule create-replicated asdf-rule default host asdf || return 1 ceph osd crush rm-device-class all || return 1 ceph osd tree | grep -q 'asdf' && return 1 + ceph osd crush class ls | grep -q 'asdf' || return 1 # still referenced by asdf-rule ceph osd crush set-device-class abc osd.2 || return 1 ceph osd crush move osd.2 root=foo rack=foo-rack host=foo-host || return 1 diff --git a/src/crush/CrushWrapper.cc b/src/crush/CrushWrapper.cc index 4bf7cc5df203..770c472c49a6 100644 --- a/src/crush/CrushWrapper.cc +++ b/src/crush/CrushWrapper.cc @@ -1889,9 +1889,45 @@ int CrushWrapper::device_class_clone( return 0; } +bool CrushWrapper::_class_is_dead(int class_id) +{ + for (auto &p: class_map) { + if (p.first >= 0 && p.second == class_id) { + return false; + } + } + for (unsigned i = 0; i < crush->max_rules; ++i) { + crush_rule *r = crush->rules[i]; + if (!r) + continue; + for (unsigned j = 0; j < r->len; ++j) { + if (r->steps[j].op == CRUSH_RULE_TAKE) { + int root = r->steps[j].arg1; + for (auto &p : class_bucket) { + auto& q = p.second; + if (q.count(class_id) && q[class_id] == root) { + return false; + } + } + } + } + } + // no more referenced by any devices or crush rules + return true; +} + +void CrushWrapper::cleanup_dead_classes() +{ + for (auto &c: class_name) { + if (_class_is_dead(c.first)) + remove_class_name(c.second); + } +} + int CrushWrapper::rebuild_roots_with_classes() { std::map > old_class_bucket = class_bucket; + cleanup_dead_classes(); int r = trim_roots_with_class(false); if (r < 0) return r; diff --git a/src/crush/CrushWrapper.h b/src/crush/CrushWrapper.h index 7d4f55cac4ab..737ba583ecec 100644 --- a/src/crush/CrushWrapper.h +++ b/src/crush/CrushWrapper.h @@ -1216,6 +1216,8 @@ public: int *clone); int populate_classes( const std::map>& old_class_bucket); + bool _class_is_dead(int class_id); + void cleanup_dead_classes(); int rebuild_roots_with_classes(); /* remove unused roots generated for class devices */ int trim_roots_with_class(bool unused);