]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
cls_rbd: check for LAYERING feature for parent methods
authorSage Weil <sage@inktank.com>
Fri, 15 Jun 2012 17:42:49 +0000 (10:42 -0700)
committerSage Weil <sage@inktank.com>
Tue, 19 Jun 2012 22:08:17 +0000 (15:08 -0700)
You need to set the feature on the image before you can use these methods.
We *could* allow get_parent, but that just means they'll get ENOENT instead
of ENOEXEC, and the latter is more informative.

Signed-off-by: Sage Weil <sage@inktank.com>
src/cls_rbd.cc
src/include/rbd_types.h
src/test/rbd/test_cls_rbd.cc

index 8685ae85163206cc2722cb8bdd6d9ef2863cbb5f..8f0099b514ea0dde633be89ff4819600cbe887e9 100644 (file)
@@ -348,6 +348,28 @@ int get_features(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
   return 0;
 }
 
+/**
+ * check that given feature(s) are set
+ *
+ * @param hctx context
+ * @param need features needed
+ * @return 0 if features are set, negative error (like ENOEXEC) otherwise
+ */
+int require_feature(cls_method_context_t hctx, uint64_t need)
+{
+  uint64_t features;
+  int r = read_key(hctx, "features", &features);
+  if (r == -ENOENT)   // this implies it's an old-style image with no features
+    return -ENOEXEC;
+  if (r < 0)
+    return r;
+  if ((features & need) != need) {
+    CLS_LOG(10, "require_feature missing feature %llx, have %llx", need, features);
+    return -ENOEXEC;
+  }
+  return 0;
+}
+
 /**
  * Input:
  * @param snap_id which snapshot to query, or CEPH_NOSNAP (uint64_t)
@@ -717,6 +739,10 @@ int get_parent(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
 
   CLS_LOG(20, "get_parent snap_id=%llu", snap_id);
 
+  r = require_feature(hctx, RBD_FEATURE_LAYERING);
+  if (r < 0)
+    return r;
+
   cls_rbd_parent parent;
   if (snap_id == CEPH_NOSNAP) {
     r = read_key(hctx, "parent", &parent);
@@ -772,6 +798,10 @@ int set_parent(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
   if (r < 0)
     return r;
 
+  r = require_feature(hctx, RBD_FEATURE_LAYERING);
+  if (r < 0)
+    return r;
+
   CLS_LOG(20, "set_parent pool=%lld id=%s snapid=%llu size=%llu",
          pool, id.c_str(), snapid.val, size);
 
@@ -818,6 +848,10 @@ int remove_parent(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
   if (r < 0)
     return r;
 
+  r = require_feature(hctx, RBD_FEATURE_LAYERING);
+  if (r < 0)
+    return r;
+
   cls_rbd_parent parent;
   r = read_key(hctx, "parent", &parent);
   if (r < 0)
index a91ca84a3074d82630374697235838ad243f4b8a..2cd5fedf5aed6e66f7a677d74d71114d0ebb514e 100644 (file)
 #define RBD_HEADER_PREFIX      "rbd_header."
 #define RBD_DATA_PREFIX        "rbd_data."
 
-#define RBD_FEATURES_INCOMPATIBLE 0
-#define RBD_FEATURES_ALL 0
+#define RBD_FEATURE_LAYERING      1
+
+#define RBD_FEATURES_INCOMPATIBLE (RBD_FEATURE_LAYERING)
+#define RBD_FEATURES_ALL          (RBD_FEATURE_LAYERING)
 
 /*
  * old-style rbd image 'foo' consists of objects
index d94bda8ccb68cb3bf66148cc7c297e55d02275e6..5fc5fee4900f527a522879bc0086a621baad8e28 100644 (file)
@@ -285,8 +285,15 @@ TEST(cls_rbd, parents)
   uint64_t size;
 
   ASSERT_EQ(-ENOENT, get_parent(&ioctx, "doesnotexist", CEPH_NOSNAP, &pool, &parent, &snapid, &size));
-
-  ASSERT_EQ(0, create_image(&ioctx, "foo", 1000, 22, 0, "foo."));
+  
+  // old image should fail
+  ASSERT_EQ(0, create_image(&ioctx, "old", 1000, 22, 0, "old_blk."));
+  ASSERT_EQ(-ENOEXEC, get_parent(&ioctx, "old", CEPH_NOSNAP, &pool, &parent, &snapid, &size));
+  ASSERT_EQ(-ENOEXEC, set_parent(&ioctx, "old", -1, "parent", 3, 10<<20));
+  ASSERT_EQ(-ENOEXEC, remove_parent(&ioctx, "old"));
+
+  // new image will work
+  ASSERT_EQ(0, create_image(&ioctx, "foo", 1000, 22, RBD_FEATURE_LAYERING, "foo."));
 
   ASSERT_EQ(-ENOENT, get_parent(&ioctx, "foo", CEPH_NOSNAP, &pool, &parent, &snapid, &size));
   ASSERT_EQ(-ENOENT, get_parent(&ioctx, "foo", 123, &pool, &parent, &snapid, &size));