]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
crush: guard set-device-class
authorxie xingguo <xie.xingguo@zte.com.cn>
Tue, 25 Jul 2017 07:18:44 +0000 (15:18 +0800)
committerxie xingguo <xie.xingguo@zte.com.cn>
Wed, 26 Jul 2017 14:34:08 +0000 (22:34 +0800)
If a device has already been bounded to a class,
do not allow to change its class silently.
Require user call rm-device-class first.

Signed-off-by: xie xingguo <xie.xingguo@zte.com.cn>
qa/standalone/crush/crush-classes.sh
src/crush/CrushWrapper.cc

index c81a4550dc8e605ff5f29f908eb959e7dc34f963..c2eccc38bd7208fd85fca3a53e1f24848ba9332d 100755 (executable)
@@ -186,6 +186,10 @@ function TEST_mon_classes() {
     expect_failure $dir EBUSY ceph osd crush class rm abc || return 1 # still referenced by foo-rule
     ceph osd crush rule rm foo-rule || return 1
     ceph osd crush class rm abc || return 1
+
+    # test set-device-class implicitly change class
+    ceph osd crush set-device-class hdd osd.0 || return 1
+    expect_failure $dir EBUSY ceph osd crush set-device-class nvme osd.0 || return 1
 }
 
 main crush-classes "$@"
index 2fc492e7f37201a6ccb235fcb7d95c2e2df263e2..11659ccf44089765962056c274ad86604177f21e 100644 (file)
@@ -1803,12 +1803,21 @@ int CrushWrapper::update_device_class(int id,
                                       const string& name,
                                       ostream *ss)
 {
+  assert(item_exists(id));
+  auto old_class_name = get_item_class(id);
+  if (old_class_name && old_class_name != class_name) {
+    *ss << "osd." << id << " has already bound to class '" << old_class_name
+        << "', can not reset class to '" << class_name  << "'; "
+        << "use 'ceph osd crush rm-device-class <osd>' to "
+        << "remove old class first";
+    return -EBUSY;
+  }
+
   int class_id = get_or_create_class_id(class_name);
   if (id < 0) {
     *ss << name << " id " << id << " is negative";
     return -EINVAL;
   }
-  assert(item_exists(id));
 
   if (class_map.count(id) != 0 && class_map[id] == class_id) {
     *ss << name << " already set to class " << class_name;