最近使用smartctl对usb硬盘获取smart信息识别。所以就仔细查了看原因。同时又记起一起使用hdparm对硬盘休眠时,usb硬盘也是有问题,使用了什么pass through方法?那时没有深入的去了解,这次正好仔细看了看代码和相关问题。

关键字

hdparm、smartctl、ATA/ATAPI command set、scsi command set、SAT、ATACB

要解决的问题

1:为什么smartctl对usb设备会失败?能否有解决的方法?

2:hdparm对usb失败后,采取的方法能否对smartctl是否有效?

查找思路

因为是用smartctl工具对usb硬盘失效的,所以就使用strace调试smartctl到底使用哪些ioctl。

ioctl(3, SG_IO, {'S', SG_DXFER_FROM_DEV, cmd[16]=[85, 08, 0e, 00, 00, 00

查找内核代码发现,0x85是ATA_16是个ata pass through命令。

sata硬盘将scsi命令转换成ata命令的函数是:ata_scsi_queuecmd--->__ata_scsi_queuecmd

该函数遵循的标准是SAT(scsi to ata translate spec),即如何将scsi命令转成ata命令。

在这个函数中发现:真正转成ata命令后,发送到sata控制器是使用:ata_scsi_translate;

而使用已有的数据来模拟scsi命令的是ata_scsi_simulate。

这里必须说明一点的是,这两个函数都是SAT标准的一部分,只是一些scsi命令的结果不需要再向sata 控制器发送,只要根据已知数据就可以填充返回值。

ata_scsi_translate

其功能就是根据scsi命令找到合适的转换函数。即ata_get_xlat_func根据scsi命令返回合适的函数。

static inline ata_xlat_func_t ata_get_xlat_func(struct ata_device *dev, u8 cmd)
{
 switch (cmd) {
 case READ_6:
 case READ_10:
 case READ_16:

case WRITE_6:
 case WRITE_10:
 case WRITE_16:
  return ata_scsi_rw_xlat;

case SYNCHRONIZE_CACHE:
  if (ata_try_flush_cache(dev))
   return ata_scsi_flush_xlat;
  break;

case VERIFY:
 case VERIFY_16:
  return ata_scsi_verify_xlat;

case ATA_12:
 case ATA_16:
  return ata_scsi_pass_thru;

case START_STOP:/*power management*/
  return ata_scsi_start_stop_xlat;
 }

return NULL;
}

通过这个函数可以看出,真正装换ata命令的基本都是读写函数。

但是ata command set命令很多,比如:smart相关、power management、hpa相关。但是上面的函数均没有处理。那么这些函数该如何处理的?这就迁出了SAT spec中最重要的两个命令:ATA_12、ATA_16.

这两个命令就是告诉SATL,scsi命令集cdb中包含不是scsi command,而是真正的ata 命令,SATL只需要将其完整的发送ATA 设备即可。转换的函数是ata_scsi_pass_thru。

以上就是一个简单的sata硬盘接收命令的过程。

这里又有一个问题:如果用户程序例如smartctl发送的scsi命令不是ATA_12/16,而是直接的smart相关ata命令,那么是不是SATL就无法处理?是的如果仍然使用SG_IO,发送的是标准ATA command这是错误。使用SG_IO,只能发送SAT spec支持的命令.否则就会被丢弃。

但是我使用strace hdparm -y /dev/sda时发现hdparm使用的不是SG_IO,命令是标准的ATA命令。那么它们是如何实现的?
ioctl(3, 0x31f, 0x7fffadc97e10)         = 0

查内核代码0x31f=HDIO_DRIVE_CMD。ioctl的执行情况:sd_ioctl--》scsi_cmd_ioctl---》scsi_ioctl--》sdev->host->hostt->ioctl

而scsi host的ioctl是ata_scsi_ioctl---》ata_cmd_ioctl。该函数的功能是将标准ATA命令,按照SAT SPEC转换成ATA_16命令后,生成request插入request 队列,回到了ata_scsi_queuecmd。
   这样虽然两个工具的ioctl不同,但是在内核中最终走到一起。

我们这里先解决问题2,即hdparm对usb设备失败的原因:usb存储的scsi host template是:struct scsi_host_template usb_stor_host_template。这个数据没有ioctl,所以0x31f命令是没有办法执行的,所以在scsi_ioctl函数中找不到任何可以执行的函数,就只能return -EINVAL;

如果我们将hdparm发送的命令改成SG_IO方式。就不会出错了。下面是改后的代码:
 int dm_start_hdardisk_standby(const char * disk_name)
{
        int fd = 0;
        struct sg_io_hdr io_hdr;
        unsigned char ssuBlk[START_STOP_CMDLEN] = {START_STOP_CMD, 0, 0, 0, 0, 0}; /*cdb*/
        unsigned char sense_b[SENSE_BUFF_LEN];
        int time_secs;
 
        if (disk_name == NULL){
                printf("%s(%d):parameter error:%s/n", __FUNCTION__, __LINE__, disk_name);
                return DM_ERR_PARAM;
        }
       
 
        fd = open(disk_name, O_RDONLY);
 
        if (fd < 0){
                printf("%s(%d): open %s error(%s)l/n", __FUNCTION__, __LINE__, disk_name, strerror(errno));
                return DM_EOPEN;
        }
 
        if ( system("sync") != 0 )
        {
            printf("%s(%d): system(sync): fail(%s)/n", __FUNCTION__, __LINE__,strerror(errno));
        }
 
         ssuBlk[4] = 0;/*from active to standby*/
       
         memset(&io_hdr, 0, sizeof(struct sg_io_hdr));
         io_hdr.interface_id = 'S';
         io_hdr.dxfer_direction = SG_DXFER_NONE;
         io_hdr.cmdp = ssuBlk;
         io_hdr.cmd_len = START_STOP_CMDLEN;
 
         memset(sense_b, 0, SENSE_BUFF_LEN);
         io_hdr.sbp = sense_b;
         io_hdr.mx_sb_len = SENSE_BUFF_LEN;
         io_hdr.timeout = ((time_secs > 0) ? (time_secs * 1000) :  DEF_TIMEOUT);
 
          if (ioctl(fd, SG_IO, &io_hdr) < 0){
                        printf("ioctl error(%s)/n", strerror(errno));
                        close(fd);
                        return DM_EIOCTL;
          }

使用SG_IO命令,command是标准的scsi命令,在ata_get_xlat_func中有对START_STOP的处理。

但是这仅仅是对正常的sata硬盘而言,那么对usb硬盘会这样吗?

usb硬盘

usb storage spec中说明了usb存储中的command set。

static int get_protocol(struct us_data *us)
{
 switch (us->subclass) {
 case US_SC_RBC:
  us->protocol_name = "Reduced Block Commands (RBC)";
  us->proto_handler = usb_stor_transparent_scsi_command;
  break;

case US_SC_8020:
  us->protocol_name = "8020i";
  us->proto_handler = usb_stor_ATAPI_command;
  us->max_lun = 0;
  break;

case US_SC_QIC:
  us->protocol_name = "QIC-157";
  us->proto_handler = usb_stor_qic157_command;
  us->max_lun = 0;
  break;

case US_SC_8070:
  us->protocol_name = "8070i";
  us->proto_handler = usb_stor_ATAPI_command;
  us->max_lun = 0;
  break;

case US_SC_SCSI:
  us->protocol_name = "Transparent SCSI";
  us->proto_handler = usb_stor_transparent_scsi_command;
  break;

case US_SC_UFI:
  us->protocol_name = "Uniform Floppy Interface (UFI)";
  us->proto_handler = usb_stor_ufi_command;
  break;

这是根据usb 控制器芯片的subclass来选择合适的命令集,我们一般见到的都是US_SC_SCSI。至少我没有见过其他类型的。这说明命令集是scsi,即在驱动中并不转成ata command,这个转换是在usb芯片中完成的。

但是我们使用smartctl时是失败,那么这是什么原因?查看smartctl发现有下面的内容:

USB devices and smartmontools

To access USB storage devices, the operating system sends SCSI commands through the USB transport to the device. If the USB device is actually a PATA or SATA disk in an USB enclosure, the firmware of its USB bridge chip translates these commands into the corresponding ATA commands. This works straightforward for read and write commands, but not for SMART commands.

To access SMART functionality, smartmontools must be able to send ATA commands directly to the disk. For USB devices, at least the following conditions must be met:

  • The USB bridge provides an ATA pass-through command.
  • This command is supported by smartmontools.
  • The operating system provides a SCSI pass-through I/O-control which works through its USB-layer.
  • SCSI support is implemented in the operating system interface of smartmontools.

Some recent USB bridges already support the vendor independent SAT (SCSI/ATA Translation, ANSI INCITS 431-2007) standard. Other USB bridges provide vendor specific ATA pass-through commands. The current version of smartmontools supports the following pass-through commands and USB bridges:

Command USB bridges smartctl option 48-bit ATA support Comment
SAT ATA pass-through 12 and 16 various (Initio, Oxford, ...) -d sat[,16]; -d sat,12 requires '-d sat[,16]' Older Linux kernels may require '-d sat,12'
Cypress ATACB Cypress CY7C68300B/C (AT2LP), CY7C68310 (ISD-300LP) -d usbcypress[,CMD] No CY7C68300A (AT2) may not work.
JMicron ATA pass-through JMicron JM20329, JM20335-39 -d usbjmicron[,x][,PORT] No:JM20327, Yes:JM20336/9 '-d usbjmicron,x' enables 48-bit support
Sunplus ATA pass-through Sunplus SPIF215/6, SPIF225/6 -d usbsunplus Yes  

Smartmontools was successfully tested with many USB devices on several Platforms. This will never work on MacOS X unless someone adds SCSI pass-through support to this OS. If the USB ID can be obtained from the operating system, smartmontools also supports auto-detection of (the already tested) USB devices. Then it is not necessary to specify the '-d' option. See the following table for details:

Platform ...has SCSI pass-through smartmontools supports SCSI ... supports USB ... auto-detection ... in smartd DEVICESCAN Comment
Linux Yes Yes YES YES YES See comment about SAT in above table
MacOS X No No No No No USB works with e.g. XP in a VM
FreeBSD Yes Yes YES YES YES  
NetBSD Yes Yes YES No No  
OpenBSD Yes Yes YES No No  
Solaris Yes Yes YES No No  
QNX ? No No No No  
OS/2 ? No No No No  
Windows NT/2K/XP/Vista Yes Yes YES YES No Auto-detection is slow due to the use of 'wmic.exe'
Windows 9x/ME Yes Yes YES No No Requires ASPI driver

usb芯片并不是将所有的scsi命令都按照SAT转换ATA的。所以有些命令是不支持的。
目前usb存储芯片:
1:支持标准SAT,使用ATA_12/16
2:支持自己的特殊命令如ATACB,类似于ATA_12/16,比如cypress公司的芯片。
在linux-2.6.28中的cypress-atacb.c中就是第二中方案:Support for emulating SAT (ata pass through) on devices based  on the Cypress USB/ATA bridge supporting ATACB.
完成该功能的函数是cypress_atacb_passthrough。
目前可以说hdparm和smartctl对usb硬盘不工作的原因是不同的。如果使用sdparm usb就会可以。但是smartctl是需要芯片支持的。所以在最新的smartctl中使用-d后面加参数。就是根据各自的芯片,填写标准ATA_16或者vendor spec comand。
可以在smartctl的主页中查找支持哪些usb芯片。
   usb芯片是否支持SAT或者特殊的如ATACB,需要看datasheet。

smartctl/hdparm对usb 硬盘识别的原因相关推荐

  1. USB无法识别原因分析及解决方案

    一.为什么U盘插上USB口后,电脑不认,没有出现"可移动磁盘"?怎么办? 原因:USB口接触不好 办法:拔下,等十秒钟再插上USB口,使接触完好! 原因:电脑的USB功能没有打开 ...

  2. 服务器固态硬盘无法识别硬盘,固态硬盘无法识别的原因及解决方法

    硬盘故障的原因很多,排除硬盘出现坏道.电路板烧毁等本身硬件损坏外,因主板或系统设置不正确而无法找到硬盘的现象也是时时发生的.譬如在更换计算机主板.电源后,或多或少的因为设置不正确而使系统无法正确识别硬 ...

  3. 读不到盘如何恢复数据?硬盘不被识别数据恢复?硬盘无法识别的原因

    硬盘方便我们存储数据的同时,也会带来一些小问题,比如有时候我们在使用移动硬盘的时候,发现插入电脑后无法识别到设备,这种情况我们该怎么处理呢? 解决方案:重新安装移动硬盘驱动器 在电脑控制面板中打开设备 ...

  4. 计算机usb无法识别网络连接,usb无法识别是什么原因 usb无法识别解决方法【详解】...

    导读:在这个信息十分发达的时代,几乎所有的人都拥有一个USB设备,USB设备是一种拥有USB接口的电子设备,我们可以通过USB数据线将USB设备和一些其他设备连接起来,然后再对其进行相应的操作,但是我 ...

  5. 进入U盘PE系统无法识别硬盘分区的原因分析和解决方法

    进入U盘PE系统无法识别硬盘分区的原因分析和解决方法 时间:2015-07-15     来源:http://www.xitongtiandi.com/    复制网址        进入U盘PE系统 ...

  6. 硬盘工作不正常计算机无法识别,电脑硬盘无法识别的原因及修复方法

    电脑硬盘无法识别的原因及修复方法 系统无法识别硬盘故障解析 在重新安装系统时去提示找到硬盘,相信有不少用户都遇到过这种问题.硬盘做为电脑中的重要存储设备,其重要性是不言而喻的,出现故障的频率想对于主板 ...

  7. 硬盘工作不正常计算机无法识别,硬盘无法识别的原因及解决方法

    硬盘做为电脑中的重要存储设备,其重要性是不言而喻的,硬盘中存放着大量的数据,一旦出现故障,损失是很严重的.硬盘无法识别的故障,相信有不少用户都遇到过.那么遇到这这种问题怎么解决呢?下面小编给大家分析一 ...

  8. 计算机管理里显示磁盘丢失,电脑识别不出硬盘是什么原因?如何恢复硬盘丢失的文件...

    电脑识别不出硬盘是什么原因?绝大多数硬盘都是固定硬盘,被永久性地密封固定在硬盘驱动器中.早期的硬盘存储媒介是可替换的,不过今日典型的硬盘是固定的存储媒介,被封在硬盘里 (除了一个过滤孔,用来平衡空气压 ...

  9. 嵌入式linux 不识别sata,sata硬盘识别不了的常见问题和解决方法

    sata硬盘也叫串口硬盘,因为支持热插拔.传输速度快等优点被广泛应用.但是使用过程中由于供电和兼容性问题,经常会碰到sata硬盘识别不了的情况,应该如何解决呢? 下面我们以西数sata硬盘和绿联外置易 ...

最新文章

  1. 在虚拟机下安装DOS 6.22(上)
  2. 学python入门书-如何学习Python,以及新手如何入门?
  3. Apache Web Server - httpd 的虚拟主机的配置
  4. java终结器_Java的终结器仍然存在
  5. IDEA项目 let报错爆红
  6. java中面向对象租车问题_答答租车系统-Java面向对象的学习
  7. 2011年倒数第三天,下雪,第一次写博客
  8. Java 表达式解析(非原创)
  9. 黑客们成功地在土豆上安装了Linux!
  10. 自从我不管事后,员工们肯定舒心多了
  11. TextView用法及实例
  12. 笔记《Hbase 权威指南》
  13. MHL中的packedpixel概念
  14. eclipse设置pom.xml打开方式
  15. 图像配准融合(一)——基于互信息的图像配准方法(c++)
  16. sql函数能判断字段是否包含英文
  17. C#,图像二值化(17)——全局阈值的ISODATA算法(亦称作InterMeans法)及其源程序
  18. shell逐行读取excel并执行sql
  19. 【物理应用】基于粒子群优化算法实现瞬变电磁法视电阻率反演附matlab代码
  20. 淘宝店铺标题栏CSS代码

热门文章

  1. vue学习记录-05 事件监听
  2. 计算机开机慢更新配置,电脑开机慢怎么办
  3. css 字间距离_css 字体字符间距设置
  4. 浪潮服务器安装乌班图系统,傻瓜书 手把手教你在VMware中试用Ubuntu
  5. linux发行版 2016,2016年2月linux发行版关注度排行
  6. EMUI11什么时候升级鸿蒙,华为EMUI11.1有望于下月发布 改用鸿蒙内核 可升级机型曝光...
  7. td内有图片和文字,如何都垂直居中
  8. mysql 返回 pair_【原创】MySQL Proxy中socketpair的使用
  9. selenium webdriver 鼠标悬浮事件
  10. ryzen7能否安装linux,AMD 锐龙(Ryzen)7 装win7系统及bios设置教程(完美支持)