眾所周知,cephfs的資料和後設資料是分離的,處於不同的pool池裡頭,而無論是rgw、cephfs、rbd底層的資料池的儲存都是基於RADOS(Reliable Autonomic Distributed Object Store),Ceph儲存叢集的基礎,RADOS層的一切都是以物件的形式儲存著的,無論上層是檔案、物件還是塊。
主要說說cephfs的檔案在資料池中是如何分佈的,下面以cephfs的核心客戶端為例進行分析。
以下圖檔案為例,先找到這個檔案的inode號1099511627776,轉換為16進製為10000000000,從資料池中找到這個物件,物件的名稱為檔案的inode號.編號(資料位置/物件大小object_size(預設4M),從0開始編號)
Cephfs讀資料轉換osd請求
struct ceph_file_layout {
/* file -> object mapping */
u32 stripe_unit; /* stripe unit, in bytes */
u32 stripe_count; /* over this many objects */
u32 object_size; /* until objects are this big */
s64 pool_id; /* rados pool id */
struct ceph_string __rcu *pool_ns; /* rados pool namespace */
};
檔案的layout的屬性,位於每個檔案的inode屬性中,是用來計算檔案實際物件分佈的條件。
客戶端(linux核心客戶端)位於檔案的擴充套件屬性xattr當中,通過set_xattr流程(客戶端入口函式__ceph_setxattr和服務端mds入口函式為Server::handle_client_setxattr)進行修改。
可以使用getxattr命令檢視預設值,命令和回顯如下:
getfattr -n ceph.file.layout ceph-debuginfo-Lakestor_v2.1.0.18-0.el7.x86_64.rpm
ceph.file.layout="stripe_unit=4194304 stripe_count=1 object_size=4194304 pool=cephfs-data”
讀流程從linux核心客戶端向osd服務端發起請求:
入口函式為
|__ceph_read_iter
|____ceph_get_caps(獲取檔案的cap,如果cap不滿足條件就傳送getattr的req向mds服務端去獲取最新的inode後設資料,服務端處理完成回請求時客戶端使用handle_reply最終fill_inode,將最新的後設資料資訊填寫到客戶端inode快取裡)
|______ceph_direct_read_write(如果客戶端dcache沒有對應位置快取,就向osd發請求獲取)
|__ceph_direct_read_write:
|____ceph_osdc_new_request(calc_layout-|______ceph_calc_file_object_mapping[ceph_oid_printf(&req->r_base_oid, "%llx.%08llx", vino.ino, objnum);])
|________ceph_osdc_start_request
...
|__ceph_osdc_new_request:
|____calc_layout(layout, off, plen, &objnum, &objoff, &objlen):
|______ceph_calc_file_object_mapping
重要入參:1,inode中的layout結構,2,要寫的偏移位置 off和3,要寫的長度plen。
出參:1,要寫的物件編號objnum,2,物件內的偏移objoff,。
|________ceph_oid_printf(&req->r_base_oid, "%llx.%08llx", vino.ino, objnum);(將inode號.物件編號拼接起來形成要寫的物件名)