0 本文概述
本文將對(duì)通過終端cli在Ceph集群中創(chuàng)建image的流程進(jìn)行解析
1 流程時(shí)序圖
2 代碼走讀
2.1 命令行處理:/src/tools/
2.1.1 rbd.cc
rbd.cc提供main函數(shù)入口薯嗤,作為主程序的入口米间,調(diào)用shell.cc中的execute()函數(shù)害淤,對(duì)指令進(jìn)行解析。
2.1.2 shell.cc
shell.cc解析命令行,并通過封裝的Action類調(diào)用對(duì)應(yīng)的文件,對(duì)應(yīng)當(dāng)前目錄下的Action文件付秕。對(duì)于create而言,這里調(diào)用create.cc文件侍郭。
2.1.3 Action/create.cc
在execute()函數(shù)中調(diào)用librados和IoContext并初始化询吴,之后調(diào)用do_create().
2.2 librbd層:src/librbd/
2.2.1 librbd.cc
librbd提供相應(yīng)的接口,具體實(shí)現(xiàn)在interval.cc中励幼,本文中create image操作使用create4()實(shí)現(xiàn)對(duì)create()接口的封裝汰寓。
通過create()接口,調(diào)用interval.cc中create()函數(shù)苹粟,interval.cc提供這些接口的實(shí)現(xiàn)(line 820 to line 877).
在create()函數(shù)中有滑,librbd獲取image id和相應(yīng)的參數(shù),并根據(jù)format的新舊使用調(diào)用不同的接口嵌削。v1現(xiàn)在已被廢棄毛好。使用v2來完成image create。
對(duì)于新format信息苛秕,調(diào)用當(dāng)前目錄中image目錄中的CreateRequest.cc中send()函數(shù)進(jìn)行調(diào)用肌访。
2.2.2 /src/librbd/image/CreateRequest.cc
librbd中,將每個(gè)操作的具體實(shí)現(xiàn)都封裝成了<operation>Request.cc/h文件艇劫,operation對(duì)應(yīng)每個(gè)具體的操作吼驶,如當(dāng)前的create操作的具體實(shí)現(xiàn)就是createRequest.cc/h中。
如上店煞,頭文件給出了類的定義蟹演,send實(shí)現(xiàn)在.cc文件中。頭文件還給出了CreateRequest.cc實(shí)現(xiàn)image create的函數(shù)調(diào)用流程圖顷蟀。
函數(shù)聲明方面酒请,函數(shù)和回調(diào)函數(shù)成對(duì)聲明,回調(diào)函數(shù)以handle_開頭區(qū)分鸣个。
上面的函數(shù)實(shí)現(xiàn)中可以看出羞反,send()函數(shù)調(diào)用validate_pool()函數(shù)布朦,在validate_pool()函數(shù)中,封裝并調(diào)用回調(diào)函數(shù)handle_validate_pool()函數(shù)昼窗,校驗(yàn)rbd_directory對(duì)象是否存在是趴,下一步的操作在回調(diào)函數(shù)中調(diào)用。其中aio_operate()實(shí)際執(zhí)行回調(diào)函數(shù)膏秫。
validate_overwrite()作用是校驗(yàn)rbd_info的內(nèi)容右遭。
在handle_validate_overwrite()函數(shù)中做盅,如果rbd_info存在并且內(nèi)容為“overwrite validated”, 直接進(jìn)入下一狀態(tài)缤削,調(diào)用create_id_object(),創(chuàng)建rbd_id.<image_name>對(duì)象吹榴。
create_id_object()函數(shù)中亭敢,先調(diào)用了cls_client::set_id()創(chuàng)建rbd_id,之后又使用回調(diào)函數(shù),這里個(gè)人觀點(diǎn)為cls的函數(shù)需要回調(diào)函數(shù)觸發(fā)图筹。在回調(diào)函數(shù)中帅刀,調(diào)用add_image_to_directory()函數(shù)進(jìn)入下一狀態(tài)。
add_image_to_directory()作用為在rbd_directory對(duì)象中加入該image的id和name远剩。
negotiate_features()中扣溺,會(huì)首先獲取所有的feature,之后觸發(fā)回調(diào)函數(shù)瓜晤,將返回的feature decode到all_features中锥余,之后調(diào)用create_image(),進(jìn)入下一狀態(tài)痢掠。
在create_image()中驱犹,通過cls注冊(cè)的函數(shù)創(chuàng)建rbd_header對(duì)象,并設(shè)置omap中的值足画,調(diào)用回調(diào)函數(shù)完成創(chuàng)建雄驹。
之后代碼遵循類似的流程,都是通過cls_client注冊(cè)的函數(shù) + 回調(diào)函數(shù)完成該狀態(tài)功能淹辞,并調(diào)用函數(shù)医舆,進(jìn)入下一狀態(tài)。調(diào)用的函數(shù)順序?yàn)椋?/p>
set_strip_unit_count() -> handle_strip_unit_count() -> object_map_resize() -> handle_object_map_resize() -> fetch_mirror_mode() -> handle_fetch_mirror_mode() -> journal_create() -> handle_journal_create() -> mirror_image_enable() -> handle_mirror_image_enable()
在一系列的調(diào)用完成后象缀,調(diào)用complete()函數(shù)蔬将,傳入的參數(shù)為0。
在complete()函數(shù)中攻冷,釋放數(shù)據(jù)對(duì)象上下文娃胆,調(diào)用CreateRequest回調(diào)函數(shù),完成步驟等曼。
2.2.3 cls/rbd/cls_rbd_client.cc
在前文的Request調(diào)用中里烦,使用回調(diào)函數(shù)進(jìn)入下一狀態(tài)之前凿蒜,會(huì)先調(diào)用cls模塊進(jìn)行注冊(cè),cls模塊針對(duì)rbd的實(shí)現(xiàn)在cls_rbd_client.cc文件中胁黑。
cls_client模塊負(fù)責(zé)注冊(cè)部分元數(shù)據(jù)操作废封。從調(diào)用的代碼可以看出,cls_client下函數(shù)不會(huì)直接執(zhí)行丧蘸,而通過librados::ObjectOperation的exec()執(zhí)行漂洋。在下一節(jié)可以看到,cls_client調(diào)用的操作在最終的OSDC層完成函數(shù)注冊(cè)力喷,但并不會(huì)實(shí)際調(diào)用刽漂。
需要注意的是,具體到image的創(chuàng)建弟孟,實(shí)際上只會(huì)記錄一些image的基本信息贝咙。比如創(chuàng)建元數(shù)據(jù)對(duì)象rbd_id.foo和rbd_header.foo,對(duì)于image的真正數(shù)據(jù)對(duì)象rbd_data*拂募,根本不會(huì)創(chuàng)建庭猩,這是因?yàn)閏eph選擇thin-provisioning這種凡事,可以做到秒級(jí)創(chuàng)建快設(shè)備陈症,后段也可以超額分配容量蔼水。
2.3 librados層:src/librados/
librbd中cls_client的注冊(cè)和回調(diào)函數(shù)的觸發(fā)都在librados中實(shí)現(xiàn)。
2.3.1 librados.cc / librados.h
librados組件提供了cls_client注冊(cè)函數(shù)需要的ObjectOperation的定義和接口實(shí)現(xiàn)录肯,和IoctxImpl相關(guān)函數(shù)接口的封裝趴腋。
cls_client調(diào)用的exec()函數(shù)的實(shí)現(xiàn)如下,函數(shù)中初始化ObjectOperationImpl實(shí)例嘁信,并調(diào)用其成員變量o的call()函數(shù)于样。
代碼中成員變量o的類型ObjectOperation來自雨OSDC層的Objecter組件,具體實(shí)現(xiàn)將在OSDC層中進(jìn)行進(jìn)一步討論潘靖。
librbd中穿剖,真正觸發(fā)回調(diào)函數(shù)是通過aio_operate()完成的,librados中提供了該接口卦溢,具體實(shí)現(xiàn)是封裝了IoctxImpl的aio_operate()接口糊余,最終實(shí)現(xiàn)是在IoctxImpl中完成。
2.3.2 IoctxImpl.cc
IoctxImpl中单寂,::ObjectOperation op實(shí)際上是引用的src/osdc/Objecter.cc里面定義的類贬芥,初始化之后,通過op將消息發(fā)送給osd宣决。真正使用osdc中的Objecter.cc中的組件的地方是operator()和aio_operate()函數(shù)蘸劈。
2.4 OSDC 層:src/osdc
osdc層直接與osd進(jìn)行通信,調(diào)用objecter.cc/objecter.h組件來實(shí)現(xiàn)消息的發(fā)送尊沸。
2.4.1 objecter.cc
objecter.cc提供對(duì)上層消息的封裝威沫,并將這些消息發(fā)送給osd贤惯,完成各項(xiàng)操作。
在librados層棒掠,cls_client調(diào)用的ObjectOperation的定義在objector.h中孵构。
代碼中各項(xiàng)成員變量的含義為
out_bl: 用于存放ops每個(gè)操作的輸出內(nèi)容
out_handler: 存放ops每個(gè)操作完成后執(zhí)行的回調(diào)函數(shù)
out_rval: 存放ops每個(gè)操作的返回值
librados層中注冊(cè)函數(shù)時(shí)調(diào)用的call函數(shù)的定義如下
add_op()為其核心操作,作用是將ops數(shù)組中增加一個(gè)op烟很,但不執(zhí)行操作颈墅。
最終的執(zhí)行操作是通過aio_operate()函數(shù)在osdc層調(diào)用的op_submit()函數(shù)完成的。
從上述代碼可以看出雾袱,在Objecter類中恤筛,遵循op_submit() -> _op_submit() -> _send_op()的調(diào)用順序。
3 備注
[注] 參考鏈接ceph-librbd-create-image.html
[注] 從相關(guān)資料描述來看谜酒,RadosClient是其核心管理類叹俏,處理Rados層和Pool層管理,但是在當(dāng)前的解析中并未體現(xiàn)RadosClient的作用僻族,需要進(jìn)一步的研究和分析。