背景
tcmu-runner在ceph iscsi gateway中是linux内核到ceph rbd间的桥梁,用于识别SCSI命令字,并根据命令字含义,调用librbd接口实现命令字的处理。详细描述见Ceph iSCSI Gateway:架构原理详解一文。
本文结论
- 设备添加
- 通过监听netlink识别iSCSI块设备添加。
- 添加过程中mmap共享内存(用于内核和用户态的命令字传输),并进行rbd_open。
- SCSI命令字处理
- 通过启动一个线程扫描mmap中为处理的命令字。
- 扫描到命令字后调用rbd相关接口处理。
- 处理完成后将处理结果和数据填写到mmap共享内存中。
- exclusive锁处理
- tcmu-runner采用了其中描述的显式加锁方法StandardPolicy。
- 一定不能将multipath配置成AA模式,配置成AA模式会导致exclusive-lock在不同的tcmu-runner客户端一直切换。
代码详解
创建块设备
通过netlink与内核configfs交互,当target中新增rbd image后,此tcmu-runner客户端会收到消息,并创建块设备。核心代码包括:
- 注册netlink
- 创建块设备
设置netlink
函数调用关系如下:
static struct genl_cmd tcmu_cmds[] = {
{
.c_id = TCMU_CMD_ADDED_DEVICE,
.c_name = "ADDED DEVICE",
.c_msg_parser = handle_netlink,
.c_maxattr = TCMU_ATTR_MAX,
.c_attr_policy = tcmu_attr_policy,
},
{
.c_id = TCMU_CMD_REMOVED_DEVICE,
.c_name = "REMOVED DEVICE",
.c_msg_parser = handle_netlink,
.c_maxattr = TCMU_ATTR_MAX,
.c_attr_policy = tcmu_attr_policy,
},
{
.c_id = TCMU_CMD_RECONFIG_DEVICE,
.c_name = "RECONFIG DEVICE",
.c_msg_parser = handle_netlink,
.c_maxattr = TCMU_ATTR_MAX,
.c_attr_policy = tcmu_attr_policy,
},
};
static struct genl_ops tcmu_ops = {
.o_name = "TCM-USER",
.o_cmds = tcmu_cmds,
.o_ncmds = ARRAY_SIZE(tcmu_cmds),
};
int main(int argc, char **argv)
tcmulib_initialize
setup_netlink
genl_register_family(&tcmu_ops); // 通过注册ops,在内核回调时进行相应处理。
添加块设备
在netlink回调之后,根据id执行添加device的流程。
handle_netlink
device_add
device_parse_cfg // 读取configfs中关于rbd image的相关配置
device_open_shm // 使用uio打开共享内存
tcmu_dev_get_memory_info // 获取内核创建的uio设备/sys/class/uio/%s/maps/map0/
mmap // 映射共享内存,有读写权限。
dev_added
...... // 创建命令字处理队列、锁、相关block属性
tcmu_rbd_open // 打开image,获取context
...... // 调用open前,配置image相关参数
tcmu_rbd_image_open
rados_create
rados_connect // 链接rados
rados_ioctx_create // 获取ioctx
rbd_open // 打开image,获取imagectx
tcmu_rbd_service_register // 注册cephmgr daemon
rbd_stat // 检查image状态
...... // 配置image一些属性,如granularity、cache等
pthread_create(tcmur_cmdproc_thread) // 启动监听uio共享内存中SCSI命令字线程。
SCSI命令字处理
在添加tcmu设备时,启动了uio共享内存的监听线程,循环获取命令字并进行后续处理。代码主要包括:
- 获取命令字。
- 命令字处理。
- 命令字处理结果返回。
获取命令字
tcmur_cmdproc_thread
while (1) { // 无限循环,如果没有命令字,就用ppoll机制等待。
tcmulib_get_next_command // 获取未处理的命令字
tcmur_generic_handle_cmd // 命令字处理
}
ppoll // 等待命令字
命令字处理
命令字包括write、read、unmap等多种,处理时调用rbd接口如下:
命令字 | tcmu-runner入口函数 | rbd接口 |
---|---|---|
READ | handle_read | rbd_aio_read/rbd_aio_readv |
WRITE | handle_write | rbd_aio_write/rbd_aio_writev |
UNMAP | handle_unmap | rbd_aio_discard |
SYNCHRONIZE_CACHE | handle_flush | rbd_aio_flush |
EXTENDED_COPY | handle_xcopy | rbd_aio_read/rbd_aio_readv + rbd_aio_write/rbd_aio_writev |
COMPARE_AND_WRITE | handle_caw | rbd_aio_compare_and_write |
WRITE_VERIFY | handle_write_verify | rbd_aio_write/rbd_aio_writev |
WRITE_SAME | handle_writesame | rbd_aio_writesame |
FORMAT_UNIT | handle_format_unit | rbd_aio_write/rbd_aio_writev |
下面以write为例进行代码梳理。
tcmur_cmd_handler
alua_check_state // 检查当前客户端是否拿到exclusive-lock,并进行相应处理
handle_write
aio_request_schedule // 由于rbd没有配置队列,因此直接执行写函数write_work_fn
write_work_fn
tcmu_rbd_write
tcmu_rbd_aio_write
rbd_aio_write
rbd_finish_aio_generic // rbd_aio_write后回调函数
tcmur_cmd_complete
handle_generic_cbk
aio_command_finish
tcmur_tcmulib_cmd_complete
tcmulib_command_complete
tcmu_sts_to_scsi // 将执行结果写入共享内存中,内核获取结果后返回
exclusive-lock
exclusive-lock是rbd的关键feature,用来保证不同客户端数据操作的互斥。详细分析见Ceph RBD:exclusize-lock代码详解 + 使用方法一文。tcmu-runner采用了其中描述的显式加锁方法StandardPolicy。
此外ceph-iscsi默认使用implicit alua配置,详见Ceph iSCSI Gateway:Multipath支持一文,本文后面的代码也基于此进行分析。
由于锁使用的是StandardPolicy,因此一定不能将multipath配置成AA模式,配置成AA模式会导致exclusive-lock在不同的tcmu-runner客户端一直切换。文章来源:https://www.toymoban.com/news/detail-523522.html
加锁流程
alua_check_state
alua_implicit_transition
alua_event_work_fn
tcmu_acquire_dev_lock
tcmu_rbd_lock
tcmu_rbd_lock_break // 调用rbd_aio_break,将所有io加入blacklist中。
rbd_lock_acquire // 调用rbd接口加锁,此处会将锁的policy强制从AutomaticPolicy设置为StandardPolicy。
参考文献
Ceph RBD:exclusize-lock代码详解 + 使用方法
Ceph iSCSI Gateway:Multipath支持
Ceph iSCSI Gateway:架构原理详解
TCMU学习笔记文章来源地址https://www.toymoban.com/news/detail-523522.html
到了这里,关于Ceph iSCSI Gateway:tcmu-runner代码原理详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!