硬盘防震保护

作者:Elias Oltmanns <eo@nebensachen.de>

最后修改:2008-10-03

1. 简介

ATA/ATAPI-7 规范通过卸载功能(unload feature)指定了 IDLE IMMEDIATE 命令。发出此命令应使驱动器切换到空闲模式并卸载磁头。此功能在现代笔记本电脑中与加速度计和适当的软件结合使用,以实现防震保护。其理念是在预料到危急情况时,停止内部硬盘上的所有 I/O 操作,并将磁头停泊在斜坡上。在 GNU/Linux 系统上提供此功能的需求,是实现 Linux 内核中通用磁盘磁头停泊接口的最初动机。然而,请注意,您的系统必须设置其他组件才能使磁盘防震保护正常工作(有关更多信息,请参阅下面的第 3 节“参考”)。

2. 接口

对于每个 ATA 设备,内核在 sysfs 中(此处假设挂载在 /sys 下)导出文件 block/*/device/unload_heads。如果设备不支持卸载功能,则访问 /sys/block/*/device/unload_heads 将被拒绝,并返回 -EOPNOTSUPP。否则,向此文件写入整数值将使相应驱动器的磁头离开盘片,并在指定毫秒数内阻止所有 I/O 操作。当超时到期且在此期间没有发出进一步的磁头停泊请求时,将恢复正常操作。超时接受的最大值为 30000 毫秒。超过此限制将返回 -EOVERFLOW,但磁头仍将停泊,并且超时将设置为 30 秒。但是,您始终可以通过在上次超时到期之前发出后续的磁头停泊请求,将超时更改为 0 到 30000 之间的任何值。特别是,总超时可以超过 30 秒,更重要的是,您可以通过指定 0 作为超时来取消先前设置的超时并立即恢复正常操作。小于 -2 的值将被拒绝,并返回 -EINVAL(有关 -1 和 -2 的特殊含义,请参见下文)。如果最近的磁头停泊请求指定的超时尚未到期,从 /sys/block/*/device/unload_heads 读取将报告恢复正常操作前剩余的毫秒数;否则,读取 unload_heads 属性将返回 0。

例如,执行以下操作,使 /dev/sda 驱动器的磁头停泊,并停止所有 I/O 操作五秒钟

# echo 5000 > /sys/block/sda/device/unload_heads

一个简单的

# cat /sys/block/sda/device/unload_heads

将显示在恢复正常操作之前还剩多少毫秒。

提醒:接口以毫秒为单位操作的事实可能会引发在现实中无法满足的期望。事实上,ATA 规范明确指出卸载操作完成所需的时间是供应商特定的。ATA-7 中关于这通常在 500 毫秒内完成的提示,在 ATA-8 中似乎已被删除。

此实现有一个技术细节可能会引起一些混淆,应在此处讨论。当成功向设备发出磁头停泊请求后,该设备所连接的控制器端口上的所有 I/O 操作都将被延迟。也就是说,连接到同一端口的任何其他设备也会受到影响。唯一的例外是,向该其他设备发出的后续磁头卸载请求将立即执行。该端口上的进一步操作将延迟,直到该端口上任一设备指定的超时到期。就 PATA(旧式 IDE)配置而言,任何单个端口上只能连接两个设备。在 SATA 世界中,我们有端口倍增器,这意味着用户向一个设备发出的磁头停泊请求实际上可能导致停止对一整批设备的 I/O。然而,由于此功能旨在用于笔记本电脑,并且在任何其他环境中似乎都不是很有用,因此每个端口上大多只有一个设备。即使 CD/DVD 刻录机碰巧连接到与硬盘相同的端口,它通常也应该能很好地从由于对硬盘发出磁头停泊请求而偶尔发生的缓冲区欠载中恢复。实际上,当您使用 ide 驱动程序而不是其 libata 对应驱动程序时(即您的磁盘名为 /dev/hda 而不是 /dev/sda),那么停泊一个驱动器(驱动器 X)的磁头通常不会像上面所描述的那样影响同一端口上另一个驱动器(驱动器 Y)的操作模式。只有当需要端口重置才能从驱动器 Y 上的异常中恢复时,该驱动器上的进一步 I/O 操作(以及重置本身)才会被延迟,直到驱动器 X 不再处于停泊状态。

最后,有些硬盘只符合早于 ATA-7 的 ATA 标准版本,但仍支持卸载功能。不幸的是,Linux 没有安全的方法来检测这些设备,因此您将无法写入 unload_heads 属性。如果您知道您的设备确实支持卸载功能(例如,因为您的笔记本电脑或硬盘本身供应商告诉过您),那么您可以通过将特殊值 -1 写入 unload_heads 属性来告诉内核为该驱动器启用此功能的使用

# echo -1 > /sys/block/sda/device/unload_heads

将为 /dev/sda 启用该功能,而输入 -2 而不是 -1 则会再次禁用它。

3. 参考

来自不同供应商的几款笔记本电脑都具有防震保护功能。由于制造商迄今为止拒绝支持所需软件组件的开源开发,因此 Linux 对防震保护的支持在不同的硬件实现之间差异很大。理想情况下,本节应包含指向旨在在不同系统上实现防震保护的不同项目的列表。不幸的是,我只知道一个项目,尽管仍被认为是实验性的,但适合使用。请随意添加那些因我的疏忽而被遗漏的项目。

4. 致谢

此磁头停泊的实现受到了 Jon Escombe <lists@dresco.co.uk> 最初发布的补丁的启发。我在开发此功能的实现以使其适合合并到主线方面的工作得到了各种内核开发人员的帮助,特别是 Tejun Heo 和 Bartlomiej Zolnierkiewicz。