概述
在Linux内核中,SCSI子系统主要承担驱动SCSI主机适配器以及完成各种SCSI存储设备接入的功能,同时向上对接块设备子系统,提供IO路径处理块设备下发的IO请求。
SCSI子系统架构
Linux SCSI系统采用分层的架构,共分为三层:
- SCSI高层:包含各种SCSI设备类型的驱动(例如SCSI磁盘驱动、SCSI磁带驱动等)。高层驱动“认领”低层驱动发现的SCSI设备,为它们分配设备名,将对设备的I/O转换为SCSI命令,交由低层驱动处理;
- SCSI中层:SCSI子系统的核心,包含SCSI堆栈的高层和低层的一些公共服务函数。高层和低层通过调用中间层的函数来实现其功能;而中间层在执行过程中,也需要调用高层和低层注册的回调函数做一些个性化处理;
- SCSI低层:包含各类底层硬件适配器驱动的实现,例如SAS驱动、iSCSI驱动等。
SCSI设备命名和寻址
SCSI设备寻址
Linux SCSI模型基于传统的并行SCSI,通过主机适配器连接主机I/O总线(通常是PCI总线)和存储I/O总线(这里是SCSI总线)。一台计算机可以有多个主机适配器,而主机适配器可以控制一个(即所谓的单通道适配器)或多个(即所谓的多通道适配器)SCSI总线,一条总线可以有多个目标节点与之相连,并且一个目标节点可以有多个逻辑单元。
Linux SCSI子系统使用四元组来唯一寻址一个SCSI设备:
- SCSI adapter number [host]:host用于唯一标识系统中SCSI主机适配器;
- channel number [bus]:总线编号,单个主机适配器可以支持多条总线,也有称channel;
- id number [target]:目标节点标识;
- lun [lun]:lun为在目标节点内的逻辑单元编号。
因此,<scsi(_adapter_number), channel, id, lun>
在Linux系统中也就唯一标识了一个SCSI设备;在devfs的命名约定中则是<host, bus, id, lun>
的格式。在Linux下可以使用lsscsi命令查看系统中的scsi设备:
SCSI设备命名
SCSI子系统接入的设备都会呈现在/dev
目录下,由于SCSI子系统可以支持多种类型的设备,因此对于不同设备命名规则也会不同。这里以常见的几类SCSI设备说明它们的设备命名规则。
磁盘设备
Linux为SCSI磁盘预留了8个主设备号:8、65、 66、 67、68、69、70和71,每个主设备号可包含256个子设备号。这里以主设备号8,说明具体的分配规则如下:
[b,8,0] /dev/sda
[b,8,1] /dev/sda1 => 磁盘分区
....
[b,8,15] /dev/sda15
[b,8,16] /dev/sdb
[b,8,17] /dev/sdb1
....
[b,8,255] /dev/sdp15
其余主设备号的分配遵循相同的方式,可以计算出,Linux系统可以支持128块SCSI磁盘,每个磁盘支持15个分区。
CD-ROM设备
SCSI CD-ROM设备使用块类型的主设备号11,总共可以支持256个CD-ROM设备,分配规则如下:
[b,11,0] /dev/scd0 [or /dev/sr0]
[b,11,255] /dev/scd255 [or /dev/sr255]
磁带设备
SCSI磁带设备使用字符类型的主设备号9,总共可以支持32个磁带设备,每个设备支持4种模式(0、1、2和3),并可分为是否支持rewind,分配规则如下:
[c,9,0] /dev/st0 [tape 0, mode 0, rewind]
[c,9,1] /dev/st1 [tape 1, mode 0, rewind]
....
[c,9,31] /dev/st31 [tape 31, mode 0, rewind]
[c,9,32] /dev/st0l [tape 0, mode 1, rewind]
....
[c,9,63] /dev/st31l [tape 31, mode 1, rewind]
[c,9,64] /dev/st0m [tape 0, mode 2, rewind]
....
[c,9,96] /dev/st0a [tape 0, mode 3, rewind]
....
[c,9,127] /dev/st31a [tape 31, mode 3, rewind]
[c,9,128] /dev/nst0 [tape 0, mode 0, no rewind]
....
[c,9,160] /dev/nst0l [tape 0, mode 1, no rewind]
....
[c,9,192] /dev/nst0m [tape 0, mode 2, no rewind]
....
[c,9,224] /dev/nst0a [tape 0, mode 3, no rewind]
....
[c,9,255] /dev/nst31a [tape 31, mode 3, no rewind]
sg设备
SCSI sg设备使用字符类型主设备号21,总共可支持256个sg设备,分配规则如下:
[c,21,0] /dev/sg0
[c,21,1] /dev/sg1
....
[c,21,255] /dev/sg255
SCSI子系统初始化
SCSI协议由于被广泛应用,因此SCSI子系统通常都是直接编译到内核中,并且默认会开启对SCSI功能的支持。SCSI子系统的初始化由subsys_initcall机制触发,入口函数为init_scsi。init_scsi主要完成procfs、sysfs以及netlink通信相关的初始化工作。
相关参考
- 《存储技术原理分析:基于Linux 2.6内核源代码分析》
- 深入浅出SCSI子系统