固態硬盤

出自 Arch Linux 中文维基

本文介紹如何管理固態硬盤等基於閃存的存儲設備。如果出於特定目的要對SSD進行分區,請考慮針對閃存優化的文件系統。對於一般用途,您只需選擇喜好的文件系統並啟用#TRIM

使用[編輯 | 編輯原始碼]

TRIM[編輯 | 編輯原始碼]

在機械硬盤上,只需在文件系統層面處理文件的刪除即可[1]。但在固態硬盤上,每次寫操作都會對相應閃存單元產生一定磨損,因此主控會使用算法來將寫操作平衡到整塊閃存上,這被稱作耗損平均技術。在刪除文件後通知主控對應的存儲單元為可用狀態將有助於這個過程。在不使用NVMe DEALLOCATE, SAS UNMAPATA_TRIM命令的情況下,由於主控不知道被刪除的文件對應的空間已空閒,很快閃存上將沒有「空閒」空間。在執行寫入操作時,主控將需要反覆搬運數據以空出一個最小擦除單元並擦除該單元以寫入數據,導致寫入用時增加(詳見:寫入放大)。此文展示了SSD裝滿數據前後的速度變化。

注意: 只需使用Periodic TRIM或Continuous TRIM中的一個即可。Continuous TRIM不是最被Linux社區推薦的TRIM方式。例如,Ubuntu默認使用periodic TRIM[2], Debian不建議使用continuous TRIM continuous TRIM,Red Hat建議在可行的情況下使用periodic TRIM[3]

自 Linux 內核版本 3.8 開始,對 TRIM 的支持不斷被添加到不同的文件系統中。見下表:

文件系統 Continuous TRIM
(discard 選項)
Periodic TRIM
(fstrim)
參考與備註
Btrfs 從6.2版內核開始,默認啟用了異步discard。
exFAT 從5.13版內核開始支持fstrim[4]
ext3
ext4 "discard, nodiscard(*)" in [5]
F2FS
JFS [6]
NILFS2
NTFS ntfs3內核驅動僅支持continuous TRIM。
NTFS-3G僅支持periodic TRIM。
VFAT 從4.19版內核開始支持fstrim[7]
XFS [8]
警告: 在啟用TRIM功能前,請確保SSD支持TRIM。否則可能導致數據丟失!

要檢查TRIM支持,執行:

$ lsblk --discard

若DISC-GRAN (discard granularity)和DISC-MAX (discard max bytes)列上的數值不為零,則表示對應設備支持TRIM。

對於SATA SSD,可通過hdparm檢測TRIM支持:以root用戶執行hdparm -I /dev/sda | grep TRIMhdparm不支持NVMe SSD。

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[編輯 | 編輯原始碼]

除定期執行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,在/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請求通過加密的塊設備傳遞。這不一定能[9]提升性能,而且有安全風險。詳見:

對非/文件系統,可修改/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"命令給連接的SATA存儲設備。同樣,一些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"來查看該設置 (見 [10], [11])。

警告: 不要試圖用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,在引導加載程序配置中添加內核命令行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下更新SSD固件。可以在此處下載僅支持Windows的SSD ToolBox工具。也可從此處下載ADATA XPG來對SSD進行監控、TRIM、基準測試或更新固件。

警告: 不建議嘗試通過Wine來更新固件,Wine不是被設計來處理硬件接口操作的。使用Wine可能使固件更新不完整,導致SSD變磚。

Crucial[編輯 | 編輯原始碼]

Crucial 提供了以ISO鏡像文件升級固件的選項。選擇產品後,下載"Manual Boot File"可獲取ISO鏡像。

注意: Crucial提供的ISO鏡像可能不是hybrid格式。如果直接使用dd命令將鏡像複製到設備上,由於MBR不會被設置,將無法從該設備啟動。要解決這一問題,可安裝syslinux並執行isohybrid path/to/image.iso

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軟件),參見[12]

在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啟動來更新固件。

另見:

另見[編輯 | 編輯原始碼]