From 96b1db80d0466c405fc1dc44680169f955c82c83 Mon Sep 17 00:00:00 2001 From: Yehuda Sadeh Date: Tue, 29 Jun 2010 15:15:00 -0700 Subject: [PATCH] rbdtool: init rbd block id, later will be used for rename --- src/cls_rbd.cc | 45 +++++++++++++++++++++++++ src/include/rbd_types.h | 10 ++++-- src/rbdtool.cc | 74 +++++++++++++++++++++++++++++++++++++++-- 3 files changed, 125 insertions(+), 4 deletions(-) diff --git a/src/cls_rbd.cc b/src/cls_rbd.cc index d4cae65d2e654..a216097e3f3da 100644 --- a/src/cls_rbd.cc +++ b/src/cls_rbd.cc @@ -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; } diff --git a/src/include/rbd_types.h b/src/include/rbd_types.h index 4f6202afea851..a7c0a39a94bb8 100644 --- a/src/include/rbd_types.h +++ b/src/include/rbd_types.h @@ -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 */ @@ -36,7 +37,11 @@ #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 { diff --git a/src/rbdtool.cc b/src/rbdtool.cc index 5a71d99a83e31..47a9235ad844c 100644 --- a/src/rbdtool.cc +++ b/src/rbdtool.cc @@ -25,6 +25,7 @@ using namespace librados; #include #include #include +#include #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)); -- 2.39.5