SCSI层代码分析(1)SCSI HOST的管理

        本节首先对scsi host相关的结构体做描述,然后介绍scsi host的管理包括scsi host的分配/释放以及添加到系统中。

1. scsi host相关结构体介绍

1.1  scsi_host结构体

        当OS通过HBA与硬盘进行交互之前,需要识别当前的HBA,然后才能识别连接到HBA上的硬盘。从SCSI层到LLDD层(有些驱动可能使用libsas层,有些没有),每一层都存在表示HBA的结构体。在SCSI层使用的是结构体scsi host。

结构体Scsi_Host各成员

__devices

识别到的scsi device

__targets

识别到的scsi target

starved_list

可能长时间没有得到执行的scsi device

default_lock

host_lock

Scsi host锁

scan_mutex

扫描过程使用锁

eh_abort_list

Scsi abort时放入此链

eh_cmd_q

EH时将异常的命令放入此链

ehandler

错误处理线程

Eh_action

host_wait

hostt

Scsi_host_template每个驱动需要填充的模板

transportt

Scsi_transport_template 传输层模板,驱动可以覆盖

tag_set

Share tag驱动使用的blk_mq_tag_set

host_blocked

被阻塞的host数目

Host_failed

host_eh_scheduled

尝试调用EH的次数

host_no

Host id

eh_deadline

last_reset

上次reset时间

max_channel

支持最大channel

max_id

支持最大ID

max_lun

支持最多lun

unique_id

独一无二的id

max_cmd_len

最大命令长度

This_id

can_queue

表示队列最大深度

与scsi_host_template中相应的成员一样

Cmd_per_lun

表示每个硬盘深度

Sg_tablesize

表示最大segment数目

Sg_prot_tablesize

表示最大segment数目(DIF)

Max_sectors

表示IO支持最大sector

Max_segment_size

表示IO支持最大segment的size

Dma_boundary

Virt_dma_boundary

Nr_hw_queues

表示支持的硬件队列数目

Nr_maps

表示支持的map数目

active_mode

Host_self_blocked

Reserse_ordering

Tmf_in_progress

async_scan

异步扫描正在进行中

eh_noresume

=1 在错误处理之前不去唤醒scsi host

=0 在错误处理前唤醒scsi host

No_write_same

Host_tagset

表示使用share-tag

Show_inquiry

No_scsi2_lun_in_cdb

Work_q_name[20]

Work_q

workqueue

Tmf_work_q

max_host_blocked

Prot_capabilities

保护信息的能力

Prot_guard_type

保护信息的guard类型

base

目前驱动很少用

Io_port

N_io_port

Dma_channel

irq

Shost_state

Scsi host的状态

shost_gendev

Scsi host对应的gendev

shost_dev

Scsi host对应的device

Shost_dev_attr_groups[3]

Shost dev对应的属性

Shost_data

一般用于指示到底层驱动对应的hba结构体

dma_dev

hostdata[]

可用于存储host相关数据

暂时只对常用的成员对简单的解释,比较重要的可分如下几类:

  1. 底层驱动或硬件的相关限制,如max_sectors/sg_tagblesize/can_queue/nr_hw_queues等;
  2. Scsi host自身相关,如host_no/shost_data/host_blocked/host_failed/shost_state/lock等;
  3. Scsi host扫描设备过程中用到的,如__devices/__targets/scan_mute等;

其他还有很多成员,真正用到时再做分析。

1.2 scsi_host_template结构体

        结构体Scsi_host_templace是非常重要的结构体,每个SCSI驱动必须定义此结构体,并进行填充。

结构体scsi_host_template各成员

成员名

含义

备注

cmd_size

提前分配request/scsi command时可以为底层驱动分配的per-command数据大小

queuecommand

IO下发函数

各SCSI驱动需要填充

commit_rqs

暂不分析

module

模块

name

名称

info

ioctl()

init_cmd_priv()

exit_cmd_priv()

若cmd_size中定义底层驱动私有结构长度,可以通过此接口初始化私有结构,若未定义此接口默认清0

eh_abort_handler()

SCSI错误处理函数,用于abort一个SCSI命令

错误处理使用,逐步升级处理

eh_device_reset_handler()

SCSI错误处理函数,用于对device发送device reset

eh_target_reset_handler()

SCSI错误处理函数,用于对target发送target reset

eh_bus_reset_handler()

SCSI错误处理函数,用于发送bus reset

eh_host_reset_handler()

SCSI错误处理函数,用于发送host reset

slave_alloc()

在SCSI device识别过程中调用

驱动可以根据当前驱动自定义特定的操作

slave_configure()

在SCSI device识别过程中调用

slave_destroy()

在SCSI device释放过程中调用

target_alloc()

在SCSI target识别过程中调用

驱动可以根据当前驱动自定义特定的操作

target_destroy()

在SCSI target释放过程中调用

scan_finished()

判断是否扫描scsi device结束

scan_start()

开始扫描scsi device

change_queue_depth()

用于修改scsi device的队列深度

map_queue()

用于驱动将硬件队列映射到BLOCK层

mq_poll()

用于poll接口

dma_need_drain()

Bios_param

Unlock_native_capacity

Show_info()

用于将驱动数据和信息导出到用户态

Write_info()

用于将驱动数据和信息导出到用户态

eh_timed_out()

可选路径,

eh_should_retry_cmd

用于驱动决定是否重试SCSI命令

host_reset()

控制器复位接口

Proc_name

Proc名字

Proc_dir

proc目录

can_queue

硬件队列深度

This_id

sg_tablesize

每个IO最大segment数目

Sg_prot_tablesize

每个IO最大segment数目(DIF)

max_sectors

每个IO支持最大sector

max_segment_size

每个segment最大的size

dma_boundary

DMA边界

Virt_boundary_mask

cmd_per_lun

队列深度

present

在增加proc hostdir时增加,表示有多少个host

tag_alloc_policy

默认不设置为BLK_TAG_ALLOC_FIFO,可以设置为BLK_TAG_ALLOC_RR

track_queue_depth

跟踪QUEUE_FULL事件,减少队列深度

supported_mode

默认为MODE_INITIATOR

emulated

skip_settle_delay

是否在eh_host_reset_handler之后需要休眠HOST_RESET_SETTLE_TIME秒

no_write_same

是否控制器支持WRITE SAME

host_tagset

是否为share tag驱动

max_host_blocked

最大host被blocked次数

shost_groups

Scsi host的sysfs属性相关

sdev_groups

Scsi device的sysfs属性相关

vendor_id

厂商ID

cmd_pool

当前没有使用,可删除

Rpm_autosuspend_delay

是否开启scsi device的autosuspend延时,与scsi/block runtime PM相关

        每个SCSI驱动需要填充结构体scsi_host_template,但并不是每个成员都需要填充,默认不填会使用默认值,根据驱动自身情况进行修改。正如名字一样,它为scsi host的模板,每个驱动需要定义。

2. scsi host的管理

        Scsi host代表HBA控制器,SCSI HOST的管理包括SCSI HOST的分配/释放,将SCSI HOST添加到系统以及对SCSI HOST的扫描(此步在下一节介绍)。这三步一般为SCSI驱动进行调用,是SCSI驱动的必须固定步骤。

2.1 scsi host的分配

        Scsi host的分配是由函数scsi_host_alloc()实现的,它有两个输入参数:scsi_host_template和privsize。根据scsi_host_template填充scsi host部分成员,privsize是底层驱动让SCSI在分配scsi host时为底层驱动分配的内存,即scsi host->hostdata[]成员。

主要设置如下:

  1. Host_no,scsi host的id;
  2. Shost->hostt = scsi_host_template
  3. 与scsi_host_template一样的参数,如can_queue / sg_tablesize / cmd_per_lun / max_sectors /max_segment_size /dma_boundary等;
  4. sysfs相关属性;
  5. 创建错误处理线程shost->ehandler;
  6. 用于abort SCSI命令的工作队列tmf_work_q;
  7. 将scsi host 添加到proc文件系统中;

2.2 scsi host的释放

        Scsi host的释放是由函数scsi_remove_host()实现的,在这里需要注意的,shost->shost_gendev的unregister将引用计数减为0时,才会调用scsi_host_dev_release()做shost_gendev相关的资源释放。

 

2.3 scsi host的添加

        Scsi host的添加指的是将scsi host添加到系统中,主要通过函数scsi_add_host()实现。过程如下:

  1. 创建scsi_sense_cache缓冲区;
  2. 为scsi host分配tag_set,进行相关设置,设置tag_set->ops,并调用blk_mq_alloc_tag_set()提前分配request和tag,对CPU和hctx进行映射(见BLOCK层代码分析(7)IO下发之request的分配和获取);
  3. 将shost_gendev和shost_dev添加到系统中;
  4. 将scsi host添加到sysfs文件系统中;
  5. 将scsi host添加到proc文件系统中;

 

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值