deepin-community/kernel SCSI子系统:存储设备驱动框架
【免费下载链接】kernel deepin linux kernel 项目地址: https://gitcode.com/deepin-community/kernel
引言:存储设备管理的核心引擎
在现代操作系统中,SCSI(Small Computer System Interface,小型计算机系统接口)子系统扮演着存储设备管理的核心角色。作为Linux内核的重要组成部分,SCSI子系统提供了一个统一的框架来管理各种存储设备,从传统的硬盘驱动器到现代的固态硬盘和存储阵列。
你是否曾经遇到过这样的问题:
- 为什么不同类型的存储设备(SATA、SAS、USB存储)都能在Linux系统中统一管理?
- 内核如何高效地处理成千上万的I/O请求而不出现混乱?
- 存储设备的错误恢复和超时处理是如何实现的?
本文将深入解析deepin-community/kernel中的SCSI子系统,揭示其作为存储设备驱动框架的设计哲学、核心架构和实现细节。
SCSI子系统架构总览
核心层次结构
SCSI子系统采用典型的分层架构设计,各层职责明确,协同工作:
核心数据结构关系
SCSI子系统通过几个关键数据结构来管理存储设备:
核心组件深度解析
1. SCSI主机结构(Scsi_Host)
Scsi_Host结构体是SCSI子系统的核心,代表一个SCSI主机适配器:
struct Scsi_Host {
struct list_head __devices; // 设备链表
struct list_head __targets; // 目标设备链表
spinlock_t *host_lock; // 主机锁
const struct scsi_host_template *hostt; // 主机模板
unsigned int host_no; // 主机编号
unsigned int max_channel; // 最大通道数
unsigned int max_id; // 最大目标ID
u64 max_lun; // 最大LUN
int can_queue; // 最大队列深度
short cmd_per_lun; // 每个LUN的命令数
enum scsi_host_state shost_state; // 主机状态
// ... 更多字段
};
2. SCSI设备结构(scsi_device)
每个SCSI设备都由scsi_device结构体表示:
struct scsi_device {
struct Scsi_Host *host; // 所属主机
struct request_queue *request_queue; // 请求队列
uint id; // 目标ID
uint channel; // 通道号
u64 lun; // LUN号
unsigned char type; // 设备类型
char scsi_level; // SCSI级别
unsigned short queue_depth; // 队列深度
enum scsi_device_state sdev_state; // 设备状态
// ... 超过100个字段
};
3. SCSI命令结构(scsi_cmnd)
SCSI命令封装在scsi_cmnd结构体中:
struct scsi_cmnd {
struct scsi_device *device; // 目标设备
unsigned char *cmnd; // CDB命令块
unsigned short cmd_len; // 命令长度
unsigned int result; // 执行结果
struct request *request; // 关联的请求
// ... 其他字段
};
SCSI工作流程详解
命令处理流程
错误处理机制
SCSI子系统实现了复杂的错误处理机制:
关键特性实现
1. 队列深度管理
SCSI子系统通过智能的队列深度管理来优化性能:
int scsi_change_queue_depth(struct scsi_device *sdev, int depth)
{
depth = min_t(int, depth, scsi_device_max_queue_depth(sdev));
if (depth > 0) {
sdev->queue_depth = depth;
wmb();
}
if (sdev->request_queue)
blk_set_queue_depth(sdev->request_queue, depth);
sbitmap_resize(&sdev->budget_map, sdev->queue_depth);
return sdev->queue_depth;
}
2. 超时处理
enum scsi_timeout_action (*eh_timed_out)(struct scsi_cmnd *);
驱动程序可以实现自定义的超时处理策略,决定是重试、中止还是重置。
3. VPD(Vital Product Data)支持
SCSI子系统支持读取设备的VPD信息:
int scsi_get_vpd_page(struct scsi_device *sdev, u8 page,
unsigned char *buf, int buf_len)
{
if (!scsi_device_supports_vpd(sdev))
return -EINVAL;
// 获取VPD页面大小并读取数据
// ...
}
设备发现和扫描机制
扫描过程
LUN扫描策略
SCSI子系统支持多种LUN扫描方式:
| 扫描方式 | 描述 | 适用场景 |
|---|---|---|
| 顺序扫描 | 逐个LUN扫描 | 传统设备 |
| REPORT LUNS | 使用REPORT LUNS命令 | 现代设备 |
| 并行扫描 | 多LUN同时扫描 | 高性能设备 |
性能优化技术
1. 分散/聚集(Scatter-Gather)支持
unsigned short sg_tablesize; // SG表大小
unsigned short sg_prot_tablesize; // 保护信息SG表大小
2. 标签命令(Tagged Command Queuing)
unsigned tagged_supported:1; // 支持标签命令
unsigned simple_tags:1; // 简单标签使能
3. 多队列支持
unsigned nr_hw_queues; // 硬件队列数量
错误处理和恢复
错误处理层次
SCSI子系统实现了分层的错误处理机制:
- 命令级恢复:尝试重新执行失败的命令
- 设备级恢复:重置特定设备
- 目标级恢复:重置整个目标
- 总线级恢复:重置SCSI总线
- 主机级恢复:重置主机适配器
超时管理
#define SCSI_DEFAULT_EH_TIMEOUT (10 * HZ) // 默认超时时间
实际应用案例
1. 设备配置示例
// 创建设备配置示例
static int example_slave_configure(struct scsi_device *sdev)
{
struct example_priv *priv = sdev->hostdata;
// 设置队列深度
scsi_change_queue_depth(sdev, EXAMPLE_QUEUE_DEPTH);
// 配置同步传输参数
if (sdev->sdtr)
configure_sync_transfer(sdev);
// 设置超时时间
sdev->eh_timeout = EXAMPLE_EH_TIMEOUT;
return 0;
}
2. 命令处理示例
static int example_queuecommand(struct Scsi_Host *shost,
struct scsi_cmnd *cmd)
{
struct example_priv *priv = shost_priv(shost);
// 检查主机状态
if (unlikely(scsi_host_in_recovery(shost)))
return SCSI_MLQUEUE_HOST_BUSY;
// 映射命令到硬件队列
int queue_num = blk_mq_unique_tag_to_hwq(blk_mq_unique_tag(cmd->request));
// 提交命令到硬件
if (submit_to_hw(priv, cmd, queue_num)) {
cmd->scsi_done(cmd);
return 0;
}
return SCSI_MLQUEUE_DEVICE_BUSY;
}
调试和故障排除
调试信息获取
SCSI子系统提供了丰富的调试信息:
# 查看SCSI主机信息
cat /proc/scsi/scsi
# 查看设备信息
cat /sys/class/scsi_device/*/device/model
# 调试日志启用
echo 1 > /sys/module/scsi_mod/parameters/scsi_logging_level
常见问题排查
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 设备不识别 | 驱动未加载 | 加载对应驱动 |
| I/O性能差 | 队列深度设置不当 | 调整queue_depth |
| 命令超时 | 硬件故障或配置问题 | 检查硬件连接 |
总结与展望
SCSI子系统作为Linux内核存储栈的核心组件,提供了:
- 统一的设备抽象:将各种存储设备统一管理
- 高效的I/O调度:智能的队列管理和命令调度
【免费下载链接】kernel deepin linux kernel 项目地址: https://gitcode.com/deepin-community/kernel
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



