如何告诉Linux内核完全忽略一块硬盘,就好像它根本没有连接上一样?

注意

向下滚动查看答案(它只有几点,但是是正确的)。该问题已通过一个补丁解决,将在3.12.7及以上版本的内核中发布;我希望它也能被移植到早期版本。

我的笔记本电脑是三星Chronos系列s 7。运行Ubuntu Gnome Remix 13.04,并使用了更新的Intel驱动程序。

我遇到了一个关于内部SSD硬盘(8G容量)的问题。它出现了COMRESET和输入/输出错误。我相当确信这个问题是硬件问题;不幸的是,我没有在笔记本电脑上安装Windows来检查是否是SSD配置或其他问题。

问题在于udev可以识别到该磁盘:

KERNEL[9.515930] add      /devices/pci0000:00/0000:00:1f.2/ata2/host1/target1:0:0/1:0:0:0/block/sdb (block)
ACTION=add
DEVNAME=sdb
DEVPATH=/devices/pci0000:00/0000:00:1f.2/ata2/host1/target1:0:0/1:0:0:0/block/sdb
DEVTYPE=disk
MAJOR=8
MINOR=16
SEQNUM=1785
SUBSYSTEM=block
UDEV_LOG=3

在那之后,它在很多检查中失败了,延迟了启动和关机,并且(我认为)使挂起变得不可能。
有没有办法告诉Linux完全忽略ata2链接上的任何内容?我尝试将这行代码添加到/etc/udev/rules.d/10-local.rules文件中。
SUBSYSTEMS=="pci"  DRIVERS=="ahci" KERNELS=="ata2" OPTIONS=="ignore_device"

但是它不起作用。
另一方面,如果有人知道如何在没有使用Windows的情况下重置SSD,如果它被留在“缓存”模式中...或者启动一个“实时”Windows来做同样的事情...
谢谢!
添加的数据:
完整的udevadm info -a -n /dev/sdb粘贴到http://paste.ubuntu.com/6186145/smartctl -i /dev/sdb -T permissive给出:
root@samsung-romano:/home/romano# smartctl -i /dev/sdb -T permissive
smartctl 5.43 2012-06-30 r3573 [x86_64-linux-3.8.0-31-generic] (local build)
Copyright (C) 2002-12 by Bruce Allen, http://smartmontools.sourceforge.net

Vendor:               /1:0:0:0
Product:              
User Capacity:        600,332,565,813,390,450 bytes [600 PB]
Logical block size:   774843950 bytes
>> Terminate command early due to bad response to IEC mode page

这显然是错误的。不过:
root@samsung-romano:/home/romano# fdisk -b 512 -C 970 -H 256 -S 63 /dev/sdb
fdisk: unable to read /dev/sdb: Input/output error

(来自http://ubuntuforums.org/showthread.php?t=1935699&p=11739579#post11739579的SSD数据)。
额外的想法:
这一切是否都是因为在安装Linux之前没有禁用Intel Smart Response Technology引起的副作用?如果是的话,我如何在不重新安装Windows的情况下检查它?或者这只是一个无望的尝试?(在BIOS中,SSD驱动器没有显示,并且没有关于Intel SRT的任何信息)。
关于标记为重复问题:
我改变了问题的标题;我不认为链接的问题回答了我的问题。我确信SSD正在出现故障。我想知道是否可能告诉Linux内核根本不去探测它。

您可能会在这个问题中找到答案: http://askubuntu.com/questions/325283/how-do-i-check-the-health-of-a-ssd - s3lph
2如果您想要隐藏的磁盘是“sdb”,请问您能否发布“udevadm info -a -n /dev/sdb”的完整输出? - Roman Raguet
我添加了所需的数据。我打开笔记本电脑试图亲自解决,但我觉得它好像焊在主板上了。而且smartctl给出了奇怪的结果,而fdisk只是显示I/O错误。 - Rmano
1这个问题与链接的问题完全不同,根本不是重复的。你能否取消将其标记为重复?我已经修改了标题以更好地传达问题。这个问题不是关于SSD检查,而是关于Linux上磁盘管理的一般问题。谢谢! - Rmano
1单纯拔掉硬盘有什么问题吗? - Braiam
1在Super User上有一个类似的问题:如何禁用内核对驱动程序的探测? - ændrük
3Braiam:SSD硬盘焊接在主板上。 - Rmano
æendrük: 明白了。完全是同样的问题。而且似乎没有解决办法...禁用SATA将会禁用所有我的硬盘。 - Rmano
6个回答

这里有两个解决方案:一个是快速应用,虽然只能部分解决问题;另一个是完整的解决方案,但需要您自己编译内核。
正确答案是内核补丁。
Robin H. Johnson为SATA内核驱动程序编写了一个补丁(在Unix/Linux堆栈交换站点上找到它),该补丁完全隐藏了驱动器。
更新1:该补丁现已上游(至少在3.12.7稳定内核中),请参阅git存储库。我已要求在Ubuntu Launchpad上进行回溯。
更新2:该补丁已包含在Ubuntu Trusty Thar 14.04的标准内核中;因此,现在只需要添加以下引导参数。
安装补丁后,添加
 libata.force=2.00:disable

将内核引导参数中的磁盘隐藏起来,以避免被Linux内核检测到。请仔细确认数字是否正确;可以通过搜索设备名称来帮助确定。
(0)samsung-romano:~% dmesg | grep iSSD
[    1.493279] ata2.00: ATA-8: SanDisk iSSD P4 8GB, SSD 9.14, max UDMA/133
[    1.494236] scsi 1:0:0:0: Direct-Access     ATA      SanDisk iSSD P4  SSD  PQ: 0 ANSI: 5

要添加内核参数(无论是临时还是永久),您可以查看此问答:如何添加内核引导参数?

解决方法

至少启用挂起-恢复的问题已经由Unix StackExchange用户Emmanuel在https://unix.stackexchange.com/a/103742/52205中解决。作为root用户,执行以下命令:

echo 1 > /sys/block/sdb/device/delete

暂停之前。

要使其永久生效,请在/etc/pm/sleep.d/中添加以下文件,并将其设置为可执行:

-rwxr-xr-x 1 root root 204 Dec  6 16:03 99_delete_sdb

有内容:

#!/bin/sh

# Delete the failing disk so that it will not block suspend

case "$1" in
    suspend|hibernate)
        if [ -d /sys/block/sdb ]; then
            echo 1 > /sys/block/sdb/device/delete       
        fi
        ;;
esac

...现在系统可以正确地暂停(和恢复)了。

1谢谢你提醒我关于/sys/block/*/device/delete的事情。 - Michael Shigorin
@kikuto --- 你提出的编辑似乎有些离题,但我添加了一个链接,告诉你如何添加内核引导参数。谢谢。 - Rmano
这对NVMe硬盘也适用吗? - Alan Franzoni
如果设备被视为(S)ATA设备,很可能是的;你可以在启动时检查它是否被列为ataX.YY。否则,很可能不是(我的电脑上没有这种类型的设备)。 - Rmano
正确的答案是将此补丁进行优化并提交给内核维护者。:) // 我觉得很奇怪的是,这不是一个内核初始化参数或者像其他所有东西一样在/sys中的开关。 - anon
@Evi1M4chine可能是这样,但考虑到在非常早期的引导过程中必须忽略磁盘,内核参数仍然是必需的(顺便说一下,该补丁自2014年以来就已经存在于内核中,我仍然在使用某人在Craig List上骗我购买的笔记本电脑...如果我不是Linux用户,它将和一块纸一样无用;-)) - Rmano

你可以尝试使用以下信息创建udev规则:(udevadm info -a -n /dev/sdb的输出)。

信息:

looking at parent device '/devices/pci0000:00/0000:00:1f.2/ata2/host1/target1:0:0/1:0:0:0':
    KERNELS=="1:0:0:0"
    SUBSYSTEMS=="scsi"
    DRIVERS=="sd"
    ATTRS{rev}=="SSD "
    ATTRS{type}=="0"
    ATTRS{scsi_level}=="6"
    ATTRS{model}=="SanDisk iSSD P4 "
    ATTRS{state}=="running"
    ATTRS{queue_type}=="none"
    ATTRS{iodone_cnt}=="0x309"
    ATTRS{iorequest_cnt}=="0x30a"
    ATTRS{queue_ramp_up_period}=="120000"
    ATTRS{timeout}=="30"
    ATTRS{evt_media_change}=="0"
    ATTRS{ioerr_cnt}=="0x1d6"
    ATTRS{queue_depth}=="1"
    ATTRS{vendor}=="ATA     "
    ATTRS{device_blocked}=="0"
    ATTRS{iocounterbits}=="32"

1) 创建udev规则。

  • sudo nano /etc/udev/rules.d/99-hide-ssd.rules

您可以尝试匹配"SUBSYSTEMS""DRIVERS"键,以及"ATTRS{rev}"ATTRS{model}属性,然后将"UDISKS"变量分配为忽略它。

99-hide-ssd.rules文件的内容应为:

SUBSYSTEMS=="scsi", DRIVERS=="sd", ATTRS{rev}=="SSD ", ATTRS{model}=="SanDisk iSSD P4 ", ENV{UDISKS_IGNORE}="1"

要保存nano中的更改...按下Ctrl+O,然后按下Enter,最后按下Ctrl+X

2) 最后使用以下命令刷新udev规则:

  • sudo udevadm trigger
注意:使用ENV{UDISKS_IGNORE}="1"将会忽略Ubuntu 12.10和13.04的磁盘。
对于Ubuntu 12.04,变量应为ENV{UDISKS_PRESENTATION_HIDE}="1"
希望这能帮到你。

尝试过了,启动时仍然检测到 sdb(并延迟启动)。我认为应该有一些内核行参数选项,但是我找不到任何相关的内容...唉。无论如何还是谢谢。 - Rmano
@Rmano... 如果你只尝试匹配内核键呢?规则将会是 KERNEL=="sdb", ENV{UDISKS_IGNORE}="1"... 用于检测设备是否在udev中被识别。 - Roman Raguet
我知道这是很久以前的事了,但这个问题仍然没有答案...... 没有任何建议起作用。不管怎样,还是非常感谢大家。 - Rmano

我为你写了一个内核补丁,实现了在启动时禁用单个磁盘的功能,这样你就不需要在udev中禁用它,也不需要在初始启动期间等待。

http://dev.gentoo.org/~robbat2/patches/3.13-libata-disable-disks-by-param.patch

应该很容易适用于许多内核(上面的那行是在2013-05-21/v3.10-rc1*添加的,但可以安全地手动应用而不需要那行)。

只有一个赞同对于一个为另一个人编写内核补丁解决问题的回答?佩服,加一。 - Binarus

https://serverfault.com/questions/112147/tell-ubuntu-to-ignore-dead-hard-drive-during-booting建议的部分如下:

以root身份,用您喜欢的文本编辑器打开/etc/udev/rules.d/60-persistent-storage.rules

往下几行,您可能会看到一行看起来像这样的内容:

跳过不适当的块设备规则

KERNEL=="ram*|loop*|fd*|nbd*|gnbd*|dm-|md", GOTO="persistent_storage_end" 在第二行中添加"sdb*",使其看起来像这样:

KERNEL=="ram*|loop*|fd*|nbd*|gnbd*|dm-|md|sdb*", GOTO="persistent_storage_end"

保存,重新启动,也许它能正常工作。如果不行,那么这是保修期后的问题吗?


试过了,没运气。还是有那个sdb驱动,还是阻止了挂起。曾经有一个sdb=ignore内核命令行选项...不幸的是,它已经过了保修期。 - Rmano
顺便说一句,我没有那个文件,所以我添加了它... - Rmano

如果您的其他磁盘没有使用AHCI,或者不是SSD,您可以删除它们的内核驱动程序。
要在当前会话中删除(直到下次重启),请运行:
sudo rmmod ahci

重新加载它,运行以下命令:
sudo modprobe ahci

如果你发现一切都顺利,你现在可以完全禁用它(下次启动时不加载)。打开文件 /etc/modprobe.d/blacklist.conf,然后添加以下行:

blacklist ahci 

要将SSD驱动程序列入黑名单,只需将ahci替换为sd

2这将使我的系统没有任何磁盘...主驱动器在ata1上,故障的SSD在ata2上。在BIOS中禁用AHCI模式会导致系统无法启动... - Rmano

据我所知,除了移除您的固态硬盘,没有其他办法可以删除这条消息。

很不幸,据我所知,SSD已焊接在主板上。只是一颗8G芯片。 - Rmano
在芯片上剪掉其中一个LED,最好找到+5V线并用X-Acto切断它。 - K7AAY
如果我只知道是哪个芯片,以及它在哪里。然后我担心这可能会引发更多的问题(未驱动的三态...)。 - Rmano