概述

当我们讲到scsi命令这个概念时,需要根据上下文去理解。可能指代两个概念:
- 一种含义指SCSI协议规划中定义的SCSI 命令描述块(Command descriptor block (CDB))。此描述块定义了需要target处理的具体的操作。遵循特定的数据格式,其格式根据操作的不同而不同。SCSI规范中针对每个命令的CDB都有详细的说明。描述块会经过传输层完整的传送到scsi target用于解析并执行。
- 另外一种含义指内核中定义的scsi_cmnd结构。该结构定义于linux/include/scsi/scsi_cmnd.h中,描述了请求在SCSI子系统执行所需要的数据结构。每个请求都会创建一个scsi_cmnd数据结构。它创建于请求的初始化,结束于命令被正确的执行或者在操作中出现错误。其存储的信息不仅仅包括了最终发送给scsi target的数据,也包括了在scsi子系统和scsi底层驱动执行中需要的运行时信息。

CBD格式

随着技术的发展 ,存储设备的容量持续增长。原有的SCSI指令的寻址空间不能满足新的要求,于是就定了新的可支持更大空间的CBD格式。考虑到向前兼容,SCSI协议没有取消原有的指令,而是重新定义操作码。于是,针对一种服务(如读、写)定义了多种指令格式。
CBD格式分为定长格式和变长格式。
定长格式的CBD包括6、10、12、16四种格式,数字表示CBD的长度(单位:字节)。所有定长指令的第一个字节均为操作码,最后一个字节为控制块。其它域取决于指令。
变长格式,其长度取决于具体的指令。如READ(32)、WRITE(32)分别为32字节。变长格式第一个字节为操作码,固定为操作码(7Fh),其具体服务(如读、写)放在SERVICE ACTION域,即CBD的第8、第9字节。变长格式的前10个字节是固定的。
无论是定长格式还是变长格式,都包括固定部分,即所有的指令都有的。这样有利于程序设计。系统可以将CBD前几个字节进行统一的解析,再进一步的根据操作码判断后面是否有数据段需要进一步解析。
CDB在内核中表现为一个连续的内存空间。通常它的存储空间在请求初始化时被创建,随着请求完成被释放。请求初始化过程中给cmnd分配了16个字节。
当CDB长度大于32时,驱动程序它初始化时创建的专用缓存池sd_cdb_pool上申请。

读命令分析

定长读命令

READ读命令可以分成两种格式。READ(10)、READ(12)、READ(16)格式一致,归为第一类。READ32归为第二类。
READ(10)、READ(12)、READ(16)所包括的属性一致。两者别在于LBA与数据传输字节数两个字段的长度,这两个字段长度决定了SCSI指令所能支持的最大容量和一次IO最大的数据长度。自SCSI-3始,规范建议实现方将READ(10-12)迁移到READ16上。
READ(16) CBD格式如下图:

各个字段含义:

字段 含义 实现
OPERATION CODE 指令操作码|调用sd_setup_read_write_cmnd设定
RDPROTECT DIF支持相关属性 调用sd_setup_read_write_cmnd设定;设定值取决于磁盘DIF保护方式
DPO 禁用页面缓存(Disable Page Out)。
设定1意为执行此操作时,不进行缓存替换
设定为0意为读取时同时在设备缓存中保留此数据
Linux永远设为0
FUA 强制访问介质。
如果设定为1,意味着target强制从介质中读取数据,而非从缓存中
在构造IO请求(struct request)时根据应用要求设置;
RARC 重构辅助模式。 scsi层未处理
LOGICAL BLOCK ADDRESS 读命令的起始地址 与请求的起始地址一致。以扇区(512字节)为单位
TRANSFER LENGTH 读写数据长度 与请求的读写长度一致
CONTROL 命令控制块 SCSI子系统未设定

变长读命令

变长由自第12字节始的8字节表示LBA,由第28字节始的4个字节表示数据长度。其支持的最大容量与最大扇区数与READ16相同。其它变量的含义与READ(16),不详细解释。
比定长CBD多出来的字节主要是用于数据校验。T10是用于解决静默错误的一种机制。
数据在读写环境中要经过多个部件、多个传输渠道和多层次的软件系统,考虑到性能,系统设计过程中并非每层次都对数据进行检测。如此,最终固化的到磁盘上的数据可能是不正确的。为避免此类错误存在,ANSI T10 定义了一种通过对每个数据块加入保护信息(PI:Protection Information)也曾被称作数据完整性域(DIF:Data Integrity Field)的方法来保护数据完整性。只有开启T10信息检验且采用type2 保护信息时,才使用READ(10)命令格式。
P10在企业Oracle数据库应用比较广泛,且是存储一大亮点,所以主流的存储厂商都支持该特性,如EMC VNX系列支持自定义PI、VMAX支持标准的T10 PI,且支持DIX;HDS HUS系列支持自定义PI、HDS VSP支持PI;IBM DS8000支持标准的T10 PI,DS5000某些特定型号支持PI;HP P10000支持标准的T10 PI,华为 OceanStor 18000和V3全系列。 1

写命令分析

写命令与读命令在格式上非常相似,也分为多种格式。

不同的写操作对应的服务是一致的。在Target端可对应于相同的实现。以WRITE(10)为例。其操作码为24A。同时,也包括了用于DIF处理的WRPROTECT域,用于缓存控制的DPO、FUA域。

scsi_cmnd

scsi_cmnd结构体记录了scsi_cmnd需要处理的所有的上下文。系统在初始化request时就为scsi_cmnd申请空间。当request在子系统处理完成,scsi上层驱动根据request创建scsi_cmnd。面向IO的scsi_cmndrequest是一对一的关系。
scsi_cmnd包含了scsi指令处理所需要的信息,包括CBD、数据、sense data等域。除此之外,还包括一些控制域。
scsi_cmnd包含了scsi设备的相关信息,用于确定交scsi_cmnd针对于哪个设备。在
scsi_cmnd流转时,设备类型相关的逻辑处理完成,系统更加关注指令和数据在通信链路上的流转。即关注总线、主机适配器、传输层等信息。
scsi_cmnd生命周期中可能被挂接到多个不同的队列,代表不同的控制面。大多数据情况,scsi_cmnd链接到主机适配器的命令处理队列中;在处理过程发生故障时,它又被错误处理相关的队列中暂存,一旦故障恢复,再进行继续处理;如果因为设备忙等原因,主机适配器不能接收scsi命令时,scsi_cmnd将放到延时处理链表中,等合适的时机再行处理。



  1. http://blog.csdn.net/swingwang/article/details/61661117 ↩

iscsi:IO操作流程(三)相关推荐

  1. iscsi:IO操作流程(四)

    系统构建SCSI指令后,将调用scsi_host的queucommand操作,将指令下移到LLD设备层进行处理. scsi_host在iscsi协议中的角色 scsi_host在系统中启动承上启下的作 ...

  2. iscsi:IO操作流程(五)——IO完成处理

    概述 前面讲到,iscsi initiator实现过程采用了多级的异步模式,通过异步模式使IO操作阶段能够批量处理.这种异步机制的存在主要为了提升系统的吞吐量.从设计的角度,考虑采用异步操作机制的任务 ...

  3. iscsi:IO操作流程(二)

    上次我们讨论了iscsi initiator IO操作需要经过的各个层次,以及每层所涉及的IO数据结构的变化.今天主要讨论IO如何形成SCSI指令并下发的. 我们知道在通用块层,IO最终放在reque ...

  4. iscsi:IO操作流程(一)

    从应用的视角,iscsi展现为一个块设备,即一块硬盘.在Linux操作系统中可以通过fdisk -l看到这块磁盘.iscsi协议所涉及的一系列的组件经过层层虚拟化,在多个层次上其操作与本地硬盘无异.这 ...

  5. IO流 (三) ----- 字符流和字符缓冲流

    相关文章: <IO流 (一) ----- 基本概念和File类> <IO流 (二) ----- 文件流> <IO流 (三) ----- 字符流和字符缓冲流> < ...

  6. 打怪升级之小白的大数据之旅(二十五)<Java面向对象进阶之IO流三 其他常见流>

    打怪升级之小白的大数据之旅(二十五) Java面向对象进阶之IO流三 其他常见流 上次回顾 上一章,我们学习了常用的字节流与字符流,本章,我会将其他的一些常见的流进行分享,IO流很多,我介绍不完,就挑 ...

  7. Java IO 体系(三):Reader与Writer

    正文 本篇讲述的是Java IO中的Reader类和Writer类.跟之前讲述的InputStream和OutputStream一样为IO流中的抽象父类之一,不过Reader和Writer的操作对象不 ...

  8. 变通实现微服务的per request以提高IO效率(三)

    效率 变通实现微服务的per request以提高IO效率(二)遗留一个问题,如何正确的释放存储在ThreadLocal中的缓存,最理由就是在我们请求的方法执行完成后去清除缓存. Filter 由于我 ...

  9. Java中IO(三、转换流与打印流)

    InputStreamReader是从字节流到字符流的桥梁,它读取字节并使用指定的字符集将其解码为字符,通常将InputStreamReader包装在BufferedReader中使用.PrintSt ...

最新文章

  1. Calendar使用方法
  2. 创建emp表 oracle,Oracle中创建和管理表详解
  3. 用JavaScript玩转游戏物理(一)运动学模拟与粒子系统
  4. 强制修改上网本分辨率
  5. 双十一消费近万亿!1亿人见证数字物流,“尾款人”收货更快了?购物狂欢七大趋势浮现
  6. 面试题 04.06. 后继者
  7. mysql导入 内存溢出_Solr Dataimporthandler 导入MySQL 内存溢出。
  8. VC6编辑直接采用Linux换行符,Tips: VC++篇
  9. 树莓派系统的安装、初步配置与远程访问
  10. html静态页面作跳转
  11. 软件项目管理期末复习题
  12. windows7配置java环境变量
  13. 计算机常用的采样频率,采样频率
  14. pythonexcel怎么读_python怎么读excel
  15. java 匿名邮件_java开发邮件发送(匿名)
  16. 安装了本地MySQL后,小皮面板上的MySQL就一直启动失败
  17. 数字化转型不给力?你可能少了vPro这样的“芯”动力
  18. VS2008 LINK : fatal error LNK1104: cannot open file 'atls.lib'错误解决方案
  19. Axure RP-产品原型设计工具使用
  20. 迷失在森林里的小女孩

热门文章

  1. box-sizing的不同属性值间的区别
  2. lua java效率_luaJavaBridge详解
  3. 尾气冒黑烟是什么问题_老司机教你从尾气颜色就判断出爱车的“身体状况”
  4. tdbgrid 数据类型输入错误 vb_VB编程从起始到普及历程了解一下
  5. 07:有趣的跳跃【一维数组】
  6. 详解Python线程对象daemon属性对线程退出的影响
  7. Python提取Word文档中所有超链接地址和文本
  8. Python使用标准库urllib模拟浏览器爬取网页内容
  9. 绿地深蓝机器人_人工智能企业深兰科技获绿地控股3亿元战略投资
  10. C++ list类的模拟实现