Ceph iSCSI Gateway:tcmu-runner代码原理详解

背景

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接口
READhandle_readrbd_aio_read/rbd_aio_readv
WRITEhandle_writerbd_aio_write/rbd_aio_writev
UNMAPhandle_unmaprbd_aio_discard
SYNCHRONIZE_CACHEhandle_flushrbd_aio_flush
EXTENDED_COPYhandle_xcopyrbd_aio_read/rbd_aio_readv + rbd_aio_write/rbd_aio_writev
COMPARE_AND_WRITEhandle_cawrbd_aio_compare_and_write
WRITE_VERIFYhandle_write_verifyrbd_aio_write/rbd_aio_writev
WRITE_SAMEhandle_writesamerbd_aio_writesame
FORMAT_UNIThandle_format_unitrbd_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客户端一直切换。

加锁流程

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学习笔记

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值