创建一个volume:
如何命名服务端的volume的名字(以format==2为例):
rbd.cc
模块 主要函数 主要数据结构
RBD do_create(librbd::RBD &rbd, librados::IoCtx& io_ctx, imgname (char *) 由用户指定
const char *imgname, uint64_t size, int *order,
int format, uint64_t features,
uint64_t stripe_unit, uint64_t stripe_count)
{
。。。
}
librbd/internal.h
create(IoCtx& io_ctx, const char *imgname, uint64_t size,
bool old_format, uint64_t features, int *order,
uint64_t stripe_unit, uint64_t stripe_count)
{
...
Rados rados(io_ctx);
uint64_t bid = rados.get_instance_id();
...
return create_v2(io_ctx, imgname, bid, size, *order, features,
stripe_unit, stripe_count);
...
}
create_v2(IoCtx& io_ctx, const char *imgname, uint64_t bid, uint64_t size, bid (uint64_t)
int order, uint64_t features, uint64_t stripe_unit, imgname(char *)
uint64_t stripe_count)
{
...
id_obj = id_obj_name(imgname) //RBD_ID_PREFIX + name #define RBD_ID_PREFIX "rbd_id."
r = io_ctx.create(id_obj, true); // 创建objetct name实例
...
extra = rand() % 0xFFFFFFFF; //生产一个随机数
bid_ss << std::hex << bid << std::hex << extra; //将bid和产生的随机数转换成16进制并拼接
id = bid_ss.str(); //转换成字符串
r = cls_client::set_id(&io_ctx, id_obj, id); //为之前创建的object name对象设置id。
...
cls_client::dir_add_image(&io_ctx, RBD_DIRECTORY, imgname, id);//将该image的name和id注册到RBD_DIRECTORY对象中
//#define RBD_DIRECTORY "rbd_directory"
...
oss << RBD_DATA_PREFIX << id; //#define RBD_DATA_PREFIX "rbd_data."
header_oid = header_name(id); //RBD_HEADER_PREFIX + id #define RBD_HEADER_PREFIX "rbd_header."
cls_client::create_image(&io_ctx, header_oid, size, order,features, oss.str()) //创建object header对象
...
}
cls/rbd/cls_rbd_client.cc
create_image(librados::IoCtx *ioctx, const std::string &oid, object_prefix(string) //RBD_DATA_PREFIX + image_id
uint64_t size, uint8_t order, uint64_t features, oid(string) //object header
const std::string &object_prefix)
{
bufferlist bl, bl2;
::encode(size, bl);
::encode(order, bl);
::encode(features, bl);
::encode(object_prefix, (bl)); //image 的prefix为 RBD_DATA_PREFIX + image_id
return ioctx->exec(oid, "rbd", "create", bl, bl2);
}
librados/librados.cc
librados::IoCtx::exec(const std::string& oid, const char *cls, const char *method, oid(string) //object header
bufferlist& inbl, bufferlist& outbl)
{
object_t obj(oid);
return io_ctx_impl->exec(obj, cls, method, inbl, outbl);
}
//bid是怎么来的,
uint64_t librados::Rados::get_instance_id()
{
return client->get_instance_id();
}
uint64_t librados::RadosClient::get_instance_id()
{
return instance_id;
}
int librados::RadosClient::connect()
{
...
instance_id = monclient.get_global_id();
...
}
uint64_t get_global_id() const {
¦ return global_id;
}
uint64_t AuthMonitor::assign_global_id(MAuth *m, bool should_increase_max)
{
int total_mon = mon->monmap->size();
dout(10) << "AuthMonitor::assign_global_id m=" << *m << " mon=" << mon->rank << "/" << total_mon
¦ ¦<< " last_allocated=" << last_allocated_id << " max_global_id=" << max_global_id << dendl;
uint64_t next_global_id = last_allocated_id + 1;
int remainder = next_global_id % total_mon;
if (remainder)
¦ remainder = total_mon - remainder;
next_global_id += remainder + mon->rank;
dout(10) << "next_global_id should be " << next_global_id << dendl;
// if we can't bump the max, bail out now on an out-of-bounds gid
if (next_global_id > max_global_id &&
¦ ¦ (!mon->is_leader() || !should_increase_max)) {
¦ return 0;
}
// can we return a gid?
bool return_next = (next_global_id <= max_global_id);
// bump the max?
while (mon->is_leader() &&
¦(max_global_id < g_conf->mon_globalid_prealloc ||
¦ next_global_id >= max_global_id - g_conf->mon_globalid_prealloc / 2)) {
¦ increase_max_global_id();
}
if (return_next) {
¦ last_allocated_id = next_global_id;
¦ return next_global_id;
} else {
¦ return 0;
}
}
bid来源于monclient,monclient是从monitor服务中申请的ID。
总结:在创建image的时候会在服务端创建两个对象:1.object name对象(rbd_id.{image_name})2.object header对象(rbd_header.{image_id});
image_id是由一个随机数和bid转换成16进制之后拼接生成的。 bid是由MonClient从monitor服务中申请而来的(标识一个MonClient)。