]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
cls_rbd: add {get,set}_id methods
authorJosh Durgin <josh.durgin@inktank.com>
Tue, 26 Jun 2012 20:47:53 +0000 (13:47 -0700)
committerJosh Durgin <josh.durgin@inktank.com>
Thu, 28 Jun 2012 19:33:20 +0000 (12:33 -0700)
These will be used on a new rbd id object to provide a level of
indirection so that header objects don't need to move when
an image is renamed.

Signed-off-by: Josh Durgin <josh.durgin@inktank.com>
src/cls_rbd.cc
src/librbd/cls_rbd_client.cc
src/librbd/cls_rbd_client.h
src/test/rbd/test_cls_rbd.cc

index ae178e14cb639b4914378b8b6a6a4a1956d808af..64d783ae6be05a66b74c5af2b1884e9665ceedc3 100644 (file)
@@ -64,6 +64,8 @@ cls_method_handle_t h_lock_image_shared;
 cls_method_handle_t h_unlock_image;
 cls_method_handle_t h_break_lock;
 cls_method_handle_t h_list_locks;
+cls_method_handle_t h_get_id;
+cls_method_handle_t h_set_id;
 cls_method_handle_t h_old_snapshots_list;
 cls_method_handle_t h_old_snapshot_add;
 cls_method_handle_t h_old_snapshot_remove;
@@ -150,6 +152,17 @@ static int read_key(cls_method_context_t hctx, const string &key, T *out)
   return 0;
 }
 
+static bool is_valid_id(const string &id) {
+  if (!id.size())
+    return false;
+  for (size_t i = 0; i < id.size(); ++i) {
+    if (!isalnum(id[i])) {
+      return false;
+    }
+  }
+  return true;
+}
+
 /**
  * Initialize the header with basic metadata.
  * Extra features may initialize more fields in the future.
@@ -1107,6 +1120,88 @@ int get_all_features(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
   return 0;
 }
 
+/************************ rbd_id object methods **************************/
+
+/**
+ * Input:
+ * @param in ignored
+ *
+ * Output:
+ * @param id the id stored in the object
+ * @returns 0 on success, negative error code on failure
+ */
+int get_id(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
+{
+  uint64_t size;
+  int r = cls_cxx_stat(hctx, &size, NULL);
+  if (r < 0)
+    return r;
+
+  if (size == 0)
+    return -ENOENT;
+
+  bufferlist read_bl;
+  r = cls_cxx_read(hctx, 0, size, &read_bl);
+  if (r < 0) {
+    CLS_ERR("get_id: could not read id: %d", r);
+    return r;
+  }
+
+  string id;
+  try {
+    bufferlist::iterator iter = read_bl.begin();
+    ::decode(id, iter);
+  } catch (const buffer::error &err) {
+    return -EIO;
+  }
+
+  ::encode(id, *out);
+  return 0;
+};
+
+/**
+ * Set the id of an image. The object must already exist.
+ *
+ * Input:
+ * @param id the id of the image, as an alpha-numeric string
+ *
+ * Output:
+ * @returns 0 on success, -EEXIST if the atomic create fails,
+ *          negative error code on other error
+ */
+int set_id(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
+{
+  int r = check_exists(hctx);
+  if (r < 0)
+    return r;
+
+  string id;
+  try {
+    bufferlist::iterator iter = in->begin();
+    ::decode(id, iter);
+  } catch (const buffer::error &err) {
+    return -EINVAL;
+  }
+
+  if (!is_valid_id(id)) {
+    CLS_ERR("set_id: invalid id '%s'", id.c_str());
+    return -EINVAL;
+  }
+
+  uint64_t size;
+  r = cls_cxx_stat(hctx, &size, NULL);
+  if (r < 0)
+    return r;
+  if (size != 0)
+    return -EEXIST;
+
+  CLS_LOG(20, "set_id: id=%s", id.c_str());
+
+  bufferlist write_bl;
+  ::encode(id, write_bl);
+  return cls_cxx_write(hctx, 0, write_bl.length(), &write_bl);
+}
+
 /****************************** Old format *******************************/
 
 int old_snapshots_list(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
@@ -1406,6 +1501,15 @@ void __cls_init()
                          CLS_METHOD_RD | CLS_METHOD_WR | CLS_METHOD_PUBLIC,
                          remove_parent, &h_remove_parent);
 
+  /* methods for the rbd_id.$image_name objects */
+  cls_register_cxx_method(h_class, "get_id",
+                         CLS_METHOD_RD | CLS_METHOD_PUBLIC,
+                         get_id, &h_get_id);
+  cls_register_cxx_method(h_class, "set_id",
+                         CLS_METHOD_RD | CLS_METHOD_WR | CLS_METHOD_PUBLIC,
+                         set_id, &h_set_id);
+
+
   /* methods for the old format */
   cls_register_cxx_method(h_class, "snap_list",
                          CLS_METHOD_RD | CLS_METHOD_PUBLIC,
index e098719641def647e5a16a452923a2f0b640251a..0778ddf29fb72e9c89ae10a46050873b38dadc52 100644 (file)
@@ -416,5 +416,31 @@ namespace librbd {
       return ioctx->exec(oid, "rbd", "break_lock", in, out);
     }
 
+    /************************ rbd_id object methods ************************/
+
+    int get_id(librados::IoCtx *ioctx, const std::string &oid, std::string *id)
+    {
+      bufferlist in, out;
+      int r = ioctx->exec(oid, "rbd", "get_id", in, out);
+      if (r < 0)
+       return r;
+
+      bufferlist::iterator iter = out.begin();
+      try {
+       ::decode(*id, iter);
+      } catch (const buffer::error &err) {
+       return -EBADMSG;
+      }
+
+      return 0;
+    }
+
+    int set_id(librados::IoCtx *ioctx, const std::string &oid, std::string id)
+    {
+      bufferlist in, out;
+      ::encode(*id, in);
+      return ioctx->exec(oid, "rbd", "set_id", in, out);
+    }
+
   } // namespace cls_client
 } // namespace librbd
index 45194af5911e3b2be6154ed56407ca55c62ff000..e606002cfdba8de301c00ad866a6c4077b54cc58 100644 (file)
@@ -44,8 +44,8 @@ namespace librbd {
                   std::string *parent_image, snapid_t *parent_snap_id,
                   uint64_t *parent_overlap);
     int set_parent(librados::IoCtx *ioctx, const std::string &oid,
-                  int64_t parent_pool, const std::string& parent_image, snapid_t parent_snap_id,
-                  uint64_t parent_overlap);
+                  int64_t parent_pool, const std::string& parent_image,
+                  snapid_t parent_snap_id, uint64_t parent_overlap);
     int remove_parent(librados::IoCtx *ioctx, const std::string &oid);
     int snapshot_add(librados::IoCtx *ioctx, const std::string &oid,
                     snapid_t snap_id, const std::string &snap_name);
@@ -73,6 +73,10 @@ namespace librbd {
     int break_lock(librados::IoCtx *ioctx, const std::string& oid,
                    const std::string &locker, const std::string &cookie);
 
+    // operations on rbd_id objects
+    int get_id(librados::IoCtx *ioctx, const std::string &oid, std::string *id);
+    int set_id(librados::IoCtx *ioctx, const std::string &oid, std::string id);
+
     // class operations on the old format, kept for
     // backwards compatability
     int old_snapshot_add(librados::IoCtx *ioctx, const std::string &oid,
index 2cf91f316a8e88b7a6b3f3334cd29721faddbf08..83965448e166277cbd8c40b1c0a6c0d5bb012c8c 100644 (file)
@@ -33,6 +33,41 @@ using ::librbd::cls_client::lock_image_exclusive;
 using ::librbd::cls_client::lock_image_shared;
 using ::librbd::cls_client::unlock_image;
 using ::librbd::cls_client::break_lock;
+using ::librbd::cls_client::get_id;
+using ::librbd::cls_client::set_id;
+
+TEST(cls_rbd, get_and_set_id)
+{
+  librados::Rados rados;
+  librados::IoCtx ioctx;
+  string pool_name = get_temp_pool_name();
+
+  ASSERT_EQ("", create_one_pool_pp(pool_name, rados));
+  ASSERT_EQ(0, rados.ioctx_create(pool_name.c_str(), ioctx));
+
+  string oid = "rbd_id_test";
+  string id;
+  string valid_id = "0123abcxyzZYXCBA";
+  string invalid_id = ".abc";
+  string empty_id;
+
+  ASSERT_EQ(-ENOENT, get_id(&ioctx, oid, &id));
+  ASSERT_EQ(-ENOENT, set_id(&ioctx, oid, valid_id));
+
+  ASSERT_EQ(0, ioctx.create(oid, true));
+  ASSERT_EQ(-EINVAL, set_id(&ioctx, oid, invalid_id));
+  ASSERT_EQ(-EINVAL, set_id(&ioctx, oid, empty_id));
+  ASSERT_EQ(-ENOENT, get_id(&ioctx, oid, &id));
+
+  ASSERT_EQ(0, set_id(&ioctx, oid, valid_id));
+  ASSERT_EQ(-EEXIST, set_id(&ioctx, oid, valid_id));
+  ASSERT_EQ(-EEXIST, set_id(&ioctx, oid, valid_id + valid_id));
+  ASSERT_EQ(0, get_id(&ioctx, oid, &id));
+  ASSERT_EQ(id, valid_id);
+
+  ioctx.close();
+  ASSERT_EQ(0, destroy_one_pool_pp(pool_name, rados));
+}
 
 TEST(cls_rbd, create)
 {