]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
cls/rbd: add dir_state_set/asset methods
authorJason Dillaman <dillaman@redhat.com>
Thu, 14 Jun 2018 21:25:16 +0000 (17:25 -0400)
committerJason Dillaman <dillaman@redhat.com>
Mon, 18 Jun 2018 17:51:46 +0000 (13:51 -0400)
These new methods will be utilized to add protection for namespace
creation/removal

Signed-off-by: Jason Dillaman <dillaman@redhat.com>
src/cls/rbd/cls_rbd.cc
src/cls/rbd/cls_rbd_client.cc
src/cls/rbd/cls_rbd_client.h
src/cls/rbd/cls_rbd_types.h
src/test/cls_rbd/test_cls_rbd.cc

index 03a10b5f3c41d8f38a3017d115c906c94c32db3b..f71e5867d8ec9a53f265e610b6a5592b45f9881e 100644 (file)
@@ -2538,6 +2538,96 @@ int dir_remove_image(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
   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;
@@ -6122,6 +6212,8 @@ CLS_INIT(rbd)
   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;
@@ -6338,6 +6430,11 @@ CLS_INIT(rbd)
   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",
index 9ad132bd1ce2d4e8281013ebc7fdab47312e9c7e..fc831ff4136d731f369e64d4dc9613ecb2cad678 100644 (file)
@@ -1254,6 +1254,40 @@ namespace librbd {
       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)
     {
index 05f8571972b7a17e6f3a83ddc054dc169fbeb713..498f47fc871b254330e9273198ae02d03f0d46db 100644 (file)
@@ -13,8 +13,9 @@
 
 class Context;
 namespace librados {
-  class ObjectReadOperation;
   class IoCtx;
+  class ObjectOperation;
+  class ObjectReadOperation;
   class ObjectWriteOperation;
 }
 
@@ -289,6 +290,14 @@ namespace librbd {
     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);
index f557a2c30e60ea3d8a5a8c1c2e852208fbf422c5..4007f59c59948b418d865816392917fabcd01959 100644 (file)
@@ -24,6 +24,24 @@ namespace rbd {
 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,
index abdb7a9797db1707f54b96a36676b25a4f056c84..0534cbeccebff9d505f8645282df12388eeb48ff 100644 (file)
@@ -245,6 +245,11 @@ TEST_F(TestClsRbd, directory_methods)
   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));
@@ -261,7 +266,13 @@ TEST_F(TestClsRbd, directory_methods)
   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));