deepin-community/kernel SCSI子系统:存储设备驱动框架

deepin-community/kernel SCSI子系统:存储设备驱动框架

【免费下载链接】kernel deepin linux kernel 【免费下载链接】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子系统采用典型的分层架构设计,各层职责明确,协同工作:

mermaid

核心数据结构关系

SCSI子系统通过几个关键数据结构来管理存储设备:

mermaid

核心组件深度解析

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工作流程详解

命令处理流程

mermaid

错误处理机制

SCSI子系统实现了复杂的错误处理机制:

mermaid

关键特性实现

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页面大小并读取数据
    // ...
}

设备发现和扫描机制

扫描过程

mermaid

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子系统实现了分层的错误处理机制:

  1. 命令级恢复:尝试重新执行失败的命令
  2. 设备级恢复:重置特定设备
  3. 目标级恢复:重置整个目标
  4. 总线级恢复:重置SCSI总线
  5. 主机级恢复:重置主机适配器

超时管理

#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内核存储栈的核心组件,提供了:

  1. 统一的设备抽象:将各种存储设备统一管理
  2. 高效的I/O调度:智能的队列管理和命令调度

【免费下载链接】kernel deepin linux kernel 【免费下载链接】kernel 项目地址: https://gitcode.com/deepin-community/kernel

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值