RBD創建一個image的過程分析。
rbd.cc
do_create(librbd::RBD &rbd, librados::IoCtx& io_ctx,const char *imgname,
uint64_t size, int *order,int format, uint64_t features,
uint64_t stripe_unit, uint64_t stripe_count) //創建一個image
>rbd.create3(io_ctx, imgname, size, features, order,stripe_unit, stripe_count)/create(...) //rbd 創建image
>librbd::create(io_ctx, name, size, false, features, order,stripe_unit, stripe_count) //librbd 創建image
>detect_format(io_ctx, imgname, NULL, NULL) //獲取image的格式,這裏用它來判斷該image是否存在
>uint64_t bid = rados.get_instance_id()
>create_v1(io_ctx, imgname, bid, size, *order) //format == 1
>create_v2(io_ctx, imgname, bid, size, *order, features,stripe_unit, stripe_count) //format ==2 以v2爲例
>validate_pool(io_ctx, cct) //判斷pool是否有效
>id_obj_name(imgname) //構建image的ID rbd_id.{imgname}
>io_ctx.create(id_obj, true) //創建image的ID對象
>io_ctx_impl->create(obj, exclusive) //創建object_t的實例
>io_ctx_impl->create(obj, exclusive)
>op.create(exclusive) //op(ObjectOperation)
>::ObjectOperation *o = (::ObjectOperation *)impl;
>o->create(exclusive)
>OSDOp& o = add_op(CEPH_OSD_OP_CREATE)
>operate(oid, &op, NULL)
>Objecter::Op *objecter_op = objecter->prepare_mutate_op(oid, oloc,*o, snapc, ut, flags,NULL, oncommit, &ver)
>objecter->op_submit(objecter_op) //提交Objecter::Op,進入Objecter層
>cls_client::set_id(&io_ctx, id_obj, id) //設置image的id (通過命令模式實現)
>ioctx->exec(oid, "rbd", "set_id", in, out)
>io_ctx_impl->exec(obj, cls, method, inbl, outbl)
>(::ObjectOperation)rd.call(cls, method, inbl) //將該操作封裝成OSDOp,放入ObjectOperation對象的vector集合中
>add_call(CEPH_OSD_OP_CALL, cname, method, indata, NULL, NULL, NULL)
>operate_read(oid, &rd, &outbl) //發起讀請求
>Objecter::Op *objecter_op = objecter->prepare_read_op(oid, oloc,*o, snap_seq, pbl, flags,onack, &ver) //創建Op的實例 數據結構變成Op
>objecter->op_submit(objecter_op) //提交到objecter層 操作對象爲Objecter::Op
>_op_submit_with_budget(op, lc, ctx_budget)
>int op_budget = _take_op_budget(op) //減去該Op的預算for throttle;
>int op_budget = calc_op_budget(op) //預算值是該Op的字節大小
> _throttle_op(op, op_budget) //這裏是Objecter的Throttle層,如果keep_balanced_budget=true,能實現對速度的限制(op_throttle_bytes&op_throttle_ops)
>_op_submit(op, lc)
>_calc_target(&op->target, &op->last_force_resend) //計算該op的操作對象(用到CRUSH算法)
>_get_session(op->target.osd, &s, lc) //爲該Op構建與osd對應的OSDSession
>_send_op_account(op) //登記該次op操作
> m = _prepare_osd_op(op) //使用Op中的信息,初始化MOSDOp的實例
>_session_op_assign(s, op) //將Op與OSDSession相關聯。
> _send_op(op, m)
>op->session->con->send_message(m) //進入Massenger層,操作對象MOSDOp
>static_cast<SimpleMessenger*>(msgr)->send_message(m, this) //使用使用massenger層的SimpleMessenger的實例發生消息
>_send_message(m, con)
>submit_message(m, static_cast<PipeConnection*>(con),con->get_peer_addr(), con->get_peer_type(), false) //提交信息
>static_cast<PipeConnection*>(con)->try_get_pipe(&pipe) //獲取該PipConnection對應的Pipe的實例
>pipe->_send(m) //通過Pipe發送消息,即:把消息放入到Pipe::out_q隊列中,並通知Pipe中的寫線程來做實際的發生操作。
>out_q[m->get_priority()].push_back(m);
>dispatch_queue.local_delivery(m, m->get_priority()) //如果發送端與接收端是同一個,則直接將消息投遞到DispathcQueue::local_messages中。
>cls_client::dir_add_image(&io_ctx, RBD_DIRECTORY, imgname, id) //將新建的image註冊到RBD_DIRECTORY中
>ioctx->exec(oid, "rbd", "dir_add_image", in, out) //做用於跨網絡傳輸的序列化工作
>io_ctx_impl->exec(obj, cls, method, inbl, outbl)
>rd.call(cls, method, inbl) //rd是(::ObjectOperation)的實例
>operate_read(oid, &rd, &outbl)
>Objecter::Op *objecter_op = objecter->prepare_read_op(oid, oloc,*o, snap_seq, pbl, flags,onack, &ver) //構建Objecter::Op的實例
>objecter->op_submit(objecter_op) //進入Objecter層
...同上
>header_name(id) //構建image的header標識
>cls_client::create_image(&io_ctx, header_oid, size, order,features, oss.str()) //創建image的header對象
>ioctx->exec(oid, "rbd", "create", bl, bl2) //命令模式,爲跨網絡傳輸做序列化工作
>io_ctx_impl->exec(obj, cls, method, inbl, outbl)
>rd.call(cls, method, inbl)
>operate_read(oid, &rd, &outbl)
>Objecter::Op *objecter_op = objecter->prepare_read_op(oid, oloc,*o, snap_seq, pbl, flags,onack, &ver)
>objecter->op_submit(objecter_op) //進入Objecter層
...同上
>cls_client::set_stripe_unit_count(&io_ctx, header_oid,stripe_unit, stripe_count) //設置image stripe的相關屬性,與header對象關聯
>ioctx->exec(oid, "rbd", "set_stripe_unit_count", in, out)
>io_ctx_impl->exec(obj, cls, method, inbl, outbl)
>rd.call(cls, method, inbl)
>operate_read(oid, &rd, &outbl)
>Objecter::Op *objecter_op = objecter->prepare_read_op(oid, oloc,*o, snap_seq, pbl, flags,onack, &ver) //構建Objecter::Op的實例
>objecter->op_submit(objecter_op) //進入Objecter層
>cls_client::object_map_resize(&op, Striper::get_num_objects(layout, size),OBJECT_NONEXISTENT) //構建op,該op用於resize object map
>rados_op->exec("rbd", "object_map_resize", in) //rados_op(librados::ObjectWriteOperation) 做序列化工作
>::ObjectOperation *o = (::ObjectOperation *)impl;
>o->call(cls, method, inbl);
>io_ctx.operate(ObjectMap::object_map_name(id, CEPH_NOSNAP), &op) //執行op
>io_ctx_impl->operate(obj, (::ObjectOperation*)o->impl, o->pmtime)
>Objecter::Op *objecter_op = objecter->prepare_mutate_op(oid, oloc,*o, snapc, ut, flags,NULL, oncommit, &ver) //創建Objecter::Op的實例,將ObjectOperation轉化成Objecter::Op
>objecter->op_submit(objecter_op) //提交Objecter::Op,進入Objecter層
創建一個Image的步驟(新image組成格式):
1.創建image的ID對象 rbd_id.{imagename}
2.創建image的id(隨機生產的,與image的ID對象完全不同)
3.將該image註冊到RBD_DIRECTORY中(imagename ,id)
4.創建image的header對象
6.將image的相關元信息,綁定到header對象上。