浅析Linux SCSI子系统:IO路径

news/2025/2/3 23:54:27/

文章目录

    • 概述
    • 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.ppmy.cn/news/1074069.html

相关文章

Leedcode19. 删除链表的倒数第 N 个结点

给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。 输入:head [1,2,3,4,5], n 2 输出:[1,2,3,5] 示例 2: 输入:head [1], n 1 输出:[] 示例 3: 输入&#xff1…

angular12自定义指令防止2重点击

方法一 import { Directive, ElementRef, HostListener } from angular/core;Directive({selector: [appPreventDoubleClick] }) export class PreventDoubleClickDirective {private isClicked: boolean false;constructor(private elementRef: ElementRef) {}HostListener(…

4.8 SYN什么时候被丢弃

TCP四次挥手过程中主动断开连接方有一个TIME_WAIT状态,这个状态会持续2MSL之后才会转变为CLOSED状态。一般一个MSL是30秒,所以以一共一般是60秒。这60秒内客户端会一直占用着端口。如果发起断开端的TIME-WAIT状态过多,占满了端口资源&#xf…

计算机毕设之Python的高校成绩分析(含文档+源码+部署)

本系统阐述的是一个高校成绩分析系统的设计与实现,对于Python、B/S结构、MySql进行了较为深入的学习与应用。主要针对系统的设计,描述,实现和分析与测试方面来表明开发的过程。开发中使用了 django框架和MySql数据库技术搭建系统的整体架构。…

YOLOv5屏蔽区域训练(选择区域训练)

YOLOv5屏蔽区域/选择区域 训练(重点区域训练) 前期准备labelme选择mask区域 代码改动 前期准备 思路就是通过使用一个mask掩膜,对我们想要屏蔽或者选择的区域进行定向遮挡或者定向选择,在训练的时候v5需要加载数据即图片和标注信…

防溺水智能预警系统解决方案 yolov7

防溺水智能预警系统解决方案采用yolov7先进的AI视觉识别算法模型框架,防溺水智能预警系统解决方案算法实现对危险水域人员活动、水面情况等各项指标的监测和分析。当发现有人进入危险水域或出现紧急情况时,算法会立即发出预警信号。Yolo算法采用一个单独…

解决方案 | 法大大电子签为保险行业加个“双保险”

近年来,人们自我保障意识的不断增强,带动了保险行业的蓬勃发展;数字化进程的加快,也让保险签署更加便捷高效。但与此同时,对于保险企业的安全合规化要求也在不断提升,电子签作为企业数字化转型的重要抓手&a…

typescript基础之never

TypeScript 的 never 类型是一种特殊的类型,它表示的是那些永远不存在的值的类型。例如,一个抛出异常或无限循环的函数的返回值类型就是 never,因为它们永远不会返回任何值。never 类型是所有类型的子类型,也就是说,任…