]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rbdtool: init rbd block id, later will be used for rename
authorYehuda Sadeh <yehuda@hq.newdream.net>
Tue, 29 Jun 2010 22:15:00 +0000 (15:15 -0700)
committerYehuda Sadeh <yehuda@hq.newdream.net>
Tue, 29 Jun 2010 23:00:05 +0000 (16:00 -0700)
src/cls_rbd.cc
src/include/rbd_types.h
src/rbdtool.cc

index d4cae65d2e654215495315b59fee396954053d4c..a216097e3f3da50485e179a09f60283f53146787 100644 (file)
@@ -18,6 +18,7 @@ cls_handle_t h_class;
 cls_method_handle_t h_snapshots_list;
 cls_method_handle_t h_snapshot_add;
 cls_method_handle_t h_snapshot_revert;
+cls_method_handle_t h_assign_bid;
 
 static int snap_read_header(cls_method_context_t hctx, bufferlist& bl)
 {
@@ -236,6 +237,47 @@ int snapshot_revert(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
   return out->length();
 }
 
+/* assign block id. This method should be called on the rbd_info object */
+int rbd_assign_bid(cls_method_context_t hctx, bufferlist *in, bufferlist *out)
+{
+  struct rbd_info info;
+  int rc;
+  bufferlist bl;
+
+  rc = cls_cxx_read(hctx, 0, sizeof(info), &bl);
+  if (rc < 0 && rc != -EEXIST)
+    return rc;
+
+  if (rc && rc < (int)sizeof(info)) {
+    CLS_LOG("bad rbd_info object, read %d bytes, expected %d", rc, sizeof(info));
+    return -EIO;
+  }
+
+  uint64_t max_id;
+  if (rc) {
+    memcpy(&info, bl.c_str(), sizeof(info));
+    max_id = info.max_id + 1;
+    info.max_id = max_id;
+  } else {
+    memset(&info, 0, sizeof(info));
+    max_id = 0;
+  }
+
+  bufferlist newbl;
+  bufferptr bp(sizeof(info));
+  memcpy(bp.c_str(), &info, sizeof(info));
+  newbl.push_back(bp);
+  rc = cls_cxx_write_full(hctx, &newbl);
+  if (rc < 0) {
+    CLS_LOG("error writing rbd_info, got rc=%d", rc);
+    return rc;
+  }
+
+  ::encode(max_id, *out);
+
+  return out->length();
+}
+
 void __cls_init()
 {
   CLS_LOG("Loaded rbd class!");
@@ -245,6 +287,9 @@ void __cls_init()
   cls_register_cxx_method(h_class, "snap_add", CLS_METHOD_RD | CLS_METHOD_WR, snapshot_add, &h_snapshot_add);
   cls_register_cxx_method(h_class, "snap_revert", CLS_METHOD_RD | CLS_METHOD_WR, snapshot_revert, &h_snapshot_revert);
 
+  /* assign a unique block id for rbd blocks */
+  cls_register_cxx_method(h_class, "assign_bid", CLS_METHOD_RD | CLS_METHOD_WR, rbd_assign_bid, &h_assign_bid);
+
   return;
 }
 
index 4f6202afea851d5c30ff78800ce81e8350c7c307..a7c0a39a94bb81ecb1426a9c6575b8dff6e76716 100644 (file)
@@ -25,6 +25,7 @@
 
 #define RBD_SUFFIX             ".rbd"
 #define RBD_DIRECTORY           "rbd_directory"
+#define RBD_INFO                "rbd_info"
 
 #define RBD_DEFAULT_OBJ_ORDER  22   /* 4MB */
 
 
 #define RBD_HEADER_TEXT                "<<< Rados Block Device Image >>>\n"
 #define RBD_HEADER_SIGNATURE   "RBD"
-#define RBD_HEADER_VERSION     "001.004"
+#define RBD_HEADER_VERSION     "001.005"
+
+struct rbd_info {
+       __le64 max_id;
+} __attribute__ ((packed));
 
 struct rbd_obj_snap_ondisk {
        __le64 id;
@@ -44,7 +49,8 @@ struct rbd_obj_snap_ondisk {
 } __attribute__((packed));
 
 struct rbd_obj_header_ondisk {
-       char text[64];
+       char text[40];
+       char block_name[24];
        char signature[4];
        char version[8];
        struct {
index 5a71d99a83e31f0d287d341d74fffb0c1513e709..47a9235ad844c50fb77b20e20833010dc847f098 100644 (file)
@@ -25,6 +25,7 @@ using namespace librados;
 #include <stdlib.h>
 #include <time.h>
 #include <sys/types.h>
+#include <errno.h>
 
 #include "include/rbd_types.h"
 
@@ -51,14 +52,18 @@ void usage()
 
 
 static void init_rbd_header(struct rbd_obj_header_ondisk& ondisk,
-                           size_t size, int order)
+                           size_t size, int order, uint64_t bid)
 {
+  uint32_t hi = bid >> 32;
+  uint32_t lo = bid & 0xFFFFFFFF;
   memset(&ondisk, 0, sizeof(ondisk));
 
   memcpy(&ondisk.text, RBD_HEADER_TEXT, sizeof(RBD_HEADER_TEXT));
   memcpy(&ondisk.signature, RBD_HEADER_SIGNATURE, sizeof(RBD_HEADER_SIGNATURE));
   memcpy(&ondisk.version, RBD_HEADER_VERSION, sizeof(RBD_HEADER_VERSION));
 
+  snprintf(ondisk.block_name, sizeof(ondisk.block_name), "rb.%08x.%08x", hi, lo);
+
   ondisk.image_size = size;
   if (order)
     ondisk.options.order = order;
@@ -103,6 +108,63 @@ void trim_image(const char *imgname, rbd_obj_header_ondisk *header, uint64_t new
   }
 }
 
+static int init_rbd_info(struct rbd_info *info)
+{
+  memset(info, 0, sizeof(*info));
+  return 0;
+}
+
+int read_rbd_info(pool_t pool, string& info_oid, struct rbd_info *info)
+{
+  int r;
+  bufferlist bl;
+
+  r = rados.read(pool, info_oid, 0, bl, sizeof(*info));
+  if (r < 0)
+    return r;
+  if (r == 0) {
+    return init_rbd_info(info);
+  }
+
+  if (r < (int)sizeof(*info))
+    return -EIO;
+
+  memcpy(info, bl.c_str(), r);
+  return 0;
+}
+
+static int touch_rbd_info(pool_t pool, string& info_oid)
+{
+  bufferlist bl;
+  int r = rados.write(pool, info_oid, 0, bl, 0);
+  if (r < 0)
+    return r;
+  return 0;
+}
+
+static int rbd_assign_bid(pool_t pool, string& info_oid, uint64_t *id)
+{
+  bufferlist bl, out;
+
+  *id = 0;
+
+  int r = touch_rbd_info(pool, info_oid);
+  if (r < 0)
+    return r;
+
+  r = rados.exec(pool, info_oid, "rbd", "assign_bid", bl, out);
+  if (r < 0)
+    return r;
+
+  cerr << "r=" << r << " out.length()=" << out.length() << std::endl;
+
+  bufferlist::iterator iter = out.begin();
+  ::decode(*id, iter);
+
+  return 0;
+}
+
+
 static void err_exit(pool_t pool)
 {
   rados.close_pool(pool);
@@ -181,6 +243,7 @@ int main(int argc, const char **argv)
     md_oid += RBD_SUFFIX;
   }
   string dir_oid = RBD_DIRECTORY;
+  string dir_info_oid= RBD_INFO;
 
   int r = rados.open_pool(poolname, &pool);
   if (r < 0) {
@@ -221,8 +284,15 @@ int main(int argc, const char **argv)
       err_exit(pool);
     }
 
+    uint64_t bid;
+    r = rbd_assign_bid(pool, dir_info_oid, &bid);
+    if (r < 0) {
+      cerr << "failed assigning block id" << std::endl;
+      err_exit(pool);
+    }
+
     struct rbd_obj_header_ondisk header;
-    init_rbd_header(header, size, order);
+    init_rbd_header(header, size, order, bid);
     
     bufferlist bl;
     bl.append((const char *)&header, sizeof(header));