mon: prevent bucket deletion when referenced by a rule

If a rule references a bucket with 'take', prevent deletion.

Fixes: #11602
Signed-off-by: Sage Weil <sage@redhat.com>
This commit is contained in:
Sage Weil 2015-05-12 16:37:56 -07:00
parent 9324d0a1af
commit 3d591afef9
3 changed files with 34 additions and 0 deletions

View File

@ -63,6 +63,12 @@ ceph osd tree | grep -c host1 | grep -q 0
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

View File

@ -192,6 +192,9 @@ bool CrushWrapper::_maybe_remove_last_instance(CephContext *cct, int item, bool
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);
@ -219,6 +222,9 @@ int CrushWrapper::remove_item(CephContext *cct, int item, bool unlink_only)
<< " items, not empty" << dendl;
return -ENOTEMPTY;
}
if (_bucket_is_in_use(cct, item)) {
return -EBUSY;
}
}
for (int i = 0; i < crush->max_buckets; i++) {
@ -258,6 +264,22 @@ bool CrushWrapper::_search_item_exists(int item) const
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
@ -293,6 +315,11 @@ int CrushWrapper::remove_item_under(CephContext *cct, int item, int ancestor, bo
{
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;

View File

@ -587,6 +587,7 @@ public:
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);