iscsi:IO操作流程(一)
从应用的视角,iscsi展现为一个块设备,即一块硬盘。在Linux操作系统中可以通过fdisk -l
看到这块磁盘。iscsi协议所涉及的一系列的组件经过层层虚拟化,在多个层次上其操作与本地硬盘无异。这实际上是一个性能、可靠性、实现多个角度权衡的结果。事实上,在所经历的各层次中,有一些次层对于iscsi磁盘来说是多余的,但操作系统的设计者为了共用SCSI实现层,将scsi initiator对接到SCSI中间层以下,作为一个scsi传输层实现。因此,自scsi层以上,iscsi提供的块设备与sas、SATA提供的块设备所经历的IO流转一致。
本文所涉及的iscsi集中考虑iscsi协议承接块设备应用说起。事实上,iscsi作为一个承载SCSI协议的传输层,除能够支持基于磁盘价值的块设备外,还可以支持其他的SCSI设备。比如磁 带、CDROM。业界也有通过iscsi实现为磁带的应用,如VTL。虚拟为其他设备时,其IO流转略有区别。scsi子系统通过
INQUIRY
探测LUN的设备类型,进而由上层驱动“认领”对应的设备。
用户的数据在initiator节点上依次经过文件系统层、块设备层、SCSI层。理论上我们也可以将通过裸scsi设备直接发送IO相关SCSI指令到SCSI中间层,但这条路径的初衷并非如此,没有针对IO处理进行优化。故只在上图中表示出来,并不做具体分析。
文件系统、裸设备在应用角度,其一般流程均为:
- 打开文件,获得句柄(系统调用open
)
- 一次或多次以字节为单位对文件进行读写(系统调用read
、write
)
- 关闭文件(系统调用close
)
应用的IO请求通过系统调用到达内存。在适合当的时机,操作系统会将上述操作构建为bio结构,调用submit_bio
将请求传递到通用块层。bio
是通用块核心的IO处理单元。bio
核心表达的是数据在内存和在磁盘中的映射关系。其中,
缓存中的地址以内存页号和页面偏移表示。以struct bio_vec
表达:
struct bio_vec {struct page *bv_page; /*存储数据的页面*/unsigned int bv_len; /*数据长度*/unsigned int bv_offset; /*数据在页面中的偏移*/
};
在磁盘上的地址以bvec_iter
表达:
struct bvec_iter {sector_t bi_sector; /* device address in 512 byte sectors */unsigned int bi_size; /* residual I/O count */unsigned int bi_idx; /* current index into bvl_vec */unsigned int bi_done; /* number of bytes completed */unsigned int bi_bvec_done; /* number of bytes completed in current bvec */
};
在新的内核版本中,对
bio
数据结构进行了一些调整。老的版本中扇区号、扇区数等信息直接放在bio
成员中。新的版本中将其集中放到bev_iter
中。此变化不影响bio
在设计中的位置
submit_bio
最终调用generic_make_request
函数将bio
插入到请求队列。generic_make_request
接收一个bio
组成的链表,并对其进行分个处理。对于每个bio首先进行一系列应用的检查,然后调用具体块磁盘驱动的make_request_fn
进行处理。scsi磁盘驱动初始化的过程中,将make_request_fn
直接指定为blk_queue_bio
。这个函数根据内核配置的IO电梯算法,将IO拆分合并到请求队列中。
上述的故事就是大家耳熟能祥的IO缓存与IO调度。在此不详细描述。可以参考其他资料研究buffer cache以及电梯调度算法相关的算法。转到iscsi实现的角度。initiator的处理过程并不需要电梯算法。毕竟到目前为止,我们数据离落盘还有很远很远。况且系统数据落盘是在target端进行,在initiator端进行电梯算法意义不大,target端有可能对数据进行重新散列,当下排序也用的LBA还需要经过再次映射,逻辑上相邻不代表物理是想邻。
还是那句话,在iscsi流程过程中,之所以将这些流程纳入,完全是一种设计的权衡、抽象的哲学问题。
我们的故事刚刚开始。
自sd设备驱动开始,便进入SCSI处理的流程。也即iscsi相关语境的上下文。从此刻,系统要回答的问题有以下几方面:
1. IO如何封装成scsi指令,封装成什么样的scsi指令
2. IO如何根据设备的特点构建任务,经过协议所定义的host、taget、lun等相应的处理
3. IO处理过程中的异常采用什么方式,以什么形式报告给initiator等
sd实现了一个块设备(drivers/scsi/sd.c)用以接受IO请求,并最终调用scsi_setup_fs_cmnd
将请求向scsi_cmd
转换,进而分发到scsi中间层进行处理。scsi中间层可以理解为SCSI处理的一个框架实现,提供了SCSI系统初始化、设备扫描、SCSI命令调度执行以及错误恢复框架等。从IO角度,SCSI中间层主要是接受IO相关的SCSI指令,进一步完善相应用的信息,调用scsi_dispatch_cmd
传递到下层进行处理。
最终的scsi指令的执行是在target端进行。scsi transport层是负责SCSI指令传输的,像SAS、FC、iscsi等都是传输层的具体实现。传输层有对应的协议实现,其核心实现思路是scsi请求进行的封装。上述的SCSI命令只是scsi请求的一个方面,除此之外还有目的LUN、任务管理、数据等信息,具体信息可参考SAM相关文档。一个SCSI的具体执行可以形式性的表达为:
Service Response =Execute Command (IN ( I_T_L_Q Nexus, CDB, Task Attribute, [Data-In Buffer Size],
[Data-Out Buffer], [Data-Out Buffer Size], [Command Reference Number], [Task
Priority]), OUT ( [Data-In Buffer], [Sense Data], [Sense Data Length], Status ))
一个SCSI指令相关的请求在传输层被称为一个task(任务),当SCSI命令被发送到scsi传输协议服务系统时,任务被建立。任务用于管理SCSI在传输层流转的一系列状态信息。当SCSI target返回响应之后task重命周期完成。一个传输任务可分为一个或者多个数据包传输给target。在iscsi协议中用PDU表示每个数据包。iscsi协议是scsi传输层的具体实现,它实现的了initiator与target间的认证、会话建立、数据联接管理、数据传输、任务控制、数据安全等一系列的服务。iscsi采用PDU描述传输数据包,是iscsi层各节点间交互的基本单位,iscsi协议是scsi传输层的具体实现。iscsi PDU将使TCP协议或者其它流式协议进行传输。在Linux系统中实现了iscsi_tcp
和iscsi_iser
两个传输模块。
以上就是Linux内核中iscsi协议initiator端实现的具体流程,流转过程中,一个IO请求自上而下经历了bio
、request
、scsi_cmd
、iscsi_task
以及iscsi hdr
(PDU)等变化。
思考:
本文提到为了系统实现概念的统一性、设计的一致性以及层次抽象与共用,操作系统将iscsi协议对接到scsi中间层。这种实现对性能的损失有多大?如果我们在device-mapper之下实现又会怎么样?欢迎讨论。
iscsi:IO操作流程(一)相关推荐
- iscsi:IO操作流程(四)
系统构建SCSI指令后,将调用scsi_host的queucommand操作,将指令下移到LLD设备层进行处理. scsi_host在iscsi协议中的角色 scsi_host在系统中启动承上启下的作 ...
- iscsi:IO操作流程(五)——IO完成处理
概述 前面讲到,iscsi initiator实现过程采用了多级的异步模式,通过异步模式使IO操作阶段能够批量处理.这种异步机制的存在主要为了提升系统的吞吐量.从设计的角度,考虑采用异步操作机制的任务 ...
- iscsi:IO操作流程(二)
上次我们讨论了iscsi initiator IO操作需要经过的各个层次,以及每层所涉及的IO数据结构的变化.今天主要讨论IO如何形成SCSI指令并下发的. 我们知道在通用块层,IO最终放在reque ...
- iscsi:IO操作流程(三)
概述 当我们讲到scsi命令这个概念时,需要根据上下文去理解.可能指代两个概念: - 一种含义指SCSI协议规划中定义的SCSI 命令描述块(Command descriptor block (CDB ...
- 网易数帆开源iSCSI服务器tgt独门优化,彻底解决性能问题
iSCSI是现代企业级存储系统中的一项重要技术, 开源iSCSI 服务器tgt存在单线程性能问题,而相关的优化补丁效果参差不齐,尚未真正解决问题,本文介绍网易数帆存储团队如何通过一系列独特的创新实现t ...
- 【死磕NIO】— 阻塞IO,非阻塞IO,IO复用,信号驱动IO,异步IO,这你真的分的清楚吗?
通过上篇文章([死磕NIO]- 阻塞.非阻塞.同步.异步,傻傻分不清楚),我想你应该能够区分了什么是阻塞.非阻塞.异步.非异步了,这篇文章我们来彻底弄清楚什么是阻塞IO,非阻塞IO,IO复用,信号驱动 ...
- 【翻译】QEMU内部机制:顶层概览
系列文章: [翻译]QEMU内部机制:宏观架构和线程模型 [翻译]QEMU内部机制:vhost的架构 [翻译]QEMU内部机制:顶层概览(本文) [翻译]QEMU内部机制:内存 原文地址:http:/ ...
- java程序课程总结_java课程总结
课程总结 一个学期结束了,下面我对一些重点知识分三个模块做一个小的总结. 一.Java基础程序设计 1.java中源文件的扩展名为.java,之后通过编译是.java的文件生成一个.class文件. ...
- java NIO入门小记
传统的IO模式 传统的IO流是阻塞式的,会一直监听一个ServerSocket,在调用read等方法时,他会一直等到数据到来或者缓冲区已满时才返回.调用accept也是一直阻塞到有客户端连接才会返回. ...
最新文章
- 基于python的大数据分析实战学习笔记-pandas(数据分析包)
- 使用struts 2 获取服务器数据 ongl表达式 标签
- 201621123023《Java程序设计》第7周学习总结
- 配置php.ini文件,关闭错误提示,打开错误日志,设置错误日志路径(亲测)
- python如何计算分子描述符_Python——描述符(descriptor)解密
- 学习笔记之四_Cisco系统IOS和安全设备管理系统SDM(CCNA知识考点)
- H5 使用微信开放标签跳转小程序
- scala(10)-----Scala 闭包
- 电流感应电阻器行业调研报告 - 市场现状分析与发展前景预测(2021-2027年)
- 极简Markdown程序员简历模板
- 黑客使用浏览器中的浏览器技术窃取Steam凭证
- 攻防世界题库logmein
- 德赛西威Mib280D升级0393版本系统
- 【论文笔记】Learning Convolutional Networks for Content-weighted Image Compression
- doodoo.js快速入门教程
- 火车票订票小助手,帮助了很多同事和朋友,安全无毒
- java_vinson_02:jdk下载安装
- 文本生成视频Make-A-Video,根据一句话就能一键生成视频 Meta新AI模型
- 【无标题】汇编实现从键盘输入并输出
- PostgreSQL 技术文档
热门文章
- Xcode 静态库调试策略
- WEB-INF/views/menu/list.jsp (line: 26, column: 58) equal symbol expected
- 华中邀请赛现场赛F题 Seats
- 微型计算机的主要,微型计算机组成,微型计算机主要由什么组成
- c语言CString转数字函数,CString与16进制的CByteArray之间相互转化
- python数字类型及运算_Python数据类型之数字(Numbers)和运算符
- qbittorrent container 改共享文件_SSH连接docker中的container
- Python批量检查docx文档中文本框的内容是否正确
- C++ STL容器之string--常用接口
- Python字符串的替换