expect_false ceph osd crush rm bar # not empty
ceph osd crush unlink host2
+
+# reference foo and bar with a rule
+ceph osd crush rule create-simple foo-rule foo host firstn
+expect_false ceph osd crush rm foo
+ceph osd crush rule rm foo-rule
+
ceph osd crush rm bar
ceph osd crush rm foo
ceph osd crush rm osd.$o2 host2
if (_search_item_exists(item)) {
return false;
}
+ if (item < 0 && _bucket_is_in_use(cct, item)) {
+ return false;
+ }
if (item < 0 && !unlink_only) {
crush_bucket *t = get_bucket(item);
<< " items, not empty" << dendl;
return -ENOTEMPTY;
}
+ if (_bucket_is_in_use(cct, item)) {
+ return -EBUSY;
+ }
}
for (int i = 0; i < crush->max_buckets; i++) {
return false;
}
+bool CrushWrapper::_bucket_is_in_use(CephContext *cct, int item)
+{
+ 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 &&
+ r->steps[j].arg1 == item) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
int CrushWrapper::_remove_item_under(CephContext *cct, int item, int ancestor, bool unlink_only)
{
ldout(cct, 5) << "_remove_item_under " << item << " under " << ancestor
{
ldout(cct, 5) << "remove_item_under " << item << " under " << ancestor
<< (unlink_only ? " unlink_only":"") << dendl;
+
+ if (!unlink_only && _bucket_is_in_use(cct, item)) {
+ return -EBUSY;
+ }
+
int ret = _remove_item_under(cct, item, ancestor, unlink_only);
if (ret < 0)
return ret;
private:
bool _maybe_remove_last_instance(CephContext *cct, int id, bool unlink_only);
int _remove_item_under(CephContext *cct, int id, int ancestor, bool unlink_only);
+ bool _bucket_is_in_use(CephContext *cct, int id);
public:
int remove_item_under(CephContext *cct, int id, int ancestor, bool unlink_only);