cls_method_handle_t h_set_protection_status;
cls_method_handle_t h_get_stripe_unit_count;
cls_method_handle_t h_set_stripe_unit_count;
+cls_method_handle_t h_get_flags;
+cls_method_handle_t h_set_flags;
cls_method_handle_t h_remove_parent;
cls_method_handle_t h_add_child;
cls_method_handle_t h_remove_child;
return 0;
}
+/**
+ * get the image flags
+ *
+ * Input:
+ * @param snap_id which snapshot to query, to CEPH_NOSNAP (uint64_t)
+ *
+ * Output:
+ * @param flags image flags
+ *
+ * @returns 0 on success, negative error code upon failure
+ */
+int get_flags(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
+{
+ uint64_t snap_id;
+ bufferlist::iterator iter = in->begin();
+ try {
+ ::decode(snap_id, iter);
+ } catch (const buffer::error &err) {
+ return -EINVAL;
+ }
+
+ CLS_LOG(20, "get_flags snap_id=%llu", (unsigned long long)snap_id);
+
+ uint64_t flags = 0;
+ if (snap_id == CEPH_NOSNAP) {
+ int r = read_key(hctx, "flags", &flags);
+ if (r < 0 && r != -ENOENT) {
+ CLS_ERR("failed to read flags off disk: %s", cpp_strerror(r).c_str());
+ return r;
+ }
+ } else {
+ cls_rbd_snap snap;
+ string snapshot_key;
+ key_from_snap_id(snap_id, &snapshot_key);
+ int r = read_key(hctx, snapshot_key, &snap);
+ if (r < 0) {
+ return r;
+ }
+ flags = snap.flags;
+ }
+
+ ::encode(flags, *out);
+ return 0;
+}
+
+/**
+ * set the image flags
+ *
+ * Input:
+ * @params flags image flags
+ * @params mask image flag mask
+ *
+ * Output:
+ * none
+ *
+ * @returns 0 on success, negative error code upon failure
+ */
+int set_flags(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
+{
+ uint64_t flags;
+ uint64_t mask;
+ bufferlist::iterator iter = in->begin();
+ try {
+ ::decode(flags, iter);
+ ::decode(mask, iter);
+ } catch (const buffer::error &err) {
+ return -EINVAL;
+ }
+
+ // check that size exists to make sure this is a header object
+ // that was created correctly
+ uint64_t orig_flags = 0;
+ int r = read_key(hctx, "flags", &orig_flags);
+ if (r < 0 && r != -ENOENT) {
+ CLS_ERR("Could not read image's flags off disk: %s",
+ cpp_strerror(r).c_str());
+ return r;
+ }
+
+ flags = (orig_flags & ~mask) | (flags & mask);
+ CLS_LOG(20, "set_flags flags=%llu orig_flags=%llu", (unsigned long long)flags,
+ (unsigned long long)orig_flags);
+
+ bufferlist flagsbl;
+ ::encode(flags, flagsbl);
+ r = cls_cxx_map_set_val(hctx, "flags", &flagsbl);
+ if (r < 0) {
+ CLS_ERR("error updating flags: %d", r);
+ return r;
+ }
+ return 0;
+}
/**
* get the current parent, if any
CLS_ERR("Could not read image's features off disk: %s", cpp_strerror(r).c_str());
return r;
}
+ r = read_key(hctx, "flags", &snap_meta.flags);
+ if (r < 0 && r != -ENOENT) {
+ CLS_ERR("Could not read image's flags off disk: %s", cpp_strerror(r).c_str());
+ return r;
+ }
int max_read = RBD_MAX_KEYS_READ;
string last_read = RBD_SNAP_KEY_PREFIX;
cls_register_cxx_method(h_class, "set_stripe_unit_count",
CLS_METHOD_RD | CLS_METHOD_WR,
set_stripe_unit_count, &h_set_stripe_unit_count);
+ cls_register_cxx_method(h_class, "get_flags",
+ CLS_METHOD_RD,
+ get_flags, &h_get_flags);
+ cls_register_cxx_method(h_class, "set_flags",
+ CLS_METHOD_RD | CLS_METHOD_WR,
+ set_flags, &h_set_flags);
/* methods for the rbd_children object */
cls_register_cxx_method(h_class, "add_child",
uint64_t features;
uint8_t protection_status;
cls_rbd_parent parent;
+ uint64_t flags;
/// true if we have a parent
bool has_parent() const {
}
cls_rbd_snap() : id(CEPH_NOSNAP), image_size(0), features(0),
- protection_status(RBD_PROTECTION_STATUS_UNPROTECTED)
+ protection_status(RBD_PROTECTION_STATUS_UNPROTECTED),
+ flags(0)
{}
void encode(bufferlist& bl) const {
- ENCODE_START(3, 1, bl);
+ ENCODE_START(4, 1, bl);
::encode(id, bl);
::encode(name, bl);
::encode(image_size, bl);
::encode(features, bl);
::encode(parent, bl);
::encode(protection_status, bl);
+ ::encode(flags, bl);
ENCODE_FINISH(bl);
}
void decode(bufferlist::iterator& p) {
- DECODE_START(3, p);
+ DECODE_START(4, p);
::decode(id, p);
::decode(name, p);
::decode(image_size, p);
if (struct_v >= 3) {
::decode(protection_status, p);
}
+ if (struct_v >= 4) {
+ ::decode(flags, p);
+ }
DECODE_FINISH(p);
}
void dump(Formatter *f) const {
t->name = "snap";
t->image_size = 123456;
t->features = 123;
+ t->flags = 31;
o.push_back(t);
t = new cls_rbd_snap;
t->id = 2;
t->parent.snapid = 456;
t->parent.overlap = 12345;
t->protection_status = RBD_PROTECTION_STATUS_PROTECTED;
+ t->flags = 14;
o.push_back(t);
}
};
return ioctx->exec(oid, "rbd", "set_parent", inbl, outbl);
}
+ int get_flags(librados::IoCtx *ioctx, const std::string &oid,
+ snapid_t snap_id, uint64_t *flags)
+ {
+ bufferlist inbl;
+ ::encode(snap_id, inbl);
+
+ bufferlist outbl;
+ int r = ioctx->exec(oid, "rbd", "get_flags", inbl, outbl);
+ if (r < 0) {
+ return r;
+ }
+
+ try {
+ bufferlist::iterator iter = outbl.begin();
+ ::decode(*flags, iter);
+ } catch (const buffer::error &err) {
+ return -EBADMSG;
+ }
+ return 0;
+ }
+
+ int set_flags(librados::IoCtx *ioctx, const std::string &oid,
+ uint64_t flags, uint64_t mask)
+ {
+ bufferlist inbl;
+ ::encode(flags, inbl);
+ ::encode(mask, inbl);
+
+ bufferlist outbl;
+ return ioctx->exec(oid, "rbd", "set_flags", inbl, outbl);
+ }
+
int remove_parent(librados::IoCtx *ioctx, const std::string &oid)
{
librados::ObjectWriteOperation op;
uint64_t *parent_overlap);
int set_parent(librados::IoCtx *ioctx, const std::string &oid,
parent_spec pspec, uint64_t parent_overlap);
+ int get_flags(librados::IoCtx *ioctx, const std::string &oid,
+ snapid_t snap_id, uint64_t *flags);
+ int set_flags(librados::IoCtx *ioctx, const std::string &oid,
+ uint64_t flags, uint64_t mask);
int remove_parent(librados::IoCtx *ioctx, const std::string &oid);
void remove_parent(librados::ObjectWriteOperation *op);
int add_child(librados::IoCtx *ioctx, const std::string &oid,
using ::librbd::cls_client::object_map_load;
using ::librbd::cls_client::object_map_resize;
using ::librbd::cls_client::object_map_update;
+using ::librbd::cls_client::get_flags;
+using ::librbd::cls_client::set_flags;
static char *random_buf(size_t len)
{
ioctx.close();
}
+
+TEST_F(TestClsRbd, flags)
+{
+ librados::IoCtx ioctx;
+ ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
+
+ string oid = get_temp_image_name();
+ ASSERT_EQ(0, create_image(&ioctx, oid, 0, 22, 0, oid));
+
+ uint64_t flags;
+ ASSERT_EQ(0, get_flags(&ioctx, oid, CEPH_NOSNAP, &flags));
+ ASSERT_EQ(0U, flags);
+
+ ASSERT_EQ(0, set_flags(&ioctx, oid, 3, 2));
+ ASSERT_EQ(0, get_flags(&ioctx, oid, CEPH_NOSNAP, &flags));
+ ASSERT_EQ(2U, flags);
+
+ uint64_t snap_id = 10;
+ ASSERT_EQ(-ENOENT, get_flags(&ioctx, oid, snap_id, &flags));
+ ASSERT_EQ(0, snapshot_add(&ioctx, oid, snap_id, "snap"));
+
+ ASSERT_EQ(0, set_flags(&ioctx, oid, 31, 4));
+ ASSERT_EQ(0, get_flags(&ioctx, oid, CEPH_NOSNAP, &flags));
+ ASSERT_EQ(6U, flags);
+
+ ASSERT_EQ(0, get_flags(&ioctx, oid, snap_id, &flags));
+ ASSERT_EQ(2U, flags);
+
+ ioctx.close();
+}