待机状态下 HDD 启动:防止旋转

待机状态下 HDD 启动:防止旋转

在我的 Linux Mint 17.1 系统上,我使用 Western Digital WD20EZRX HDD 进行备份。为了最大限度地降低功耗并延长驱动器的使用寿命,我希望 HDD 通常处于旋转待机状态,并且仅在明确需要时才旋转。

这可以通过两种方式实现:最简单的方法是使用 手动将 HDD 设置为待机模式hdparm -y /dev/sdb。但是,缺点是驱动器在启动期间旋转,直到通过脚本再次设置为睡眠状态。因此,我想让驱动器待机状态下启动普伊斯,以防止其第一次就旋转起来。

有些 WD 硬盘支持 PUIS,尽管它被称为PM2电源管理2模式Western Digital 提供。此功能使用跳线启用,具体说明如下 此 WD 知识库文章. 可以使用以下命令验证此配置的结果hdparm

# hdparm -I /dev/sdb | grep "Power-Up In Standby"
   *    Power-Up In Standby feature set

但是,在启动过程中,驱动器仍然在旋转,甚至在显示 Grub 启动屏幕之前。这可能是由于 Bootloader 配置错误,导致它正在所有连接的硬盘上寻找操作系统?

答案1

几年前,我也搜索过同样的东西,针对 Linux Mint 和一个仅用于偶尔存储数据的旧硬盘。

我找到的解决方案(不再有链接)和你找到的一样:很少硬盘可能有一个跳线设置应该导致驱动器保持睡眠状态/在启动时不旋转。它不起作用,我的结果和你的完全一样,它仍然在启动时旋转。我没有找到任何修复方法,据我所知,这是 BIOS/GRUB/linux 的问题,无论是单独还是协同工作,或者只是 HD 本身没有监听。

我做了一些“热插拔”/“热交换”测试,在计算机启动并运行时将电源连接到 (SATA) 硬盘驱动器。它生成了一些日志条目 (dmesg & /var/log/syslog) 和成功运作。然后,当驱动器(同步、卸载、睡眠/)完成后,hdparm -y再次拔下电源。成功了!但它显然需要兼容的主板和操作系统,所以 YMMV。

但是,拔掉电源插头来使用驱动器并不方便或容易,所以我接了一个双刀单掷开关 -DPST,维基百科上有一张图- 有 4 个端子,用于连接 2 根独立的电源线(12V 和 5V?),将它们分开并同时打开/关闭。将其连接到 HD 的电源后,我可以在需要时打开和关闭驱动器。

更新:

热插拔用过的在 Linux Mint 14/15/16 上可以工作,但由于某种原因,它在 17 及更高版本上停止工作,我猜是一些内核更改阻止了它。现在热插拔硬盘似乎只起作用,但驱动器读取为损坏,只有开机重启才能成功运行。也许有一种简单的方法可以让它再次运行,或者需要使用一些特殊开关重新编译内核……?

更新 2

热插拔显然在 Ubuntu 16.04 上再次起作用(Mint 18 也应该可以起作用)。

答案2

Linux 内核启动驱动器。查看 drivers/ata/libata-core.c(内核源代码)中的以下几行:

if (!tried_spinup && (id[2] == 0x37c8 || id[2] == 0x738c)) {
    tried_spinup = 1;
    /*
     * Drive powered-up in standby mode, and requires a specific
     * SET_FEATURES spin-up subcommand before it will accept
     * anything other than the original IDENTIFY command.
     */
    err_mask = ata_dev_set_feature(dev, SETFEATURES_SPINUP, 0);
    if (err_mask && id[2] != 0x738c) {
        rc = -EIO;
        reason = "SPINUP failed";
        goto err_out;
    }
    /*
     * If the drive initially returned incomplete IDENTIFY info,
     * we now must reissue the IDENTIFY command.
     */
    if (id[2] == 0x37c8)
        goto retry;
}

如果您注释掉这些行并重新编译内核,驱动器将不会启动。然后您需要一个命令来启动它们,例如,当 hdparm 禁用 PUIS 时,它会启动驱动器。看看这个关联。

这就是我对 PUIS 的全部了解。

编辑: 我刚刚注意到您的驱动器在 grub 屏幕之前启动:这意味着主板正在启动驱动器。您可以尝试在 BIOS/UEFI 配置中禁用相应的 sata 端口(如果允许这样做),然后重试。如果它正常工作,驱动器将保持静止,直到内核启动它,在 grub 屏幕之后和用户登录提示之前,您可以在 dmesg 中找到

ataX.00: failed to IDENTIFY (SPINUP failed, err_mask=0x4)
ataX.00: revalidation failed (errno=-5)
ataX: SATA link up 6.0 Gbps (SStatus 133 SControl 300)

此时,如果您破解内核,驱动器将根本不会旋转,就像我之前描述的那样。

编辑2: 我找到了一个更好的启动磁盘的命令:

sg_sat_set_features --feature=7 /dev/sdX

它是 sg3_utils 包的一部分,需要 root 权限,但可以很好地启动磁盘。 在 Arch Linux 论坛上更新帖子,这是我目前的最终解决方案。该帖子的简短摘要:

  • 如果启用 PUIS 的磁盘在启动加载程序屏幕之前启动,请尝试禁用相应的 SATA 端口,或尝试使用 PCI-ex SATA 控制器卡
  • 重新编译内核以禁用在 PUIS 状态下启动磁盘的命令
  • 使用 sg_sat_set_feature 启动磁盘
  • 重新扫描 SATA 端口以获取对分区的访问权限

编辑3: 有位好心人在 archlinux 论坛上写了一个补丁:https://bbs.archlinux.org/viewtopic.php?pid=1855326#p1855326

转录:

如果无法避免修补 libata,不妨在启动时禁用 PUIS 驱动器,以摆脱无休止的错误消息。缺点是我们必须告诉内核在请求时重新启用它们,因为像 sg_sat* 这样的用户空间工具需要 /dev 内的条目。

看看我针对该功能编写的暂定补丁。我希望有人会考虑抽出时间将其重新设计为内核标准并将其提交给上游。我针对干净的 v4.19.56 编写了该补丁。

重新编译模块并重建 initramfs 映像后,请记住在引导加载程序中设置“libata.spinup_control=0”内核参数!

那你应该

echo 1 > /sys/module/libata/parameters/spinup_control

并对您想要启动的驱动器进行重新扫描。

echo '- - -' > devices/pci0000:00/0000:00:1f.2/ata4/host3/scsi_host/host3/scan

--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -171,6 +171,10 @@ static int atapi_an;
 module_param(atapi_an, int, 0444);
 MODULE_PARM_DESC(atapi_an, "Enable ATAPI AN media presence notification (0=0ff [default], 1=on)");

+static int spinup_control = 1;
+module_param(spinup_control, int, 0644);
+MODULE_PARM_DESC(spinup_control, "Spin up standby drives (0=PUIS drives disabled, 1=standby drives can spin up [default])");
+
 MODULE_AUTHOR("Jeff Garzik");
 MODULE_DESCRIPTION("Library module for ATA devices");
 MODULE_LICENSE("GPL");
@@ -1978,28 +1982,40 @@ retry:
            goto err_out;
    }

-   if (!tried_spinup && (id[2] == 0x37c8 || id[2] == 0x738c)) {
+   /*
+    * My drives indicate with 0x738c that media is ready when PUIS
+    * is enabled, in conflict with the relevant standards.
+    * The compliant behavior therefore prevents spun-up and ready
+    * drives from being recognized on reboot.
+    * I had no choice but to remove "|| id[2] == 0x738c))".
+    */
+   if (!tried_spinup && (id[2] == 0x37c8)) {
        tried_spinup = 1;
        /*
         * Drive powered-up in standby mode, and requires a specific
         * SET_FEATURES spin-up subcommand before it will accept
         * anything other than the original IDENTIFY command.
         */
-       err_mask = ata_dev_set_feature(dev, SETFEATURES_SPINUP, 0);
-       if (err_mask && id[2] != 0x738c) {
-           rc = -EIO;
-           reason = "SPINUP failed";
-           goto err_out;
-       }
-       /*
-        * If the drive initially returned incomplete IDENTIFY info,
-        * we now must reissue the IDENTIFY command.
-        */
-       if (id[2] == 0x37c8)
+       if (spinup_control) {
+           err_mask = ata_dev_set_feature(dev, SETFEATURES_SPINUP, 0);
+           if (err_mask) {
+               rc = -EIO;
+               reason = "SPINUP failed";
+               goto err_out;
+           }
+           /*
+            * If the drive initially returned incomplete IDENTIFY info,
+            * we now must reissue the IDENTIFY command.
+            */
            goto retry;
+       } else {
+           dev->horkage |= ATA_HORKAGE_DISABLE;
+           ata_dev_notice(dev, "horkage modified (drive powered-up in standby)\n");
+       }
    }

-   if ((flags & ATA_READID_POSTRESET) &&
+   if (spinup_control && (flags & ATA_READID_POSTRESET) &&
        (class == ATA_DEV_ATA || class == ATA_DEV_ZAC)) {
        /*
         * The exact sequence expected by certain pre-ATA4 drives is:

我认为,这要感谢 az12shareart,他注册了 arch linux 论坛就是为了写这篇文章。

相关内容