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

浅析Linux SCSI子系统:设备管理

文章目录

    • 概述
    • 设备管理数据结构
      • scsi_host_template:SCSI主机适配器模板
      • scsi_host:SCSI主机适配器
        • 主机适配器支持DIF
      • scsi_target:SCSI目标节点
      • scsi_device:SCSI设备
    • 添加主机适配器
      • 构建sysfs目录
    • 添加SCSI设备
      • 挂载Lun
        • IO请求队列初始化
    • 相关参考

概述

Linux SCSI子系统通过SCSI主机适配器(HBA)接入所有SCSI存储设备,在Linux系统中,可以安装多种主机适配器,SCSI中层会提供主机适配器的统一抽象,这些主机适配器的厂商提供具体的低层驱动实现;主机适配器接入到SCSI子系统后,SCSI会通过扫描或者低层驱动主动上报的方式,接入主机适配器下挂的所有SCSI存储设备。

设备管理数据结构

Linux SCSI子系统通过Scsi_Host、scsi_target和scsi_device数据结构分别来描述SCSI主机适配器、目标节点和逻辑单元,它们之间的关系如下:
在这里插入图片描述

  • Linux系统支持安装多个主机适配器,所有接入的主机适配器在SCSI中层都会有对应的Scsi_Host结构。Scsi_Host结构描述了SCSI主机适配器的通用属性和方法,由低层驱动根据scsi_host_template进行创建并注册到SCSI子系统中;
  • Scsi_Host维护了两个设备链表:target链表和device链表,其中target链表管理所有的scsi_targe结构,device链表管理所有的scsi_device结构。

scsi_host_template:SCSI主机适配器模板

scsi_host_template描述了SCSI主机适配器的公共属性和接口,包括主机队列深度、命令处理回调、错误处理回调等。低层驱动自定义SCSI主机适配器模板,SCSI中层会提供接口由低层驱动调用,根据SCSI主机适配器模板信息生成相应的Scsi_Host实例。

struct scsi_host_template {struct module *module;const char *name;int (* queuecommand)(struct Scsi_Host *, struct scsi_cmnd *);      // SCSI命令下发接口int (* eh_abort_handler)(struct scsi_cmnd *);  // 错误恢复:取消指定的SCSI命令int (* eh_device_reset_handler)(struct scsi_cmnd *);   // 错误恢复:复位SCSI设备int (* eh_target_reset_handler)(struct scsi_cmnd *);   // 错误恢复:复位SCSI目标节点int (* eh_bus_reset_handler)(struct scsi_cmnd *);      // 错误恢复:复位SCSI总线int (* eh_host_reset_handler)(struct scsi_cmnd *);     // 错误恢复:复位SCSI主机适配器int (* slave_alloc)(struct scsi_device *);     // 添加SCSI设备时,中层调用让驱动传递设备私有数据int (* slave_configure)(struct scsi_device *); void (* slave_destroy)(struct scsi_device *);  // 删除SCSI设备时,中层调用让驱动释放设备私有数据int (* target_alloc)(struct scsi_target *);    // 添加SCSI目标时,中层调用让驱动传递设备私有数据void (* target_destroy)(struct scsi_target *);     // 删除SCSI目标时,中层让驱动释放设备私有数据int (* scan_finished)(struct Scsi_Host *, unsigned long);void (* scan_start)(struct Scsi_Host *);int (* change_queue_depth)(struct scsi_device *, int);     // 调整SCSI设备的队列深度int (* map_queues)(struct Scsi_Host *shost);enum blk_eh_timer_return (*eh_timed_out)(struct scsi_cmnd *);      // 低层驱动自定义IO超时处理策略int (*host_reset)(struct Scsi_Host *shost, int reset_type);int can_queue;int this_id;unsigned short sg_tablesize;unsigned short sg_prot_tablesize;unsigned int max_sectors;unsigned long dma_boundary;short cmd_per_lun;unsigned char present;int tag_alloc_policy;unsigned track_queue_depth:1;unsigned supported_mode:2;unsigned unchecked_isa_dma:1;unsigned use_clustering:1;unsigned emulated:1;unsigned skip_settle_delay:1;unsigned no_write_same:1;unsigned force_blk_mq:1;unsigned int max_host_blocked;
};

scsi_host:SCSI主机适配器

SCSI主机适配器通常也是PCI设备,由内核的PCI子系统负责扫描接入。

struct Scsi_Host {struct list_head	__devices;    // 管理Host下的所有scsi_devicestruct list_head	__targets;    // 管理Host下的所有scsi_targetstruct list_head	starved_list;struct list_head	eh_cmd_q;struct task_struct    * ehandler;  struct completion     * eh_action; wait_queue_head_t       host_wait;struct scsi_host_template *hostt;      // 指向主机适配器模板的指针struct scsi_transport_template *transportt;union {struct blk_queue_tag	*bqt;struct blk_mq_tag_set	tag_set;};atomic_t host_busy;	atomic_t host_blocked;unsigned int host_failed;	  unsigned int host_eh_scheduled;      unsigned int host_no; int eh_deadline;unsigned long last_reset;unsigned int max_channel;unsigned int max_id;u64 max_lun;unsigned int unique_id;unsigned short max_cmd_len;int this_id;int can_queue;short cmd_per_lun;short unsigned int sg_tablesize;short unsigned int sg_prot_tablesize;unsigned int max_sectors;unsigned long dma_boundary;unsigned nr_hw_queues;...char work_q_name[20];struct workqueue_struct *work_q;struct workqueue_struct *tmf_work_q;unsigned int max_host_blocked;unsigned int prot_capabilities;unsigned char prot_guard_type;enum scsi_host_state shost_state;struct device		shost_gendev, shost_dev;void *shost_data;unsigned long hostdata[0]  __attribute__ ((aligned (sizeof(unsigned long))));  // 可用于存储低层驱动私有数据
}

主机适配器支持DIF

Scsi_Host的prot_capabilities字段描述了SCSI主机适配器支持DIF的能力。

enum scsi_host_prot_capabilities {SHOST_DIF_TYPE1_PROTECTION = 1 << 0, /* T10 DIF Type 1 */SHOST_DIF_TYPE2_PROTECTION = 1 << 1, /* T10 DIF Type 2 */SHOST_DIF_TYPE3_PROTECTION = 1 << 2, /* T10 DIF Type 3 */SHOST_DIX_TYPE0_PROTECTION = 1 << 3, /* DIX between OS and HBA only */SHOST_DIX_TYPE1_PROTECTION = 1 << 4, /* DIX with DIF Type 1 */SHOST_DIX_TYPE2_PROTECTION = 1 << 5, /* DIX with DIF Type 2 */SHOST_DIX_TYPE3_PROTECTION = 1 << 6, /* DIX with DIF Type 3 */
}

scsi_target:SCSI目标节点

struct scsi_target {struct scsi_device	*starget_sdev_user;struct list_head	siblings;     // 用于挂接在Host的__targets链表中struct list_head	devices;      // 管理目标节点下的所有SCSI设备的链表struct device		dev;struct kref		reap_ref; unsigned int		channel;unsigned int		id; unsigned int		create:1; unsigned int		single_lun:1;	   // 标识是否是单Lununsigned int		pdt_1f_for_no_lun:1;	unsigned int		no_report_luns:1;unsigned int		expecting_lun_change:1;	atomic_t		target_busy;atomic_t		target_blocked;unsigned int		can_queue;unsigned int		max_target_blocked;char			scsi_level;enum scsi_target_state	state;void 			*hostdata;     // 驱动私有数据unsigned long		starget_data[0];    // 驱动私有数据
}

scsi_device:SCSI设备

在SCSI子系统的语义中,SCSI设备对应的才是逻辑单元的概念,也就是我们常说的Lun。

struct scsi_device {struct Scsi_Host *host;struct request_queue *request_queue;   // IO请求队列struct list_head    siblings;      // 用于链接到Host的__devices链表struct list_head    same_target_siblings; atomic_t device_busy;atomic_t device_blocked;	spinlock_t list_lock;struct list_head cmd_list;     // 下发到设备的SCSI命令链表struct list_head starved_entry;unsigned short queue_depth;	unsigned short max_queue_depth;	unsigned short last_queue_full_depth; unsigned short last_queue_full_count; unsigned long last_queue_full_time;unsigned long queue_ramp_up_period;unsigned long last_queue_ramp_up;unsigned int id, channel;u64 lun;unsigned int manufacturer;	unsigned sector_size;	     // 扇区大小void *hostdata;	unsigned char type;char scsi_level;char inq_periph_qual;	...struct list_head event_list;struct work_struct event_work;unsigned int max_device_blocked; atomic_t iorequest_cnt;atomic_t iodone_cnt;atomic_t ioerr_cnt;struct device		sdev_gendev,sdev_dev;struct execute_work	ew; /* used to get process context on put */struct work_struct	requeue_work;struct scsi_device_handler *handler;void			*handler_data;unsigned char		access_state;struct mutex		state_mutex;enum scsi_device_state sdev_state;struct task_struct	*quiesced_by;unsigned long		sdev_data[0];
} 

添加主机适配器

驱动添加主机适配器前,需要先调用scsi_alloc_host分配Scsi_Host结构。scsi_alloc_host根据驱动填写的主机适配器模板对Scsi_Host结构进行初始化,同时允许驱动传入特定的size,这样SCSI中层在分配Scsi_Host结构时,会在尾部申请额外的空间存储驱动的私有数据。
在这里插入图片描述
完成Scsi_Host的结构申请后,驱动调用scsi_add_host将主机适配器添加到系统中:
在这里插入图片描述

构建sysfs目录

添加主机适配器的过程中,一个很重要的部分就是在sysfs文件系统构建相关的节点,以支持应用程序访问SCSI子系统的相关信息。
在这里插入图片描述

添加SCSI设备

无论是SCSI总线扫描或者是驱动发现的SCSI设备,最后都需要调用scsi_add_device接口将设备添加到系统中。scsi_add_device执行流程如下:

  • 确认SCSI目标节点在系统中是否存在,不存在就会创建新的scsi_target结构;
  • 向SCSI目标节点中添加Lun,即scsi_device。

在这里插入图片描述

挂载Lun

scsi_probe_and_add_lun负责挂载Lun设备到系统中,它的执行流程如下:

  • 确认SCSI设备在系统中是否存在,不存在则创建新的scsi_device结构;
  • 向设备发送INQUIRY命令,设备在正常接入的情况下,会返回INQUIRY数据;
  • 解析INQUIRY数据,初始化SCSI设备信息

在这里插入图片描述

IO请求队列初始化

分配scsi_device结构时,也会初始化设备的IO请求队列。根据主机适配器是否支持多队列,初始化函数也会不同。对于单队列,SCSI使用scsi_old_alloc_queue函数分配IO请求队列。
在这里插入图片描述

相关参考

  • 《存储技术原理分析:基于Linux 2.6内核源代码分析》

相关文章:

浅析Linux SCSI子系统:设备管理

文章目录 概述设备管理数据结构scsi_host_template&#xff1a;SCSI主机适配器模板scsi_host&#xff1a;SCSI主机适配器主机适配器支持DIF scsi_target&#xff1a;SCSI目标节点scsi_device&#xff1a;SCSI设备 添加主机适配器构建sysfs目录 添加SCSI设备挂载LunIO请求队列初…...

爬虫逆向实战(二十五)--某矿采购公告

一、数据接口分析 主页地址&#xff1a;某矿 1、抓包 通过抓包可以发现数据接口是cgxj/by-lx-page 2、判断是否有加密参数 请求参数是否加密&#xff1f; 通过查看“载荷”模块可以发现有一个param的加密参数 请求头是否加密&#xff1f; 无响应是否加密&#xff1f; 无c…...

DPLL 算法之分裂策略

前言 DPLL算法确实是基于树&#xff08;或二叉树&#xff09;的回溯搜索算法&#xff0c;它用于解决布尔可满足性问题&#xff08;SAT问题&#xff09;。下面我会分析您提到的DPLL算法中的分裂策略&#xff0c;以及它是如何在搜索过程中起作用的。 DPLL算法中的分裂策略是用于在…...

Jmeter+ServerAgent

一、Jmeter 下载 https://jmeter.apache.org/download_jmeter.cgi选择Binaries二进制下载 apache-jmeter-5.6.2.tgz 修改配置文件 jmeter下的bin目录&#xff0c;打开jmeter.properties 文件 languagezh_CN启动命令 cd apache-jmeter-5.6/bin sh jmeter二、ServerAgent 监…...

打破数据孤岛!时序数据库 TDengine 与创意物联感知平台完成兼容性互认

新型物联网实现良好建设的第一要务就是打破信息孤岛&#xff0c;将数据汇聚在平台统一处理&#xff0c;实现数据共享&#xff0c;放大物联终端的行业价值&#xff0c;实现系统开放性&#xff0c;以此营造丰富的行业应用环境。在此背景下&#xff0c;物联感知平台应运而生&#…...

ubuntu22安装和部署Kettle8.2

前提 kettle是纯java编写的etl开源工具&#xff0c;目前kettle7和kettle8都需要java8或者以上才能正常运行。所以运行kettle前先检查java环境是否正确配置&#xff0c;java版本是否是8或者以上。 kettle安装 1、创建kettle目录&#xff0c;并将kettle的zip包解压到kettle目…...

修复 Ubuntu Linux 中的“找不到命令‘python’”错误

在ubuntu 22.04版本中使用 callstack backtrace.txt 回溯错误点是碰到了该问题。 参考文章&#xff1a;链接 ubuntu22.04版本中默认只安装了python3版本 查看python各个版本安装情况&#xff0c;在终端输入命令&#xff1a; type python python2 python3如果安装了对应的版本…...

【业务功能篇86】微服务-springcloud-系统性能压力测试-jmeter-性能优化-JVM参数调优

系统性能压力测试 一、压力测试 压力测试是给软件不断加压&#xff0c;强制其在极限的情况下运行&#xff0c;观察它可以运行到何种程度&#xff0c;从而发现性能缺陷&#xff0c;是通过搭建与实际环境相似的测试环境&#xff0c;通过测试程序在同一时间内或某一段时间内&…...

mysql的登录与退出

mysql是c/s架构&#xff0c;意味着同时要有客户端和服务端 1 找到客户端。mysql.exe的安装目录 打开命令行 2 输入对应的服务器的ip&#xff0c;如果是本地&#xff0c;就是Localhost&#xff0c;如果是远程服务器&#xff0c;那就输入对应ip/域名。并且指定mysql监听的端口 …...

SOLIDWORKS工程图转DWG图层映射技巧

DWG格式的图纸在工程制图中有着非常重要的地位&#xff0c;工程实践中常常就需要将SOLIDWORKS工程图进行转换。对于两者之间数据衔接的妥善处理&#xff0c;是提升工作效率的有效手段。基于此目的&#xff0c;本次我们将介绍数据衔接的一个有效解决方案&#xff1a;图层数据的映…...

PMAC与Modbus主站进行Modbus Tcp通讯

PMAC与Modbus主站进行Modbus Tcp通讯 创建modbus通讯参数 在项目的PMAC Script Language\Global Includes下创建一个名为00_Modbus_Para.pmh的pmh文件。 Modbus[0].Config.ServerPort 0 Modbus[0].Config.ConnectTimeOut 6000 Modbus[0].Config.SendRecvTimeOut 0 Modbu…...

MyBatis分页插件PageHelper的使用及MyBatis的特殊符号---详细介绍

一&#xff0c;分页的概念 分页是一种将大量数据或内容分割成多个页面以便逐页显示的方式。在分页中&#xff0c;数据被分割成一定数量的页&#xff0c;每页显示一部分数据或内容&#xff0c;用户可以通过翻页或跳分页是一种将大量数据或内容分割成多个页面以便逐页显示的方式。…...

Qt(C++)计算一段程序执行经过的时间

一、前言 在许多应用程序和系统中,需要对经过的时间进行计算和记录。例如 可能想要测量某个操作的执行时间,或者记录一个过程中经过的时间以进行性能分析。在这些场景下,准确地计时是非常重要的。 Qt提供了一个功能强大的计时器类QElapsedTimer,可以方便地记录经过的时间…...

UnionTech OS(统信桌面操作系统)安装 g++ 和 cmake

文章目录 前言一、debian 10简介二、安装 g三、安装cmake参考资料 前言 统信桌面操作系统支持x86、龙芯、申威、鲲鹏、飞腾、兆芯等国产CPU平台&#xff0c;基于debian 10.x 的稳定版本&#xff0c;长期维护的统一内核版本(4.19)。 一、debian 10简介 Debian 10 是一款广泛使…...

php_webshell免杀--从0改造你的AntSword

0x00 前言&#xff1a; 为什么会有改造蚁剑的想法&#xff0c;之前看到有做冰蝎的流量加密&#xff0c;来看到绕过waf&#xff0c;改造一些弱特征&#xff0c;通过流量转换&#xff0c;跳过密钥交互。 但是&#xff0c;冰蝎需要反编译去改造源码&#xff0c;再进行修复bug&am…...

RocketMQ mqadmin java springboot python 调用笔记

命令 mqadmin命令列表 yeqiangyeqiang-MS-7B23:/opt/rocketmq-all-5.1.3-bin-release$ sh bin/mqadmin The most commonly used mqadmin commands are:updateTopic Update or create topicdeleteTopic Delete topic from broker and NameServer.…...

Java aspose 将HTML导出成Excel文件

1.需求 有一批表格的html文件&#xff0c;需要将这些表格导出成excel文件 2.代码 使用第三方库 aspose ByteArrayInputStream htmlIs new ByteArrayInputStream(htmlBuilder.toString().getBytes()); // 将html字符串构建成输入流 LoadOptions lo new LoadOptions(LoadFo…...

原生微信小程序 动态(横向,纵向)公告(广告)栏

先看一下动态效果 Y轴滚动公告的原理是swiper组件在页面中的Y轴滚动&#xff0c;属性vertical&#xff0c;其余属性也设置一下autoplay circular interval"3000" X轴滚动的原理是&#xff0c;利用动画效果&#xff0c;将内容从右往左过渡过去 wxml&#xff1a; &l…...

pandas和polars简单的对比分析

pandas pandas是基于python写的&#xff0c;底层的数据结构是Numpy数据(ndarray)。pandas自身有两个核心的数据结构&#xff1a;DataFrame和Series&#xff0c;前者是二维的表格数据结构&#xff0c;后者是一维标签化数组。 polars polars是用Rust&#xff08;一种系统级编程…...

Feign远程调用的使用

假设已配好nacos服务&#xff1a;并且已配好userservice、orderservice&#xff0c;点击跳转 Feign是一个声明式的http客户端&#xff0c;官方地址&#xff1a;https://github.com/OpenFeign/feign&#xff0c;其作用就是在程序中帮助我们优雅的实现http请求的发送&#xff0c…...

生成xcframework

打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式&#xff0c;可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合

强化学习&#xff08;Reinforcement Learning, RL&#xff09;是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程&#xff0c;然后使用强化学习的Actor-Critic机制&#xff08;中文译作“知行互动”机制&#xff09;&#xff0c;逐步迭代求解…...

从WWDC看苹果产品发展的规律

WWDC 是苹果公司一年一度面向全球开发者的盛会&#xff0c;其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具&#xff0c;对过去十年 WWDC 主题演讲内容进行了系统化分析&#xff0c;形成了这份…...

visual studio 2022更改主题为深色

visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中&#xff0c;选择 环境 -> 常规 &#xff0c;将其中的颜色主题改成深色 点击确定&#xff0c;更改完成...

LeetCode - 394. 字符串解码

题目 394. 字符串解码 - 力扣&#xff08;LeetCode&#xff09; 思路 使用两个栈&#xff1a;一个存储重复次数&#xff0c;一个存储字符串 遍历输入字符串&#xff1a; 数字处理&#xff1a;遇到数字时&#xff0c;累积计算重复次数左括号处理&#xff1a;保存当前状态&a…...

ETLCloud可能遇到的问题有哪些?常见坑位解析

数据集成平台ETLCloud&#xff0c;主要用于支持数据的抽取&#xff08;Extract&#xff09;、转换&#xff08;Transform&#xff09;和加载&#xff08;Load&#xff09;过程。提供了一个简洁直观的界面&#xff0c;以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...

GitHub 趋势日报 (2025年06月08日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...

音视频——I2S 协议详解

I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议&#xff0c;专门用于在数字音频设备之间传输数字音频数据。它由飞利浦&#xff08;Philips&#xff09;公司开发&#xff0c;以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...

Netty从入门到进阶(二)

二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架&#xff0c;用于…...

pycharm 设置环境出错

pycharm 设置环境出错 pycharm 新建项目&#xff0c;设置虚拟环境&#xff0c;出错 pycharm 出错 Cannot open Local Failed to start [powershell.exe, -NoExit, -ExecutionPolicy, Bypass, -File, C:\Program Files\JetBrains\PyCharm 2024.1.3\plugins\terminal\shell-int…...