Solid state drive (简体中文)

From ArchWiki
翻译状态:本文是 Solid_State_Drives翻译。上次翻译日期:2021-01-30。如果英文版本有所更改,则您可以帮助同步翻译。

Tango-preferences-desktop-locale.png本文或本节需要翻译。要贡献翻译,请访问简体中文翻译团队Tango-preferences-desktop-locale.png

附注: "External SSD with TRIM support"节未翻译(在 Talk:Solid state drive (简体中文)# 中讨论)

本文介绍专题操作固态硬盘和其他闪存的存储设备。如果要出于特定目的对SSD进行分区,请考虑针对闪存优化的文件系统列表。对于一般用途,您只需选择喜好的文件系统

使用

TRIM

绝大多数SSD支持 ATA_TRIM 命令 以保持性能并降低损耗。本文展示了SSD装满数据前后的速度变化。

自 Linux 内核版本 3.8 开始,对 TRIM 的支持不断被添加到不同的文件系统中。见下表:

文件系统 Continuous TRIM
(discard 选项)
Periodic TRIM
(fstrim)
参考与备注
Btrfs
exFAT 从5.13版内核开始支持fstrim[1]
ext3
ext4 "discard, nodiscard(*)" in [2]
F2FS
JFS [3]
NILFS2
NTFS-3G 从2015.3.14版本开始, [4]
VFAT 从4.19版内核开始支持fstrim[5]
XFS [6][失效链接 2021-11-19 ⓘ]
警告: 在启用TRIM功能前,请确保你的SSD支持TRIM。否则可能导致数据丢失!

检验TRIM支持:

$ lsblk --discard

查看DISC-GRAN (discard granularity)和DISC-MAX (discard max bytes)列。非零数值表示对应设备支持TRIM。

或者,安装hdparm 包并执行:

# hdparm -I /dev/sda | grep TRIM
        *    Data Set Management TRIM supported (limit 1 block)
注意: 不同的规范定义了不同的TRIM支持类型。因此,对于不同设备,以上输出可能不同。参见Wikipedia:Trim (computing)#ATA

Periodic TRIM

util-linux包提供了fstrim.servicefstrim.timer两个Systemd unit文件。启用计时器(fstrim.timer)会每周激活服务来在所有已挂载的支持discard操作的文件系统上执行fstrim(8)

该计时器使用/var/lib/systemd/timers/stamp-fstrim.timer(将在服务第一次启动时创建)的时间戳来判断上次运行的时间。因此,不必担心服务被太过频繁地调用。

该unit的状态与活动可通过journalctl查看。若要修改运行的周期或执行的指令,可编辑unit文件。

Continuous TRIM

注意: 如果已定期运行fstrim,就不必再启用Continuous TRIM。只需在periodic TRIM和Continuous TRIM中选择一个即可。

除定期(若使用fstrim.timer则默认为每周)执行TRIM指令外,也可每次在文件被删除后就立即执行TRIM指令(这被称为Continuous TRIM)。

警告:SATA 3.1前,所有TRIM指令都是非队列(non-queued)的,使用Continuous TRIM将造成频繁的卡顿,此时应使用#Periodic TRIM。此外,某些设备也会造成类似问题。因为在这些设备上,队列的TRIM指令会造成严重的数据损坏。在这种情况下,系统可能会强制发送非队列的TRIM指令。参见Linux源码中的ata_device_blacklist。详见Wikipedia:Trim_(computing)#Disadvantages
注意: Continuous TRIM不是最被Linux社区推荐的TRIM方式。例如,Ubuntu默认使用periodic TRIM[7], Debian不建议使用continuous TRIM [8],Red Hat建议在可行的情况下使用periodic TRIM而非continuous TRIM。[9][失效链接 2020-04-03 ⓘ](存档于[10]

要使用Continuous TRIM,在/etc/fstab中对应挂载点指定discard选项:

/dev/sda1  /           ext4  defaults,discard   0  1
注意: 不能在/etc/fstab中为XFS / 分区指定discard挂载选项选项。根据此帖子,必须使用rootflags=discard 内核参数

对于Ext4文件系统,也可用tune2fsdiscard设置为一个默认挂载选项

# tune2fs -o discard /dev/sdXY

使用此方式代替/etc/fstab中的条目对于可移动驱动器尤其有用。这样,在其他计算机上挂载分区时,就不需要每次修改/etc/fstab了。

注意: 此默认挂载选项不会在/proc/mounts中列出。

Trim整个设备

当在全新安装或想卖掉你的SSD时,你可能想Trim整个设备。可以使用blkdiscard命令,这将立即丢弃设备上所有的block。

警告: 设备上的所有数据都将丢失!
# blkdiscard /dev/sdX

为LVM启用TRIM

由LVM逻辑卷上的文件系统产生的TRIM请求将直达对应物理卷。因此,无需额外的配置。

LVM操作(lvremove, lvreduce等)默认不会产生TRIM请求,以便使用vgcfgrestore(8)恢复之前的卷组(VG)设定。/etc/lvm/lvm.conf中的issue_discards设置决定是否在逻辑卷不再占用卷组空间时将discard发送给底层物理卷。

注意: 在修改issue_discards设置前,请仔细阅读/etc/lvm/lvm.conf中的注释。issue_discards设置不会影响由逻辑卷文件系统产生的TRIM请求(如在文件系统内删除文件)的传递,也不会影响thin pool中的空间管理。
警告: 启用issue_discards后,将不能再使用vgcfgrestore恢复卷组(VG)元数据。一旦执行LVM命令,将无法撤销。

为dm-crypt启用TRIM

警告: discard选项允许discard请求通过加密的块设备传递。这可能并不会[11] [12]提升SSD性能,而且有安全风险。详见dm-crypt/Specialties#Discard/TRIM support for solid state drives (SSD)

对非/文件系统,为SSD上的块设备配置 /etc/crypttab 来把 discard 加入到选项列表中 (见 Dm-crypt/System configuration#crypttab)。

对于/文件系统,遵循 Dm-crypt/TRIM support for SSD 的指示来将正确的内核参数加入到bootloader配置中。

提升性能

参照Improving performance#Storage devices中的提示来提高SSD性能。

物理块大小

大多数SSD将其扇区大小报告为512字节(与HDD兼容),但实际上具有更大的块大小 -- 通常是4kB、8kB甚至更大。由于被认为扇区大小为512字节,文件系统不能自动优化到物理块大小。为防止性能损失,应在创建文化系统时手动指定扇区大小。

作为手动指定扇区大小的替代,某些SSD可在格式化时更改块大小,因此其可能会汇报一个更接近其真实数值的块大小。

NVMe

使用Identify Namespace命令来查看指定的NVMe设备是否支持该特性。

# nvme id-ns /dev/nvme0n1
nlbaf   : 0
[...]
lbaf  0 : ms:0   lbads:9  rp:0 (in use)

nlbaf是支持的LBA格式数减1,所以本例中只支持1种格式。支持的格式列举在其后。lbaf 0表示支持LBA format #0。其lbads(LBA data size)为9,表示块大小为29=512字节。如果设备支持4kB块大小,lbads将会是12。rp(相对性能)表示那种LBA格式具有最好的性能,0表示当前格式具有最好的性能。ms(可能)是每个块中额外的元数据大小(Bytes),在Linux下,对其的支持并不完善,所以最好选择该值为0的格式。

要修改块大小,使用nvme format命令并通过--lbaf参数指定对应的lbaf值。

SATA

对于SATA设备,必须使用制造商提供的工具。 不是所有的SATA设备都支持修改块大小。

安全

Hdparm 显示 "frozen" 状态

一些主板BIOS在初始化时发送了"security freeze"命令给连接上的存储设备。同样,一些SSD(和HDD) BIOS在工厂已设置为"security freeze"。二者都会导致设备的密码安全设置设为 frozen,如下面的输出:

:~# hdparm -I /dev/sda
Security: 
 	Master password revision code = 65534
 		supported
 	not	enabled
 	not	locked
 		frozen
 	not	expired: security count
 		supported: enhanced erase
 	4min for SECURITY ERASE UNIT. 2min for ENHANCED SECURITY ERASE UNIT.

如格式化设备或安装新系统之类的操作不受"security freeze"影响。

上面的输出显示了设备在启动时not locked,而frozen状态保护设备免于间谍软件侵害。它们试图在运行时设置密码来达到目的。

如果你想为"frozen"的设备设置密码,则必须要主板BIOS支持才可。许多笔记本都支持,这是因为这是 硬件加密 所必需的,但并非台式机/服务器主板所必需。例如,对于 Intel DH67CL/BL 主板,必须用跳线设置为"maintenance mode"来查看设置 (见 [13], [14])。

警告: 不要试图用hdparm来改变上述的lock安全设置,除非你十分清楚自己在干什么。

如果你想擦除SSD,见 Securely wipe disk#hdparm 以及 下文

SSD存储单元的清除

有时用户希望通过重置SSD单元到刚安装时的纯净状态以使其恢复到 出厂时的写入性能。即使是原生支持TRIM的SSD,其写入性能也会随时间变差。TRIM只在文件删除时起作用,而不是如增量保存一样的替代保障措施。

重置按wiki文章SSD memory cell clearing指示,三步之内即可轻松完成。如果重置的原因是为了擦除数据,你可能不想依靠SSD bios来安全执行。更多信息与例子见Securely wipe disk#Flash memory

硬件加密

正如#Hdparm 显示 "frozen" 状态中提到的,在BIOS中为存储设备(SSD/HDD)设置密码可能在支持的设备上启动硬件加密。如果设备同时符合OPAL标准,硬件加密还可能在BIOS没有设置密码的功能上实现,见Self-encrypting drives

故障排除

你遇到的问题可能是由于SSD固件而不是Linux产生的。在尝试排除故障前,请检查以下固件是否有更新:

即使是固件的bug,也可能在不更新固件的情况下避免。若没有固件更新可用,或你不想进行固件更新,以下内容可能有所帮助。

处理NCQ错误

部分SSD和SATA芯片组并不在Linux的原生命令队列(NCQ)下正常工作。dmesg错误提示看起来像这样:

[ 9.115544] ata9: exception Emask 0x0 SAct 0xf SErr 0x0 action 0x10 frozen
[ 9.115550] ata9.00: failed command: READ FPDMA QUEUED
[ 9.115556] ata9.00: cmd 60/04:00:d4:82:85/00:00:1f:00:00/40 tag 0 ncq 2048 in
[ 9.115557] res 40/00:18:d3:82:85/00:00:1f:00:00/40 Emask 0x4 (timeout)

要在系统启动时禁用NCQ,在bootloader配置中添加内核命令行libata.force=noncq。要仅为disk0 port9关闭NCQ,使用:libata.force=9.00:noncq

或者,可通过sysfs在不重启的情况下在指定设备上关闭NCQ:

# echo 1 > /sys/block/sdX/device/queue_depth

如果问题仍未得到解决或导致了其他问题,提交一个bug

处理与SATA电源管理有关的错误

某些SSD(如Transcend MTS400)在SATA Active Link Power Management(ALPM)启用时会出现错误。 ALPM默认关闭,并被节能程序(如TLP, Laptop Mode Tools)启用。

如果在使用这些节能程序时遇到SATA相关错误,应将使用电池时与充电时的电源配置都设为max_performance来关闭ALPM。

External SSD with TRIM support

Tango-edit-clear.pngThis article or section needs language, wiki syntax or style improvements. See Help:Style for reference.Tango-edit-clear.png

Reason: Several style and formatting problems, especially too many explicit commands - see Help:Style#File editing requests. (Discuss in Talk:Solid state drive (简体中文))

一些USB转SATA芯片(如VL715、VL716等)以及在 IB-1817M-C31[失效链接 2021-11-19 ⓘ] 之类外接NVMe硬盘盒中使用的USB转PCIe芯片(如 智微(JMicron) JMS583 )支持类TRIM命令,可通过 USB Attached SCSI 驱动程序(在Linux下称为"uas")发送。

然而内核可能不会自动检测到这一功能,从而也不会使用它。假设需要的块设备为/dev/sdX,可以用以下命令确定是不是这种情况

# sg_readcap -l /dev/sdX

如果输出中有一行写着“Logical block provisioning: lbpme=0”,则由于没有设置LBPME位,内核认为该设备不支持Logical Block Provisioning Management

If this is the case, then you should next find out whether the "Vital Product Data" (VPD) page on "Logical Block Provisioning" of your device tells of supported mechanisms for unmapping data. You can do this using the command:

# sg_vpd -a /dev/sdX

Look for lines in the output that look like this:

Unmap command supported (LBPU): 1
Write same (16) with unmap bit supported (LBPWS): 0
Write same (10) with unmap bit supported (LBPWS10): 0

This example would tell you the device supports the "UNMAP" command.

Have a look at the output of

$ cat /sys/block/sdX/device/scsi_disk/*/provisioning_mode

If the kernel did not detect the capability of your device to unmap data, then this will likely return "full". Apart from "full", the kernel SCSI storage driver currently knows the following values for provisioning_mode:

unmap
writesame_16
writesame_10
writesame_zero
disabled

For the example above, you could now write "unmap" to "provisioning_mode" to ask the kernel to use that:

# echo "unmap" >/sys/block/sdX/device/scsi_disk/*/provisioning_mode

This should immediately enable you to use tools like "blkdiscard" on /dev/sdX or "fstrim" on filesystems mounted on /dev/sdX.

If you want to enable a "provisioning_mode" automatically when an external device of a certain vendor/product is attached, this can be automated via the "udev" mechanism. First find the USB Vendor and Product IDs:

$ cat /sys/block/sdX/../../../../../../idVendor
$ cat /sys/block/sdX/../../../../../../idProduct

Then create or append to a udev rule file (example here using idVendor 152d and idProduct 0583):

# echo 'ACTION=="add|change", ATTRS{idVendor}=="152d", ATTRS{idProduct}=="0583", SUBSYSTEM=="scsi_disk", ATTR{provisioning_mode}="unmap"' >>/etc/udev/rules.d/10-uas-discard.rules

(You can also use the lsusb command to look for the relevant idVendor/idProduct.)

固件升级

ADATA

ADATA 在其支持页面上提供了Linux (i686)版的工具。在选择型号之后会出现到最新固件的链接。最新的Linux上的升级工具打包有固件,并必须以root权限运行。必须首先给二进制文件设置合适的权限。

Crucial

Crucial 提供了以ISO镜像文件升级固件的选项。镜像可以在选择产品和下载"Manual Boot File"之后找到。

注意: Crucial提供的ISO镜像可能不是hybrid格式。如果直接使用dd命令将镜像复制到设备上,由于MBR不会被设置,将无法从该设备启动。

M4 Crucial model用户可通过smartctl检查是否有需要的固件更新。

$ smartctl --all /dev/sdX
==> WARNING: This drive may hang after 5184 hours of power-on time:
https://www.tomshardware.com/news/Crucial-m4-Firmware-BSOD,14544.html
See the following web page for firmware updates:
https://www.crucial.com/usa/en/support-ssd

建议看见这个警告的用户备份所有重要数据并立即升级。参见该指引来使用ISO镜像和grub来更新Crucial MX100的固件。

Intel

对于无法使用Windows版本Intel® Solid-State Drive Toolbox[失效链接 2021-05-17 ⓘ]软件的系统,Intel提供了一个基于Linux live系统的固件更新工具

此外,还可用使用Intel Memory and Storage (MAS) Toolintel-mas-cli-toolAUR)命令行工具来在Linux下刷入固件。其PDF用户指南[失效链接 2021-11-19 ⓘ]

一个检查固件状态的例子:

# intelmas show -intelssd 0
DevicePath : /dev/nvme0n1
DeviceStatus : Healthy
Firmware : 002C
FirmwareUpdateAvailable : The selected Intel SSD contains current firmware as of this tool release.

若有多个SSD,请将-intelssd 0修改为对应的值(1对应第二块SSD,以此类推)。

如果有可用的更新,可通过intelmas load -intelssd 0来应用。PDF用户指南建议进行应用操作后重启并再进行一次。所有设备的最新固件都作为MAS工具的一部分发布,无需单独下载。

Kingston

适用于基于Sandforce设备的KUF工具可从kingston_fw_updaterAUR获取。

Mushkin

不怎么出名的 Mushkin 牌固态硬盘也使用 Sandforce 控制器,提供了Linux版的升级工具 (和 Kingston 的几乎一样)。

OCZ

OCZ 在论坛上提供了Linux (i686 and x86_64) 版的升级工具。

Samsung

Samsung 注意到使用他们的 Magician Software 是"不支持的",但是是可能的。显然 Magician Software 可以把USB做成以升级固件启动。最简单的方式是使用他们提供的用于升级固件的可启动的ISO镜像。可从这里获取。

注意: Samsung 根本不明确提供这些。他们似乎有四个固件升级页面,每个页面要求做不同的事情。

用户更喜欢从USB的live Linux系统上升级固件(而不是在Microsoft Windows下用三星的 "Magician" 软件)。参见这里

在Linux下更新

此外,固件可在不使用USB启动盘的情况下直接更新。首先,从这里下载适用于Windows的最新固件(一个磁盘镜像,以Samsung_SSD_840_EVO_EXT0DB6Q.iso为例)。

设置磁盘镜像:

$ udisksctl loop-setup -r -f Samsung_SSD_840_EVO_EXT0DB6Q.iso

这会将ISO映射到一个loop设备,假设为/dev/loop0。执行:

$ udisksctl mount -b /dev/loop0

获取需要镜像中需要的内容:

$ mkdir Samsung_SSD_840_EVO_EXT0DB6Q
$ cp -r /run/media/$USER/CDROM/isolinux/ Samsung_SSD_840_EVO_EXT0DB6Q

卸载镜像:

$ udisksctl unmount -b /dev/loop0
$ cd Samsung_SSD_840_EVO_EXT0DB6Q/isolinux

固件包含在一个FreeDOS镜像中,用上文的方法将其挂载:

$ udisksctl loop-setup -r -f btdsk.img
$ udisksctl mount -b /dev/loop1
$ cp -r /run/media/$USER/C04D-1342/ Samsung_SSD_840_EVO_EXT0DB6Q
$ cd Samsung_SSD_840_EVO_EXT0DB6Q/C04D-1342/samsung

使用magician获取目标SSD的编号:

# magician -L

假设编号为0,执行:

# magician --disk 0 -F -p DSRD

确认固件已被更新:

# magician -L

最后,重启计算机。

SanDisk

SanDisk 制作ISO固件镜像来允许用户在 SanDisk SSD 工具包不支持的系统上升级。必须找到正确的SSD 型号以及它的容量(例如 60GB, 或者 256GB)。烧制合适的ISO固件镜像之后,只需重启电脑启动到新创立的CD/DVD启动盘(也可以是USB)。

ISO镜像必须只包含一个linux内核和一个initrd.解压到 /boot 分区并用 GRUB 或者 Syslinux 启动它来升级。

目前我找不到列出固件升级的单独页面(恕我直言网站简直一团糟),但这里有一些相关链接:

SanDisk Extreme SSD Firmware Release notes and Manual Firmware update version R211

SanDisk Ultra SSD Firmware release notes and Manual Firmware update version 365A13F0

另见