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>
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)
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);
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);
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)
#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
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));