Solid state drive (简体中文)

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

本文介绍如何管理固态硬盘等基于闪存的存储设备。如果出于特定目的要对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]
警告: 在启用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(将在服务第一次启动时创建)的时间戳来判断上次运行的时间。因此,不必担心服务被过于频繁地调用(类似anacron)。

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

Continuous TRIM

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

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

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

要使用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命令,

为LVM启用TRIM

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

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

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

为dm-crypt启用TRIM

警告: discard选项允许discard请求通过加密的块设备传递。这不一定能[10]提升性能,而且有安全风险。详见:

对非/文件系统,可修改/etc/crypttab,在相应设备的options中加入discard选项。(见 Dm-crypt/System configuration#crypttab)。

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

提升性能

参见Improving performance#Storage devices

物理块大小

参见 Advanced Format#Solid state drives

清空SSD

TRIM只在删除文件时起作用,而在增量保存等替换操作上无能为力。因此,即使在支持TRIM的SSD上,写入性能也会随时间降低。你可能想将SSD存储单元恢复到出厂时的状态,来使其恢复出厂时的写入性能

要清除存储单元,依照SSD memory cell clearing中的步骤。

注意: 如果你想通过清除存储单元来清除数据,靠SSD控制器来执行该操作可能并不安全可靠。如果你不信任SSD制造商或担心固件中潜在的bug,参见Securely wipe disk#Flash memory

安全

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状态(未设置HDD密码),其frozen状态可防止恶意软件在运行时对设备设置密码。

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

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

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

从睡眠中唤醒时设置SSD为"frozen"状态

当从睡眠中唤醒时,SSD很可能失去"frozen"状态,这导致其可被ATA SECURE ERASE命令擦除。

要防止这一问题,可以在每次唤醒后运行一个脚本:

/usr/lib/systemd/system-sleep/ssd-freeze.sh
#!/bin/sh
if [ "$1" = 'post' ]; then
	sleep 1
	if hdparm --security-freeze /dev/disk/by-id/ata-name-of-disk; then
		logger "$0: SSD freeze command executed successfully"
	else
		logger "$0: SSD freeze command failed"
	fi	
fi

硬件加密

正如#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。

支持TRIM的外接SSD

一些USB转SATA芯片(如VL715、VL716等)以及在外接NVMe硬盘盒(如IB-1817M-C31[失效链接 2022-09-23 ⓘ]))中使用的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 。此时,你应该检查设备的"Logical Block Provisioning"中的"Vital Product Data"页是否显示了支持的unmapping data机制。你可以执行以下命令:

# sg_vpd -a /dev/sdX

查看有无类似下面的输出:

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

上例中,设备支持"UNMAP"命令。

此外,查看如下命令的输出:

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

如果输出为"full",则表明内核没有检测到该设备支持unmap data。 除了"full"外,内核的SCSI存储驱动目前接受以下provisioning_mode的值:

unmap
writesame_16
writesame_10
writesame_zero
disabled

对于上例,要使内核使用"unmap"模式,你可以向"provisioning_mode"中写入"unmap":

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

之后,你应该能立刻在对应设备上使用blkdiscard等工具,并在其文件系统上使用fstrim。

如果你想对于特定制造商的所有产品或特定产品,当通过USB其连接时,都能自动设置provisioning_mode,可配置udev

首先,找到对应设备的Vendor ID和Product ID:

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

然后,创建或修改相应的udev规则(本例中使用idVendor 152d和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

(也可以使用lsusb命令来查看idVendor/idProduct。)

固件更新

如果设备制造商支持,建议使用fwupd工具来更新固件。

ADATA

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

Crucial

Crucial 提供了以ISO镜像文件升级固件的选项。选择产品后,下载"Manual Boot File"可获取ISO镜像。

注意: 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软件的系统,Intel提供了一个基于Linux live系统的固件更新工具

此外,还可用使用Intel Memory and Storage (MAS) Toolintel-mas-cli-toolAUR)命令行工具在Linux下刷入固件。(其PDF用户指南

例如,要检查固件状态:

# 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提供Command Line Online Update Tool (CLOUT)。相关软件包可在AUR找到:ocz-ssd-utilityAURocztoolboxAURoczcloutAUR

Samsung

除了使用Magician软件外,也有其它方法升级固件(尽管Samsung认为这是”不受支持“的)。Magician软件可以创建包含固件更新的启动盘,然而Samsung不再为消费级SSD提供该软件。此外,Samsung提供的可引导的ISO镜像也能用来更新固件。还可以使用magician工具(samsung_magician-consumer-ssdAUR)。Magician只支持三星品牌的SSD,不支持Samsung为其它OEM(如联想)制造的SSD。

注意: 对于这些信息,Samsung提供得并不“显然”。它们似乎有4个不同的固件更新页面,每个都介绍了不同的更新方法。

如果你想通过在Linux下创建的Live USB来更新固件(而不是在Microsoft Windows下使用Samsung的Magician软件),参见[13]

在Linux下更新

此外,固件可在不使用USB启动盘的情况下直接更新。首先,从这里下载适用于对应SSD的最新固件(一个ISO镜像)。

注意: 若ISO镜像中没有下面提到的initrd镜像,见#较旧的SSD

从ISO镜像中解压Linux initrd镜像(将samsung_ssd_firmware替换为对应的ISO镜像文件名):

$ bsdtar xf samsung_ssd_firmware.iso initrd

解压root/fumagician/。该目录中包含固件更新文件:

$ bsdtar xf initrd root/fumagician

最后,以root权限运行root/fumagician/fumagician,确认成功更新固件后,重启计算机。

较旧的SSD

有些SSD固件ISO中包含FreeDOS镜像而不是Linux initrd镜像,故需要采取不同的更新方法。下表展示了这些SSD及固件的相对路径:

SSD型号 FreeDOS镜像路径 固件包路径
470, 830 BTDSK.IMG SSR/
840 isolinux/btdsk.img samsung/DSRD/
840 EVO (mSATA), Pro ISOLINUX/BTDSK.IMG

首先,从ISO镜像中解压FreeDOS镜像(将samsung_ssd_firmware替换为对应的ISO镜像文件名,freedos_image_path替换为FreeDOS镜像路径,下同):

$ bsdtar xf samsung_ssd_firmware.iso freedos_image_path

将FreeDOS镜像挂载到/mnt/

# mount freedos_image_path /mnt

利用Magician SSD management utility获取SSD对应的Disk Number

# magician --list

更新SSD固件(将firmware_package_path替换为对应的固件包路径):

# magician --disk Disk Number --firmware-update --fwpackage-path /mnt/firmware_package_path

最后,以root权限执行magician --list,检查输出中Firmware对应的固件版本是否成功更新,并重启计算机。

SanDisk

对于SanDisk SSD Toolkit不支持的操作系统,SanDisk制作了ISO镜像来进行固件更新。

你必须选择对应SSD型号容量的固件。烧录ISO镜像后,从创建的CD/DVD启动盘启动计算机即可(可能可以使用USB启动盘)。

此外,由于ISO镜像只包含了Linux内核及initrd,也可以将内核及initrd提取到/boot下,并用GRUBSyslinux启动来更新固件。

另见:

另见