当前位置: 首页 > news >正文

浅析Linux SCSI子系统:IO路径

文章目录

    • 概述
    • scsi_cmd:SCSI命令
      • result字段
      • proto_op字段
      • proto_type字段
    • SCSI命令下发
      • scsi_request_fn
        • scsi_dev_queue_ready
        • scsi_host_queue_ready
    • SCSI命令响应
      • 命令请求完成的软中断处理
    • 相关参考

概述

SCSI子系统向上与块层对接,由块层提交的对块设备的IO请求,会由SCSI子系统转换成SCSI协议的标准命令,然后调用Scsi_Host结构的queuecommand回调下发到低层驱动执行;低层驱动会将SCSI命令和数据发送给真实的设备,并在请求完成后,调用scsi_cmd结构中的scsi_done回调,将请求响应信息返回给SCSI中层,SCSI中层完成请求响应的解析后,将结果返回给块层。

scsi_cmd:SCSI命令

struct scsi_cmnd {struct scsi_request req;struct scsi_device *device;struct list_head list;     // 用于链入到关联SCSI设备的SCSI命令链表中struct list_head eh_entry;     // 用于链入到SCSI Host的错误恢复链表中struct delayed_work abort_work;struct rcu_head rcu;int eh_eflags;unsigned long serial_number;unsigned long jiffies_at_alloc;int retries;   // SCSI命令已重试的次数int allowed;   // SCSI命令允许重试的次数unsigned char prot_op;     // DIF操作类型unsigned char prot_type;   // DIF保护类型unsigned char prot_flags;unsigned short cmd_len;enum dma_data_direction sc_data_direction;unsigned char *cmnd;struct scsi_data_buffer sdb;  // SCSI命令的数据缓冲区struct scsi_data_buffer *prot_sdb;     // SCSI命令的保护数据缓冲区unsigned underflow;	unsigned transfersize;struct request *request;unsigned char *sense_buffer;   // 存放sense信息的缓冲区void (*scsi_done) (struct scsi_cmnd *);    // 底层驱动完成IO请求后,调用scsi_done将结果返回给SCSIunsigned char *host_scribble;	int result;    // 存放低层驱动返回的IO状态信息int flags;
};

result字段

result携带了驱动或SCSI中层在完成SCSI命令处理后返回的一些结果信息,一共包含4个字段。
在这里插入图片描述

  • driver_byte:由SCSI中层进行设置;
  • host_byte:存放底层驱动返回的状态信息;
  • msg_byte:存放主机适配自身的一些信息;
  • status_byte:存放目标设备返回的状态信息,由SCSI协议定义。

proto_op字段

proto_op字段描述了SCSI命令的DIF操作类型,由scsi_prot_operations枚举类型定义:

enum scsi_prot_operations {SCSI_PROT_NORMAL = 0,SCSI_PROT_READ_INSERT,SCSI_PROT_WRITE_STRIP,SCSI_PROT_READ_STRIP,SCSI_PROT_WRITE_INSERT,SCSI_PROT_READ_PASS,SCSI_PROT_WRITE_PASS,
}

proto_type字段

proto_type字段描述了SCSI命令支持的DIF保护类型,由t10_dif_type枚举类型定义:

enum t10_dif_type {T10_PI_TYPE0_PROTECTION = 0x0,T10_PI_TYPE1_PROTECTION = 0x1,T10_PI_TYPE2_PROTECTION = 0x2,T10_PI_TYPE3_PROTECTION = 0x3,
}

SCSI命令下发

scsi_request_fn

在这里插入图片描述

scsi_dev_queue_ready

scsi_dev_queue_ready检查SCSI设备运行IO情况,确认是否允许下发新的IO。函数检查的维度有两个:

  • 检查SCSI设备的IO请求队列是否已满。若满,则不允许下发新的IO;
  • 检查SCSI设备是否设置了device_blocked。若设置,则需要等待device_blocked计数减为0时,才允许下发IO。

在这里插入图片描述

scsi_host_queue_ready

scsi_host_queue_ready检查主机适配器能否下发新的IO,检查逻辑与scsi_dev_queue_ready类似。
在这里插入图片描述

SCSI命令响应

SCSI中层在将SCSI命令请求下发给驱动时,会设置scsi_cmnd结构中的done回调函数,驱动在完成IO请求时,通过调用done回调,将IO响应信息返回给中层。
在这里插入图片描述

命令请求完成的软中断处理

IO请求完成的处理流程前半部分在硬中断上下文处理,后半部分的工作回切换到软中断进行处理,SCSI提供的软中断处理入口是scsi_softirq_done函数。scsi_softirq_done的工作如下:

  1. 调用scsi_decide_disposition解析scsi_cmd的返回信息,包括驱动返回状态、sense数据等,确定如何进一步处理scsi_cmd;
  2. 根据scsi_decide_disposition返回的动作,处理scsi_cmnd,分为几种情况:
    • SUCCESS:IO成功完成,将结果返回上层;
    • NEEDS_RETRY/ADD_TO_MLQUEUE:IO重试。把scsi_cmnd重新加入到块设备请求队列处理;
    • 默认情况:IO错误处理。调用scsi_en_scmd_add把scsi_cmnd加入到错误处理队列中,等待错误恢复。

scsi_softirq_done流程示意如下:
在这里插入图片描述

相关参考

  • 《存储技术原理分析:基于Linux 2.6内核源代码分析》
http://www.lryc.cn/news/148770.html

相关文章:

  • linux系统(centos、Ubuntu、银河服务器)备份
  • 堆栈深度超过限制
  • Linux ptrace系统调用
  • CSDN每日一练 |『贝博士发奖金』『Longest Continuous Increasing Subsequence』『最小差值』2023-09-01
  • 二维数组创建方式比较
  • 安达发|富士康科技集团利用自动排程APS软件打造智慧工厂
  • 云计算在大数据分析中的应用与优势
  • linux————ELK(日志收集系统集群)
  • Leetcode213 打劫家舍2
  • Redis全局命令
  • Xml转json
  • Spring框架知识点汇总
  • JavaScript Web APIs - 06 正则表达式
  • Python入门教程 | Python3 字符串
  • Playwright for Python:安装及初步使用
  • Ubuntu 20.04.5 怎么安装微信
  • HummerRisk V1.4.0发布
  • C语言每日一练----Day(12)
  • 【Tkinter系列11/15】小部件 (Text)
  • 通过「内网穿透」技术,实现出差期间远程访问企业局域网中的象过河ERP系统
  • ChatGPT和大型语言模型(LLM)是什么关系?
  • list(介绍与实现)
  • Centos7 使用docker安装oracle数据库(超详细)
  • 昨天面试的时候被提问到的问题集合(答案)
  • PYTHON用户流失数据挖掘:建立逻辑回归、XGBOOST、随机森林、决策树、支持向量机、朴素贝叶斯和KMEANS聚类用户画像...
  • 详解IP协议
  • Stream流式编程用例
  • 【Pytorch笔记】1. tensor的创建
  • Maven 基础之安装和命令行使用
  • 运动耳机需要具备哪些功能、挂耳式运动蓝牙耳机推荐