return dir_remove_image_helper(hctx, name, id);
}
+/**
+ * Verify the current state of the directory
+ *
+ * Input:
+ * @param state the DirectoryState of the directory
+ *
+ * Output:
+ * @returns -ENOENT if the state does not match
+ * @returns 0 on success, negative error code on failure
+ */
+int dir_state_assert(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
+{
+ cls::rbd::DirectoryState directory_state;
+ try {
+ auto iter = in->cbegin();
+ decode(directory_state, iter);
+ } catch (const buffer::error &err) {
+ return -EINVAL;
+ }
+
+ cls::rbd::DirectoryState on_disk_directory_state;
+ int r = read_key(hctx, "state", &on_disk_directory_state);
+ if (r < 0) {
+ return r;
+ }
+
+ if (directory_state != on_disk_directory_state) {
+ return -ENOENT;
+ }
+ return 0;
+}
+
+/**
+ * Set the current state of the directory
+ *
+ * Input:
+ * @param state the DirectoryState of the directory
+ *
+ * Output:
+ * @returns -ENOENT if the state does not match
+ * @returns 0 on success, negative error code on failure
+ */
+int dir_state_set(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
+{
+ cls::rbd::DirectoryState directory_state;
+ try {
+ auto iter = in->cbegin();
+ decode(directory_state, iter);
+ } catch (const buffer::error &err) {
+ return -EINVAL;
+ }
+
+ int r = check_exists(hctx);
+ if (r < 0 && r != -ENOENT) {
+ return r;
+ }
+
+ switch (directory_state) {
+ case cls::rbd::DIRECTORY_STATE_READY:
+ break;
+ case cls::rbd::DIRECTORY_STATE_ADD_DISABLED:
+ {
+ if (r == -ENOENT) {
+ return r;
+ }
+
+ // verify that the directory is empty
+ std::map<std::string, bufferlist> vals;
+ bool more;
+ r = cls_cxx_map_get_vals(hctx, RBD_DIR_NAME_KEY_PREFIX,
+ RBD_DIR_NAME_KEY_PREFIX, 1, &vals, &more);
+ if (r < 0) {
+ return r;
+ } else if (!vals.empty()) {
+ return -EBUSY;
+ }
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ r = write_key(hctx, "state", directory_state);
+ if (r < 0) {
+ return r;
+ }
+
+ return 0;
+}
+
int object_map_read(cls_method_context_t hctx, BitVector<2> &object_map)
{
uint64_t size;
cls_method_handle_t h_dir_add_image;
cls_method_handle_t h_dir_remove_image;
cls_method_handle_t h_dir_rename_image;
+ cls_method_handle_t h_dir_state_assert;
+ cls_method_handle_t h_dir_state_set;
cls_method_handle_t h_object_map_load;
cls_method_handle_t h_object_map_save;
cls_method_handle_t h_object_map_resize;
cls_register_cxx_method(h_class, "dir_rename_image",
CLS_METHOD_RD | CLS_METHOD_WR,
dir_rename_image, &h_dir_rename_image);
+ cls_register_cxx_method(h_class, "dir_state_assert", CLS_METHOD_RD,
+ dir_state_assert, &h_dir_state_assert);
+ cls_register_cxx_method(h_class, "dir_state_set",
+ CLS_METHOD_RD | CLS_METHOD_WR,
+ dir_state_set, &h_dir_state_set);
/* methods for the rbd_object_map.$image_id object */
cls_register_cxx_method(h_class, "object_map_load",
return ioctx->operate(oid, &op);
}
+ void dir_state_assert(librados::ObjectOperation *op,
+ cls::rbd::DirectoryState directory_state)
+ {
+ bufferlist bl;
+ encode(directory_state, bl);
+ op->exec("rbd", "dir_state_assert", bl);
+ }
+
+ int dir_state_assert(librados::IoCtx *ioctx, const std::string &oid,
+ cls::rbd::DirectoryState directory_state)
+ {
+ librados::ObjectWriteOperation op;
+ dir_state_assert(&op, directory_state);
+
+ return ioctx->operate(oid, &op);
+ }
+
+ void dir_state_set(librados::ObjectWriteOperation *op,
+ cls::rbd::DirectoryState directory_state)
+ {
+ bufferlist bl;
+ encode(directory_state, bl);
+ op->exec("rbd", "dir_state_set", bl);
+ }
+
+ int dir_state_set(librados::IoCtx *ioctx, const std::string &oid,
+ cls::rbd::DirectoryState directory_state)
+ {
+ librados::ObjectWriteOperation op;
+ dir_state_set(&op, directory_state);
+
+ return ioctx->operate(oid, &op);
+ }
+
void dir_remove_image(librados::ObjectWriteOperation *op,
const std::string &name, const std::string &id)
{
class Context;
namespace librados {
- class ObjectReadOperation;
class IoCtx;
+ class ObjectOperation;
+ class ObjectReadOperation;
class ObjectWriteOperation;
}
void dir_rename_image(librados::ObjectWriteOperation *op,
const std::string &src, const std::string &dest,
const std::string &id);
+ void dir_state_assert(librados::ObjectOperation *op,
+ cls::rbd::DirectoryState directory_state);
+ int dir_state_assert(librados::IoCtx *ioctx, const std::string &oid,
+ cls::rbd::DirectoryState directory_state);
+ void dir_state_set(librados::ObjectWriteOperation *op,
+ cls::rbd::DirectoryState directory_state);
+ int dir_state_set(librados::IoCtx *ioctx, const std::string &oid,
+ cls::rbd::DirectoryState directory_state);
// operations on the rbd_object_map.$image_id object
void object_map_load_start(librados::ObjectReadOperation *op);
static const uint32_t MAX_OBJECT_MAP_OBJECT_COUNT = 256000000;
static const string RBD_GROUP_IMAGE_KEY_PREFIX = "image_";
+enum DirectoryState {
+ DIRECTORY_STATE_READY = 0,
+ DIRECTORY_STATE_ADD_DISABLED = 1
+};
+
+inline void encode(DirectoryState state, bufferlist& bl,
+ uint64_t features=0)
+{
+ ceph::encode(static_cast<uint8_t>(state), bl);
+}
+
+inline void decode(DirectoryState &state, bufferlist::const_iterator& it)
+{
+ uint8_t int_state;
+ ceph::decode(int_state, it);
+ state = static_cast<DirectoryState>(int_state);
+}
+
enum MirrorMode {
MIRROR_MODE_DISABLED = 0,
MIRROR_MODE_IMAGE = 1,
string invalid_id = ".abc";
string empty;
+ ASSERT_EQ(-ENOENT, dir_state_assert(&ioctx, oid,
+ cls::rbd::DIRECTORY_STATE_READY));
+ ASSERT_EQ(-ENOENT, dir_state_set(&ioctx, oid,
+ cls::rbd::DIRECTORY_STATE_ADD_DISABLED));
+
ASSERT_EQ(-ENOENT, dir_get_id(&ioctx, oid, imgname, &id));
ASSERT_EQ(-ENOENT, dir_get_name(&ioctx, oid, valid_id, &name));
ASSERT_EQ(-ENOENT, dir_remove_image(&ioctx, oid, imgname, valid_id));
ASSERT_EQ(0u, images.size());
ASSERT_EQ(0, ioctx.remove(oid));
+ ASSERT_EQ(0, dir_state_set(&ioctx, oid, cls::rbd::DIRECTORY_STATE_READY));
+ ASSERT_EQ(0, dir_state_assert(&ioctx, oid, cls::rbd::DIRECTORY_STATE_READY));
+
ASSERT_EQ(0, dir_add_image(&ioctx, oid, imgname, valid_id));
+ ASSERT_EQ(-EBUSY, dir_state_set(&ioctx, oid,
+ cls::rbd::DIRECTORY_STATE_ADD_DISABLED));
+
ASSERT_EQ(-EEXIST, dir_add_image(&ioctx, oid, imgname, valid_id2));
ASSERT_EQ(-EBADF, dir_add_image(&ioctx, oid, imgname2, valid_id));
ASSERT_EQ(0, dir_list(&ioctx, oid, "", 30, &images));