]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mon: prevent bucket deletion when referenced by a rule 4891/head
authorSage Weil <sage@redhat.com>
Tue, 12 May 2015 23:37:56 +0000 (16:37 -0700)
committerAbhishek Lekshmanan <abhishek.lekshmanan@ril.com>
Sun, 7 Jun 2015 09:19:03 +0000 (14:49 +0530)
If a rule references a bucket with 'take', prevent deletion.

Fixes: #11602
Signed-off-by: Sage Weil <sage@redhat.com>
(cherry picked from commit 3d591afef90b0601572c748f13faac029d05f5a0)

qa/workunits/mon/crush_ops.sh
src/crush/CrushWrapper.cc
src/crush/CrushWrapper.h

index 80950032fb2f97ad89a3283b9eed7838db261e39..adb3162038cb6f6183417aa4f4246d7091fafe34 100755 (executable)
@@ -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
index 497c2196958a2f2404b8d9b1c511885da8b177f8..ec3414b3dda60076066539c9db8118e9f2f685f9 100644 (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;
index cfafab067dee29a8a1992212f6ad2aa625509001..43acc48f49e508af6f05cf1cfc06fa27e5250eb9 100644 (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);