目录
1. 硬盘启动协议

2.SCSI总线扫描的方法
-
SCSI总线扫描是通过协议特定或者芯片特定的方法探测出挂接在主机适配器后面的目标节点和逻辑单元,为它们在内存中构建相应的数据结构并把它们添加到系统中。
方法:
- scsi中间层以可能的ID和LUN构造INQUIRY命令,之后将这些命令提交给I/O子系统后,通过SCSI上层磁盘驱动处理生成请求,后通过SCSI中间层将请求转换成CDB,最后调用SCSI底层驱动的queuecommand回调函数实现命令发送。
3. 内核打印信息
-
硬盘开机.内核函数跟踪打印信息
ata1.02: SATA link down (SStatus0SControl310)ata1.03: hard resetting linkata1.03: SATA link down (SStatus0SControl310)ata1.04: hard resetting linkata1.04: SATA link down (SStatus0SControl310)ata1.00: ATA-9: WDC WD5000LUCT-63C26Y0,01.01A01, max UDMA/133ata1.00:976773168sectors, multi0: LBA48 NCQ (depth31/32)ata1.00: configuredforUDMA/133ata1: EH completescsi0:0:0:0: Direct-Access ATA WDC WD5000LUCT-601.0PQ:0ANSI:5------------[ cut here ]------------WARNING: at drivers/scsi/sd.c:2936sd_probe+0x1c/0x378()Modules linked in:CPU:2PID:6Comm: kworker/u8:0Not tainted3.10.0_hi3536 #6Workqueue: events_unbound async_run_entry_fn[<80019e10>] (unwind_backtrace+0x0/0xf4) from [<80016ea4>] (show_stack+0x10/0x14)[<80016ea4>] (show_stack+0x10/0x14) from [<8002c278>] (warn_slowpath_common+0x54/0x6c)[<8002c278>] (warn_slowpath_common+0x54/0x6c) from [<8002c32c>] (warn_slowpath_null+0x1c/0x24)[<8002c32c>] (warn_slowpath_null+0x1c/0x24) from [<80338860>] (sd_probe+0x1c/0x378)[<80338860>] (sd_probe+0x1c/0x378) from [<8031a224>] (driver_probe_device+0x78/0x214)[<8031a224>] (driver_probe_device+0x78/0x214) from [<80318898>] (bus_for_each_drv+0x58/0x8c)[<80318898>] (bus_for_each_drv+0x58/0x8c) from [<8031a17c>] (device_attach+0x74/0x88)[<8031a17c>] (device_attach+0x74/0x88) from [<803197a0>] (bus_probe_device+0x84/0xa8)[<803197a0>] (bus_probe_device+0x84/0xa8) from [<80317efc>] (device_add+0x4ec/0x59c)[<80317efc>] (device_add+0x4ec/0x59c) from [<80331f34>] (scsi_sysfs_add_sdev+0x84/0x294)[<80331f34>] (scsi_sysfs_add_sdev+0x84/0x294) from [<803300d0>] (scsi_probe_and_add_lun+0x8bc/0x98c)[<803300d0>] (scsi_probe_and_add_lun+0x8bc/0x98c) from [<803304a0>] (__scsi_add_device+0xf4/0x104)[<803304a0>] (__scsi_add_device+0xf4/0x104) from [<8034ac5c>] (ata_scsi_scan_host+0xb0/0x234)[<8034ac5c>] (ata_scsi_scan_host+0xb0/0x234) from [<80050df4>] (async_run_entry_fn+0x48/0x184)[<80050df4>] (async_run_entry_fn+0x48/0x184) from [<800452c8>] (process_one_work+0x10c/0x370)[<800452c8>] (process_one_work+0x10c/0x370) from [<80045fd0>] (worker_thread+0x138/0x3fc)[<80045fd0>] (worker_thread+0x138/0x3fc) from [<8004b24c>] (kthread+0xb4/0xb8)[<8004b24c>] (kthread+0xb4/0xb8) from [<800130d8>] (ret_from_fork+0x14/0x3c)---[ end trace 63dc1c18fe366fe2 ]---sd0:0:0:0: Fix disk[0:0:0:0] to sdesd0:0:0:0: [sde]976773168512-bytelogical blocks: (500GB/465GiB)sd0:0:0:0: Attached scsi generic sg0 type0<ata_scsi_scan_host>:hd [0:0:0:0] change hd status to HD_STATUS_OKsd0:0:0:0: [sde]4096-bytephysical blockssd0:0:0:0: [sde] Write Protect is offsd0:0:0:0: [sde] Write cache: enabled, read cache: enabled, doesn't support DPO or FUAsde: sde1 sde2 sde3 sde4sd0:0:0:0: [sde] Attached SCSI diskata2: SATA link down (SStatus0SControl300)ata3: SATA link down (SStatus0SControl300)ata4: SATA link down (SStatus0SControl300) -
信息解读
-
基本参数:
-
ata1.02表示的是ata的prot1,复用端口号2
-
max UDMA/133:最大读取速度133MB/s
-
LBA48:指以48位逻辑寻址的方式使用硬盘
-
NCQ:原生命令队列技术是一种使硬盘内部优化工作负荷执行顺序,通过对内部队列中的命令进行重新排序实现智能数据管理,改善硬盘因机械部件而受到的各种性能制约。
-
EH complete:error handler complete
-
- 流程处理
- 首先是ata卡硬件初始化与故障处理,并打印了硬盘的相关信息
- 之后开始扫描硬盘信息,上面为扫描过程中的调用关系
- 打印识别信息
- 依次扫描其他ata端口
- dump_stack信息
- 通过工作队列async_run_entry_fn扫描scsi的host,chanle,target,device
- 最后通过sd_probe关联到block_device,到通用块层。
-
-
硬盘热插拔.内核函数跟踪打印信息
硬盘断电:ata1.00: exception Emask0x10SAct0x0SErr0x10002action0xfata1.00: SError: { RecovComm PHYRdyChg }ata1.00: hard resetting linkata1.00: SATA link down (SStatus0SControl310)ata1.00: hard resetting linkata1.00: SATA link down (SStatus0SControl310)ata1.00: limiting SATA link speed to1.5Gbpsata1.00: hard resetting linkata1.00: SATA link down (SStatus0SControl310)ata1.00: disabledata1: EH complete<ata_scsi_remove_dev>:hd [0:0:0:0] change hd status to HD_STATUS_NOEXISTata1.00: detaching (SCSI0:0:0:0)sd0:0:0:0: [sde] Synchronizing SCSI cachesd0:0:0:0: [sde]Result: hostbyte=0x04driverbyte=0x00sd0:0:0:0: [sde] Stopping disksd0:0:0:0: [sde] START_STOP FAILEDsd0:0:0:0: [sde]Result: hostbyte=0x04driverbyte=0x00#硬盘上电:ata1.00: exception Emask0x10SAct0x0SErr0x4050000action0xf//ata_eh_link_reportata1.00: SError: { PHYRdyChg CommWake DevExch }ata1.00: hard resetting link//ata_eh_reset --> postreset(slave, classes)(.postreset = ata_std_postreset)ata1.00: SATA link up1.5Gbps (SStatus113SControl310)//ata_std_postreset--> sata_print_link_statusata1.00: ATA-9: WDC WD5000LUCT-63C26Y0,01.01A01, max UDMA/133//ata_dev_configureata1.00:976773168sectors, multi0: LBA48 NCQ (depth31/32)//ata_dev_configureata1.00: configuredforUDMA/133//generic_set_modeata1: EH complete//ata_scsi_port_error_handlerscsi0:0:0:0: Direct-Access ATA WDC WD5000LUCT-601.0PQ:0ANSI:5//scsi_add_lun------------[ cut here ]------------WARNING: at drivers/scsi/sd.c:2936sd_probe+0x1c/0x378()Modules linked in:CPU:0PID:4Comm: kworker/0:0Tainted: G W3.10.0_hi3536 #6Workqueue: events ata_scsi_hotplug[<80019e10>] (unwind_backtrace+0x0/0xf4) from [<80016ea4>] (show_stack+0x10/0x14)[<80016ea4>] (show_stack+0x10/0x14) from [<8002c278>] (warn_slowpath_common+0x54/0x6c)[<8002c278>] (warn_slowpath_common+0x54/0x6c) from [<8002c32c>] (warn_slowpath_null+0x1c/0x24)[<8002c32c>] (warn_slowpath_null+0x1c/0x24) from [<80338860>] (sd_probe+0x1c/0x378)[<80338860>] (sd_probe+0x1c/0x378) from [<8031a224>] (driver_probe_device+0x78/0x214)[<8031a224>] (driver_probe_device+0x78/0x214) from [<80318898>] (bus_for_each_drv+0x58/0x8c)[<80318898>] (bus_for_each_drv+0x58/0x8c) from [<8031a17c>] (device_attach+0x74/0x88)[<8031a17c>] (device_attach+0x74/0x88) from [<803197a0>] (bus_probe_device+0x84/0xa8)[<803197a0>] (bus_probe_device+0x84/0xa8) from [<80317efc>] (device_add+0x4ec/0x59c)[<80317efc>] (device_add+0x4ec/0x59c) from [<80331f34>] (scsi_sysfs_add_sdev+0x84/0x294)[<80331f34>] (scsi_sysfs_add_sdev+0x84/0x294) from [<803300d0>] (scsi_probe_and_add_lun+0x8bc/0x98c)[<803300d0>] (scsi_probe_and_add_lun+0x8bc/0x98c) from [<803304a0>] (__scsi_add_device+0xf4/0x104)[<803304a0>] (__scsi_add_device+0xf4/0x104) from [<8034ac5c>] (ata_scsi_scan_host+0xb0/0x234)[<8034ac5c>] (ata_scsi_scan_host+0xb0/0x234) from [<8034ae88>] (ata_scsi_hotplug+0x70/0x7c)[<8034ae88>] (ata_scsi_hotplug+0x70/0x7c) from [<800452c8>] (process_one_work+0x10c/0x370)[<800452c8>] (process_one_work+0x10c/0x370) from [<80045fd0>] (worker_thread+0x138/0x3fc)[<80045fd0>] (worker_thread+0x138/0x3fc) from [<8004b24c>] (kthread+0xb4/0xb8)[<8004b24c>] (kthread+0xb4/0xb8) from [<800130d8>] (ret_from_fork+0x14/0x3c)---[ end trace 63dc1c18fe366fe3 ]---sd0:0:0:0: Fix disk[0:0:0:0] to sdesd0:0:0:0: Attached scsi generic sg0 type0sd0:0:0:0: [sde]976773168512-bytelogical blocks: (500GB/465GiB)sd0:0:0:0: [sde]4096-bytephysical blockssd0:0:0:0: [sde] Write Protect is offsd0:0:0:0: [sde] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA<ata_scsi_scan_host>:hd [0:0:0:0] change hd status to HD_STATUS_OKsde: sde1 sde2 sde3 sde4sd0:0:0:0: [sde] Attached SCSI disk
-
信息解读
- 流程处理:
- 断电
- 断电后会重连几次,进行错误处理,直到完成
- 移除磁盘,同步scsi缓存
-
hostbyte=0x04表示DID_BAD_TARGET
- 上电
- 和开机启动基本相同
- dump_stack信息
- 磁盘的扫描是通过ata_scsi_hotplug工作队列实现的
- 断电
- 流程处理:
4. 硬盘识别过程
- 系统启动时初始化各文件系统的超级块,分配超级块操作函数
- AHCI平台设备初始化
- 通过驱动和设备匹配,初始化AHCI平台设备
- 添加ATA的SCSI主机适配器,包括两部分,为主机适配器分配数据结构,然后将主机适配器添加到系统
- 初始化并运行错误处理线程scsi_error_handler
- 初始化上电识别硬盘的工作队列async_run_entry_fn和热插拔识别工作队列ata_scsi_hotplug
- ata检测及错误处理
- 运行ahci错误处理函数
- 连接报告
- 发送ata id查询命令获取硬盘基本信息,共512字节
- 将ata命令转换成FIS,设置host寄存器,
- 传输层发送FIS给链路层,链路层加上SOF,EOF,CRC,加扰,8b/10b转换
- 发送到物理层,物理层发出
- 相反过程接收
- 打印硬盘型号、扇区数、工作模式、寻址方式等
- 硬盘检测
- 探测lun设备,为设备分配了请求队列,设置回调处理函数,设置超时处理函数,设置请求处理函数
- 通过发送SCSI INQUIRY命令探测lun单元
- 该命令先转换成通用块层的request,再把请求进行I/O后加入请求队列。把请求队列发送到请求处理函数scsi_requeset_fn。
- 初始化完成量,定义回调函数,并等待完成量,阻塞
- 在SCSI中间层把请求转换成SCSI CDB。再把命令发送给ata host处理。
- 根据CDB选择合适的处理函数,INQUIRY命令不需要转换成ata命令,通过加载硬盘时获取的ata id 处理。处理完成后调用SCSI中间层回调函数scsi_done。
- 再调用回调函数结束request,发送完成量给阻塞的lun探测。结果返回前其一直阻塞(完成量),根据返回参数注册scsi_device到scsi总线上。
- 总线上的每个driver来匹配device。
- 匹配成功则调用函数sd_probe初始化scsi_device,映射其对应的<host,channel,target,lun>和设备文件名称,同时分配主次设备号。
- 然后通过add_disk注册到通用块层,在通用块层根据初始化的超级块操作函数关联到inode指向的block_device。
- 识别完成。

5. 硬盘识别过程代码调用
|
|
本文深入探讨硬盘启动过程中的SCSI总线扫描方法,详细解释硬盘开机与热插拔时内核函数跟踪打印信息的含义,揭示硬盘识别过程及其代码调用流程。从硬盘启动协议到SCSI命令转换,再到内核层面的错误处理与设备注册,全面剖析硬盘从物理层到系统层的识别机制。
782

被折叠的 条评论
为什么被折叠?



