]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
cls_rbd: add set_features class method
authorJason Dillaman <dillaman@redhat.com>
Wed, 11 Mar 2015 20:07:41 +0000 (16:07 -0400)
committerJason Dillaman <dillaman@redhat.com>
Mon, 6 Apr 2015 17:14:34 +0000 (13:14 -0400)
Allow certain mutable feature flags to be updated within
an image.

Signed-off-by: Jason Dillaman <dillaman@redhat.com>
src/cls/rbd/cls_rbd.cc
src/include/rbd/features.h

index 677cfe0d011969f4b8f0244e700313332b204d33..6bd5999060d1d55bf2351f705a7030a95e30156e 100644 (file)
@@ -64,6 +64,7 @@ CLS_NAME(rbd)
 cls_handle_t h_class;
 cls_method_handle_t h_create;
 cls_method_handle_t h_get_features;
+cls_method_handle_t h_set_features;
 cls_method_handle_t h_get_size;
 cls_method_handle_t h_set_size;
 cls_method_handle_t h_get_parent;
@@ -323,6 +324,60 @@ int get_features(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
   return 0;
 }
 
+/**
+ * set the image features
+ *
+ * Input:
+ * @params features image features
+ * @params mask image feature mask
+ *
+ * Output:
+ * none
+ *
+ * @returns 0 on success, negative error code upon failure
+ */
+int set_features(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
+{
+  uint64_t features;
+  uint64_t mask;
+  bufferlist::iterator iter = in->begin();
+  try {
+    ::decode(features, iter);
+    ::decode(mask, iter);
+  } catch (const buffer::error &err) {
+    return -EINVAL;
+  }
+
+  if ((mask & RBD_FEATURES_MUTABLE) != mask) {
+    CLS_ERR("Attempting to set immutable feature: %" PRIu64,
+            mask & ~RBD_FEATURES_MUTABLE);
+    return -EINVAL;
+  }
+
+  // check that features exists to make sure this is a header object
+  // that was created correctly
+  uint64_t orig_features = 0;
+  int r = read_key(hctx, "features", &orig_features);
+  if (r < 0 && r != -ENOENT) {
+    CLS_ERR("Could not read image's features off disk: %s",
+            cpp_strerror(r).c_str());
+    return r;
+  }
+
+  features = (orig_features & ~mask) | (features & mask);
+  CLS_LOG(10, "set_features features=%" PRIu64 " orig_features=%" PRIu64,
+          features, orig_features);
+
+  bufferlist bl;
+  ::encode(features, bl);
+  r = cls_cxx_map_set_val(hctx, "features", &bl);
+  if (r < 0) {
+    CLS_ERR("error updating features: %s", cpp_strerror(r).c_str());
+    return r;
+  }
+  return 0;
+}
+
 /**
  * check that given feature(s) are set
  *
@@ -2501,6 +2556,9 @@ void __cls_init()
   cls_register_cxx_method(h_class, "get_features",
                          CLS_METHOD_RD,
                          get_features, &h_get_features);
+  cls_register_cxx_method(h_class, "set_features",
+                         CLS_METHOD_RD | CLS_METHOD_WR,
+                         set_features, &h_set_features);
   cls_register_cxx_method(h_class, "get_size",
                          CLS_METHOD_RD,
                          get_size, &h_get_size);
index 1d170679d49ddff6952339cb5b124cb06e491287..39abb396224cb59f2e17e856dbfc74b001b99074 100644 (file)
@@ -18,4 +18,7 @@
                                         RBD_FEATURE_EXCLUSIVE_LOCK | \
                                          RBD_FEATURE_OBJECT_MAP)
 
+#define RBD_FEATURES_MUTABLE            (RBD_FEATURE_EXCLUSIVE_LOCK | \
+                                         RBD_FEATURE_OBJECT_MAP)
+
 #endif