mdt0
mdt0
是lustre元数据服务的注册开启的地方,注册处理客户端请求的各种handler
.mdt
初始化的通过mount
时候读取CONFIGS/{fsname}-MDT0000
文件数据进行mds obd
初始化,mds初始化的读取bigfs-MDT0000-mdtlov、bigfs-MDT0000(mdt0)、bigfs-OST0001(osc1)、bigfs-OST0002(osc2)
,用llog_reader
解析配置文件如下:// 通过llog_reader读取mdt的配置文件
$ llog_reader bigfs-MDT0000
// 这是rec的记录的长度和偏移量
rec #1 type=10620000 len=224 offset 8192
rec #2 type=10620000 len=136 offset 8416
rec #3 type=10620000 len=176 offset 8552
rec #4 type=10620000 len=224 offset 8728
rec #5 type=10620000 len=224 offset 8952
rec #6 type=10620000 len=120 offset 9176
rec #7 type=10620000 len=112 offset 9296
rec #8 type=10620000 len=160 offset 9408
rec #9 type=10620000 len=224 offset 9568
rec #10 type=10620000 len=224 offset 9792
rec #11 type=10620000 len=80 offset 10016
rec #12 type=10620000 len=144 offset 10096
rec #13 type=10620000 len=144 offset 10240
rec #14 type=10620000 len=136 offset 10384
rec #15 type=10620000 len=224 offset 10520
rec #16 type=10620000 len=224 offset 10744
rec #17 type=10620000 len=80 offset 10968
rec #18 type=10620000 len=144 offset 11048
rec #19 type=10620000 len=144 offset 11192
rec #20 type=10620000 len=136 offset 11336
rec #21 type=10620000 len=224 offset 11472
// 这里是mds端初始化的需要的配置
Header size : 8192 llh_size : 80
Time : Wed Oct 19 03:08:38 2022
Number of records: 21 cat_idx: 0 last_idx: 21
Target uuid : config_uuid
-----------------------
#01 (224)marker 2 (flags=0x01, v2.15.0.0) bigfs-MDT0000-mdtlov 'lov setup' Wed Oct 19 03:08:38 2022-
#02 (136)attach 0:bigfs-MDT0000-mdtlov 1:lov 2:bigfs-MDT0000-mdtlov_UUID
#03 (176)lov_setup 0:bigfs-MDT0000-mdtlov 1:(struct lov_desc)
uuid=bigfs-MDT0000-mdtlov_UUID stripe:cnt=1 size=1048576 offset=18446744073709551615 pattern=0x1
#04 (224)END marker 2 (flags=0x02, v2.15.0.0) bigfs-MDT0000-mdtlov 'lov setup' Wed Oct 19 03:08:38 2022-
#05 (224)marker 3 (flags=0x01, v2.15.0.0) bigfs-MDT0000 'add mdt' Wed Oct 19 03:08:38 2022-
#06 (120)attach 0:bigfs-MDT0000 1:mdt 2:bigfs-MDT0000_UUID
#07 (112)mount_option 0: 1:bigfs-MDT0000 2:bigfs-MDT0000-mdtlov
#08 (160)setup 0:bigfs-MDT0000 1:bigfs-MDT0000_UUID 2:0 3:bigfs-MDT0000-mdtlov 4:f
#09 (224)END marker 3 (flags=0x02, v2.15.0.0) bigfs-MDT0000 'add mdt' Wed Oct 19 03:08:38 2022-
#10 (224)marker 9 (flags=0x01, v2.15.0.0) bigfs-OST0001 'add osc' Wed Oct 19 03:08:38 2022-
#11 (080)add_uuid nid=10.211.55.5@tcp(0x200000ad33705) 0: 1:10.211.55.5@tcp
#12 (144)attach 0:bigfs-OST0001-osc-MDT0000 1:osc 2:bigfs-MDT0000-mdtlov_UUID
#13 (144)setup 0:bigfs-OST0001-osc-MDT0000 1:bigfs-OST0001_UUID 2:10.211.55.5@tcp
#14 (136)lov_modify_tgts add 0:bigfs-MDT0000-mdtlov 1:bigfs-OST0001_UUID 2:1 3:1
#15 (224)END marker 9 (flags=0x02, v2.15.0.0) bigfs-OST0001 'add osc' Wed Oct 19 03:08:38 2022-
#16 (224)marker 12 (flags=0x01, v2.15.0.0) bigfs-OST0002 'add osc' Wed Oct 19 03:08:38 2022-
#17 (080)add_uuid nid=10.211.55.5@tcp(0x200000ad33705) 0: 1:10.211.55.5@tcp
#18 (144)attach 0:bigfs-OST0002-osc-MDT0000 1:osc 2:bigfs-MDT0000-mdtlov_UUID
#19 (144)setup 0:bigfs-OST0002-osc-MDT0000 1:bigfs-OST0002_UUID 2:10.211.55.5@tcp
#20 (136)lov_modify_tgts add 0:bigfs-MDT0000-mdtlov 1:bigfs-OST0002_UUID 2:2 3:1
#21 (224)END marker 12 (flags=0x02, v2.15.0.0) bigfs-OST0002 'add osc' Wed Oct 19 03:08:38 2022-
[root@CentOS-Lustre-Server /mnt/mgt_mdt/CONFIGS]$
mdt_init0
的核心逻辑负责初始化mdt
的obd stack
操作栈,如下是mdt0
初始化的核心函数,这个做了mdt操作栈初始化->fld的初始化->seq初始化->注册intent回调函数->io表初始化->mds faiover的rpc设置->设置参数调整的函数表->quota初始化->分布式锁客户端初始化->lustre客户端驱逐服务
等核心逻辑的初始化static int mdt_init0(....)
{
// 根据obd name查找挂在点,返回lustre_mount_info信息
server_get_mount(dev);
// 根据CONFIGS/{fsname}-MDT0000 初始化mdt的操作栈
mdt_stack_init((struct lu_env *)env, m, cfg);
// mdt fid存储数据库初始化
mdt_fld_init(env, mdt_obd_name(m), m)
{
fld_server_init(...)
}
// mdt中seq_controller和seq_server的初始化
mdt_seq_init(env, m)
{
// seq_controller服务初始化
seq_server_init(LUSTRE_SEQ_CONTROLLER,...);
// seq_server的初始化
seq_server_init(LUSTRE_SEQ_SERVER,...);
// seq_server通过seq_client来和seq_controller交互
mdt_seq_init_cli(env, mdt);
}
// 设置intent锁的回调函数
ldlm_register_intent(m->mdt_namespace, mdt_intent_policy);
// mdt请求处理函数,各种请求处理handler的注册
tgt_init(...);
// mdt中事务的回调函数初始化
mdt_fs_setup(env, m, obd, lsi);
// 初始化mds端本地oi表
local_oid_storage_init(env, m->mdt_bottom, &fid, &m->mdt_los);
// mds中rpc failover的设置
tgt_adapt_sptlrpc_conf(&m->mdt_lut);
// mds端参数设置的初始化,设置参数设置的操作函数
mdt_tunables_init(m, dev);
// mdt quota的初始化
mdt_quota_init(env, m, cfg);
// mdt端分布式锁的客户端初始化
ptlrpc_init_client(LDLM_CB_REQUEST_PORTAL, LDLM_CB_REPLY_PORTAL,
"mdt_ldlm_client", m->mdt_ldlm_client);
// lustre客户端驱逐的服务初始化
ping_evictor_start();
}
mds
的整体OBD Stack
如下:文件创建
链路实现lookup
过程lookup
过程做了几个事情,第一是查看root
节点的信息;第二是父目录的meta信息;第三父目录加锁的过程;第四是在父目录中查找新文件的fid
int mdt_reint_open(struct mdt_thread_info *info, struct mdt_lock_handle *lhc)
{
// 查找root节点信息,根据请求加锁
result = mdt_lock_root_xattr(info, mdt)
{
md_root = mdt_object_find(...)
{
o = lu_object_find(...)
{
lu_object_find_at(...)
}
}
}
// 查找新文件的父目录meta信息,其定义结构为struct mdt_object
parent = mdt_object_find(...)
{
o = lu_object_find(...)
{
lu_object_find_at(...)
}
}
// 加锁:检查父目录下的文件是否存在,如果存在则在父目录存在添加LCK_PR锁;否则添加LCK_PW,新文件是第一创建,所以会在父目录加CK_PW锁
lock_mode = mdt_open_lock_mode(...)
{
mdo_lookup(...)
{
mdd_lookup(...)
{
__mdd_lookup(...)
{
// dt_lookup 根据文件名称查找dentry从中获取到inode,如果inode存在从inode获取fid信息,从inode扩展属性中获取fid
osd_index_ea_lookup(...)
{
osd_ea_lookup_rec(...)
}
}
}
}
}
// 这里查找新文件是否存在,这里有一个疑惑,父目录已经能判断出新文件是否存在,这里为何还要查找一次
result = mdo_lookup(info->mti_env, mdt_object_child(parent),
&rr->rr_name, child_fid, &info->mti_spec)
{
// 查找新创建的目标文件,如果存在返回0,否则返回其他
mdd_lookup(...)
{
__mdd_lookup(...)
{
// 注意新文件在父目录里压根不存在
dt_lookup(...)
{
// 根据文件名称查找dentry从中获取到inode,如果inode存在从inode获取fid信息
osd_index_ea_lookup(...)
{
osd_ea_lookup_rec(...)
}
}
}
}
}
}
result = mdo_create(....);
rc = mdt_finish_open(...);
}
create
过程create
阶段是做了几个事情,第一是获取root节点的信息,第二是获取新文件的父目录meta,第三查看目标文件是否存在,第四是创建新文件的meta信息;第五是开启事务准备写入新文件meta信息,最后完成新文件创建成功后续操作。这个过程非常复杂,核心的设计理念可以理解为虚函数(函数指针)int mdt_reint_open(struct mdt_thread_info *info, struct mdt_lock_handle *lhc)
{
/***************这是lookup过程***************/
// 查找root节点信息,根据请求加锁
result = mdt_lock_root_xattr(info, mdt)
// 查找新文件的父目录meta信息
parent = mdt_object_find(...)
// 加锁:检查父目录下的文件是否存在,如果存在则在父目录存在添加LCK_PR锁;否则添加LCK_PW,新文件是第一创建,所以会在父目录加CK_PW锁
lock_mode = mdt_open_lock_mode(...)
// 这里查找新文件是否存在
result = mdo_lookup(info->mti_env, mdt_object_child(parent),
&rr->rr_name, child_fid, &info->mti_spec)
/***************这是create过程***************/
// 这里是创建新文件的meta
child = mdt_object_new(info->mti_env, mdt, child_fid)
{
lu_object_find(...)
{
// 这里调用的是 lu_object_alloc 实际call的是mdt_object_alloc
lu_object_find_at(...)
{
lu_object_alloc(...){
mdt_object_alloc(...){
// lu_object_init实际调用的是mdt_object_init
mdt_object_init(...){
// call ldo_object_alloc
mdd_object_alloc(...)
}
}
}
lu_object_start(env, dev, o, conf)
{
loo_object_init(...)
{
// loo_object_init
mdt_object_init(...)
{
//ldo_object_alloc
lod_object_alloc(...)
{
lu_object_init(...)
}
}
// loo_object_init
lod_object_init(...)
{
lod_fld_lookup(...)
{
fld_server_lookup(....)
{
fld_local_lookup(...)
}
}
// ldo_object_alloc
osd_object_alloc(...)
{
dt_object_init(...)
}
}
osd_object_init(...)
}
}
loo_object_start(...)
{
mdd_object_start(....)
}
}
}
}
result = mdo_create(info->mti_env, mdt_object_child(parent),
&rr->rr_name, mdt_object_child(child),
&info->mti_spec, &info->mti_attr);
{
// mdo_create实际调用mdd_create
mdd_create(...)
{
// 执行事务
handle = mdd_trans_create(env, mdd)
{
// dt_trans_create
osd_trans_create(...)
}
// 准备文件的link属性,link属性包含了父目录的fid和自身文件名称
// parent-fid=[0x200000007:0x1:0x0],filename=demo1.txt
rc = mdd_linkea_prepare(...);
rc = mdd_declare_create(...)
{
mdd_declare_create_object(...)
{
// 这个函数准备
mdd_declare_create_object_internal(...)
{
mdo_declare_create_object(...)
{
// dt_declare_create call do_declare_create
osd_declare_create(...)
//
mdo_declare_xattr_set(...)
{
// 这个函数内调用dt_declare_attr_set函数指针
lod_declare_attr_set(...)
{
// 获取每个ost的容量信息,通过lod_ost_alloc_rr函数决定数据应该写到哪个ost上
lod_declare_striped_create(...)
}
}
}
}
}
}
// 开启事务准备写入
rc = mdd_trans_start(env, mdd, handle)
{
// 执行dt_trans_start函数指针,写入mds端的数据时候的事务
top_trans_start(...)
{
// 开启mds端osd的事务
osd_trans_start(...)
}
}
rc = mdd_create_object(...)
{
mdd_create_object_internal(...)
{
// mdo_create_object->dt_create
lod_create(...)
{
lod_sub_create(...)
{
// dt_create
osd_create(...)
{
fid_is_on_ost()
osd_ea_fid_set()
__osd_oi_insert()
{
osd_oi_insert()
}
osd_idc_find_and_init()
}
}
lod_striped_create()
{
for (j = 0; j < lc_stripe_count; j++)
{
lod_sub_create()
{
// dt_create指向osp_create
osp_create(...)
}
}
lod_generate_and_set_lovea()
{
lod_generate_lovea(...)
lod_sub_xattr_set(XATTR_NAME_LOV)
{
// dt_xattr_set函数指针,设置文件的trusted.lov
osd_xattr_set(...)
}
}
}
}
}
mdd_object_initialize(...)
}
__mdd_index_insert(...)
{
__mdd_index_insert_only()
{
// dt_insert函数指针
osd_index_ea_insert()
}
}
mdd_links_add(...)
{
mdd_links_rename()
{
mdd_links_write(){
// mdo_xattr_set 函数指针
lod_xattr_set()
{
// lod_sub_xattr_set函数指针
lod_xattr_set_internal()
{
lod_sub_xattr_set()
{
// dt_xattr_set
// 设置文件的trusted.link
osd_xattr_set()
}
}
}
}
}
}
}
mdd_changelog_ns_store(...)
mdd_trans_stop(...)
{
top_trans_stop()
{
osd_trans_stop()
}
}
}
rc = mdt_finish_open(...)
{
mdt_mfd_open(...)
{
// mo_open
mdd_open()
mdt_mfd_new()
}
}
}
文件创建
链路实现tgt_request_handle
进行处理.MDS端把文件对应的元数据存储后,通过MDS的osp
请求发送到ost端,ost处理对应的请求.// 内核线程启动ptl_main函数接受来自rpc的请求,然后进行处理
static int ptlrpc_main(void *arg)
{
while (!ptlrpc_thread_stopping(thread)))
{
// 请求数据处理函数
ptlrpc_server_handle_request(...)
{
// 函数指针 so_req_handler
tgt_request_handle(...)
{
target_handle_connect(...)
{
// obd_connect函数指针
ofd_obd_connect(...)
{
tgt_client_new(...)
{
// 写入新文件对应的对象分片
tgt_client_data_update(...)
{
//dt_trans_create函数指针
osd_trans_create(...)
//dt_declare_record_write函数指针
osd_declare_write(...)
// dt_trans_start_local函数指针
osd_trans_start(...)
tgt_client_data_write(...)
// dt_trans_stop函数指针
osd_trans_stop(...)
}
}
}
}
}
}
}
}