固態硬碟 - Arch Linux 中文维基

跳至內容

# 固態硬碟

出自 Arch Linux 中文维基
翻譯狀態：

- 本文（或部分內容）譯自 Solid_State_Drives，最近一次同步於 2025-02-05，若英文版本有所更改，則您可以幫助同步與翻譯更改的內容。
- 您可以在 ArchWiki 的對應頁面找到本文翻譯的原始修訂歷史。
- 本文可能與英文原文存在出入。

相關文章

- 固態硬碟/NVMe
- 固態硬碟/存儲單元擦除
- 基準測試
- 性能優化#存儲設備

本文介紹如何管理固態硬碟（SSD）等基於快閃記憶體的存儲設備。

如果要針對特定目的對 SSD 進行分區，請參考針對快閃記憶體優化的文件系統清單。

對於一般用途，您只需選擇喜好的文件系統並啟用 #TRIM。

## 使用

### TRIM

在機械硬碟上，刪除操作是在文件系統層級上處理的[1]，而 SSD 會向硬碟主控通知特定區域的空間可以被再次使用。由於每次寫入操作都會對快閃記憶體單元一定磨損，因此主控會使用算法來將寫操作平衡到快閃記憶體的所有單元上，這被稱作耗損平均技術。在不使用 NVMe DEALLOCATE，SAS UNMAP 或 ATA_TRIM 命令（多數 SSD 都支持）的情況下，如果沒有空餘的存儲塊，主控就需要反覆搬運數據以空出一個最小擦除單元，並擦除該單元以寫入數據，導致寫入耗時增加（詳見：寫入放大）。關於 SSD 空間占滿前後的性能對比可參考 TechSpot 的評測。

注意：如果要使用 TRIM，只能在定期 TRIM 和持續性 TRIM 間二選一。Linux 社區認為持續性 TRIM 不是首選的 TRIM 方法，例如 Ubuntu 就默認使用定期 TRIM [2]，Debian 也不建議使用持續性 TRIM，紅帽建議儘可能選擇使用定期 TRIM [3]。

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

文件系統 | 持續性 TRIM （`discard` 選項） | 定期 TRIM （fstrim） | 參考與備註
--- | --- | --- | ---
Bcachefs | 是 | 否 |
Btrfs | 是 | 是 | 從 6.2 內核版本開始默認啟用異步 discard
exFAT | 是 | 是 | 從 5.13 內核版本開始支持 fstrim [4]
ext3 | 是 | 是 |
ext4 | 是 | 是 | 「discard, nodiscard(*)」 [5]
F2FS | 是 | 是 |
JFS | 是 | 是 | [6]
NILFS2 | 是 | 是 |
NTFS | 是 | 否 | ntfs3 內核驅動僅支持持續性 TRIM
否 | 是 | NTFS-3G 驅動僅支持定期 TRIM
VFAT | 是 | 是 | 從 4.19 內核版本開始支持 fstrim [7]
XFS | 是 | 是 | [8]
Swap | 是 | 否 | 理論上不是個「文件系統」，但也適用於 TRIM。「once」 選項在啟動時提供了定期 TRIM 的功能，具體請參考 swapon(8)

警告：在啟用 TRIM 功能前，請確保 SSD 支持 TRIM，否則可能導致數據丟失！

要檢查 TRIM 支持，執行：

    $ lsblk --discard

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

對於 SATA SSD，可通過 hdparm包 檢測 TRIM 支持：以根用戶執行 `hdparm -I /dev/sda | grep TRIM`。注意：`hdparm` 不支持 NVMe SSD。

#### 定期 TRIM

util-linux包 提供了 `fstrim.service` 和 `fstrim.timer` 兩個 systemd 單元文件。啟用 `fstrim.timer` 計時器會在每周激活服務，在所有已掛載的支持 discard 操作的文件系統上執行 fstrim(8)。

該計時器使用 `/var/lib/systemd/timers/stamp-fstrim.timer`（將在服務第一次啟動時創建）的時間戳來判斷上次運行的時間。因此，不必擔心服務被過於頻繁地調用（類似 anacron）。

單元的狀態與活動記錄可通過 journalctl 查看。若要修改運行的周期或執行的指令，可編輯單元文件。

#### 持續性 TRIM

除定期執行 TRIM 指令外（若使用 `fstrim.timer` 則默認為每周一次），也可每次在文件被刪除後就立即執行 TRIM 指令（這被稱為持續性 TRIM）。

警告：在 SATA 3.1 前，所有 TRIM 指令都是非隊列化的，因此使用持續性 TRIM 將造成系統頻繁卡頓，這種情況下應使用 #定期 TRIM。另外，某些設備（具體請參考 Linux 源碼中的 `__ata_dev_quirks` 內帶有 `ATA_QUIRK_NO_NCQ_TRIM` 的項）使用隊列化 TRIM 命令會造成嚴重的數據損壞，因此系統會對這些設備強制發送非隊列化的 TRIM 命令，具體請參考 Wikipedia:Trim_(computing)#Disadvantages。

要使用持續性 TRIM，在 `/etc/fstab` 中對應掛載點指定 `discard` 選項：

    /dev/sda1  /           ext4  defaults,discard   0  1

注意：不能在 `/etc/fstab` 中為 XFS `/` 分區指定 discard 掛載選項。根據此帖子，必須使用 `rootflags=discard` 內核參數。

對於Ext4文件系統，也可用 tune2fs 將 `discard` 設置為一個默認掛載選項：

    # tune2fs -o discard /dev/sdXY

對於可行動裝置，由於配置後的分區在其它設備上也會使用默認掛載選項，使用此方式而不是在 `/etc/fstab` 中新增條目尤其有用。這樣，在其他計算機上掛載分區時，就不需要每次修改 `/etc/fstab` 了。

注意：此默認掛載選項不會在 `/proc/mounts` 中列出。

#### Trim 整個設備

當在全新安裝或想賣掉你的 SSD 時，你可能想 Trim 整個設備，這時候可以使用 blkdiscard 命令。

#### LVM

由 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

警告：dm-crypt 支持將 discard 請求傳遞到底層塊設備上。這不一定能提升 SSD 的性能[9]，而且還有安全風險，因此默認不被啟用。

為 LUKS 和普通 dm-crypt 設備啟用 discard 的步驟請參考 dm-crypt/特殊應用#固態硬碟的Discard/TRIM支持。

#### swap

可以通過將 `discard` 選項添加到 fstab 中的 swap 設備條目或調用 `swapon` 時傳遞 `--discard` 選項為 swap 啟用 discard。

在使用 Systemd#GPT分區自動掛載時，discard 不會被自動應用到 swap 分區。

See swapon(8) for discussion on when swap is discarded: `discard=once` or `discard=pages`. If `discard` is specified without a specific mode, the default is to enable both.

警告：對於使用 mdadm 的 RAID 配置，為 swapon 啟用 discard 會導致系統在啟動和運行時鎖死。

### 提升性能

參見性能優化#存儲設備。

#### 清空 SSD

有時用戶可能會想將 SSD 的存儲單元重置回出廠狀態，從而恢復到出廠時的寫入性能。由於 TRIM 只對文件刪除有用，而對替換操作（如增量保存）無能為力，因此就算 SSD 帶有原生 TRIM 支持，其寫入性能還是會隨時間逐漸下降。

無論是 SATA 還是 NVMe SSD，都可以參考固態硬碟/存儲單元擦除中的對應步驟進行重置。

注意：如果你想通過清除存儲單元來清除數據，靠 SSD 控制器來執行該操作可能並不安全可靠。如果你不信任 SSD 製造商或擔心固件中潛在的 bug，可以參考 安全地擦除磁碟#快閃記憶體 中的信息和範例進行手動擦除。

### 安全

#### 凍結（Frozen）模式

有些主板的固件會在初始化時向 SATA 設備發送 ATA SECURITY FREEZE LOCK 命令，將硬碟設為凍結模式（即切換到 SEC2 狀態，禁用安全、非鎖定並凍結）。同樣，有些 SSD 和 HDD 在出廠時也會設成該狀態。可以通過 hdparm 和 smartctl 的輸出確認該現象：

    # 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.

    # smartctl -g security /dev/sda

    ATA Security is:  Disabled, frozen [SEC2]

格式化或安裝系統等操作不受凍結模式的影響。

上面的 hdparm 輸出顯示設備在啟動時未被 HDD 密碼鎖定，frozen 凍結狀態可防止惡意軟體在運行時對設備設置密碼進行鎖定。

如果你想手動為「凍結」的設備設置密碼，需要主板 BIOS 支持該功能的。由於硬體加密的需要，很多筆記本都支持該功能，但台式機/伺服器主板上則不然。以 Intel DH67CL/BL 主板為例，需要通過板上跳線將主板設為「維護模式」才能訪問該設置。[10]

警告：除非你十分清楚自己在幹什麼，否則不要試圖用 hdparm 來改變上述的 lock 安全設置。

如果你想擦除 SSD，請參考安全地擦除磁碟#hdparm 和 /存儲單元擦除。

##### 從睡眠中喚醒時設置 SATA SSD 為凍結模式

當從 S3 睡眠狀態喚醒時，SATA SSD 很可能會回到 SEC1 狀態（禁用安全、非鎖定、非凍結），導致其有可能受 /存儲單元擦除中描述的 ATA SECURITY ERASE UNIT 命令攻擊。

要防止這一問題，可以在每次喚醒後運行一個腳本：

    /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

如果系統有多個存儲設備和/或移動 USB 盤，可以通過 Hdparm#使用 udev 規則使配置持久化為所有硬碟（包括機械硬碟）指定 `--security-freeze`。

#### 硬體加密

正如#凍結（Frozen）模式中提到的，在設備支持的情況下，在 BIOS 中為存儲設備（SSD/HDD）設置密碼可能同時會啟用硬體加密。如果設備同時符合 OPAL 標準，即使 BIOS 沒有設置密碼的功能，硬體加密也可能啟動，具體請參考 Self-encrypting drives。

## 故障排除

你遇到的問題可能是由於 SSD 固件而不是 Linux 產生的。在嘗試排除故障前，請檢查固件是否有更新：

- SSD 的固件
- 主板的 BIOS/UEFI 固件

即使是固件的 bug，也可能在不更新固件的情況下避免。若沒有固件更新可用，或你不想進行固件更新，以下內容可能有所幫助。

### 處理 NCQ 錯誤

部分 SSD 和 SATA 晶片組在 Linux 的原生命令隊列（NCQ）下不能正常工作。通過 journal 可看到如下錯誤信息:

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

要在系統啟動時禁用 NCQ，需要在引導加載程序配置的內核命令行中添加 `libata.force=noncq`。例如，要僅為硬碟 0 埠 9 禁用 NCQ，可以使用：`libata.force=9.00:noncq`

或者，可通過 sysfs 在不重啟的情況下為指定設備禁用 NCQ：

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

如果更新固件並完成操作後問題仍未解決或導致了其他問題，請提交 bug 報告。

### 處理與 SATA 電源管理有關的錯誤

某些 SSD（如 Transcend MTS400 或 Crucial M550）搭配特定 SATA 控制器時，在 ALPM 啟用時會出現故障。

Linux 從 4.16 版本開始默認啟用，也可能會被節能守護進程（例如 TLP 和 Laptop Mode Tools）啟用。更多信息請參考電源管理#SATA 活動鏈路電源管理。

### 支持 TRIM 的外接 SSD

本文或本章節的語言、語法或風格需要改進。參考：幫助:風格

原因：Several style and formatting problems, especially too many explicit commands - see Help:Style#File editing requests.（在Talk:固態硬碟討論）

有多個 USB 轉 SATA 橋接晶片（如 VL715，VL716 等）及 USB 轉 PCIe 橋接晶片（如 IB-1817M-C31 外置 NVMe 硬碟盒使用的 JMicron JMS583）支持類似 TRIM 的命令，這些命令可通過 USB Attached SCSI 驅動程序（在 Linux 下稱為"uas"）發送。

然而內核可能不會自動檢測到並啟用這一功能。 假設有問題的設備為 /dev/sdX，可以通過 sg3_utils包 使用以下命令確定是否為這種情況：

    # sg_readcap -l /dev/sdX

如果輸出中有一行寫著「Logical block provisioning: lbpme=0」，就意味著由於沒有設置 LBPME 位，內核認為該設備不支持「Logical Block Provisioning Management」。

在這種情況下，就需要找出設備上的「Logical Block Provisioning」中的「Vital Product Data」（VPD）頁是否說明了支持的解除數據映射機制。可以使用該命令進行查看：

    # 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」，則表明內核沒有檢測到該設備有能力解除數據映射。 除了「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

現在就可以在 /dev/sdX 上使用 blkdiscard 等工具，或是對 /dev/sdX 上的文件系統上使用 fstrim。

如果想在特定廠商或產品設備連接時自動啟用一個「provisioning_mode」，可以使用 udev。首先找到 USB Vendor 和 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 工具來更新固件。

檢查當前固件版本：

    # smartctl -i /dev/ssd_device

### 威剛（ADATA）

威剛不支持在 Linux 下更新 SSD 固件。可以在支持頁下載僅支持 Windows 的 SSD ToolBox 工具，也可從支持頁下載 ADATA XPG 來對 SSD 進行監控、TRIM、基準測試或更新固件。

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

### 英睿達（Crucial）

英睿達提供了以 ISO 鏡像文件升級固件的選項。在 SSD 支持頁選擇產品後，下載「Manual Boot File」可獲取 ISO 鏡像。

注意：英睿達提供的 ISO 鏡像似乎不是 hybrid 格式。如果直接使用 `dd` 命令將鏡像複製到設備上，由於沒有配置 MBR，將導致無法從該設備啟動。要解決這一問題，可安裝 syslinux包 並執行 `isohybrid path/to/image.iso`。

Crucial M4 用戶可通 過`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 軟體的系統，英特爾提供了一個基於 Linux live 系統的固件更新工具。

此外，還可用使用 Intel Memory and Storage (MAS) Tool（intel-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.

如果只有一個 Intel SSD，可以省略 `-intelssd 0`；如果要指定第二塊 SSD，則修改為 `-intelssd 1`，依此類推。

如果有可用的更新，可通過 `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-utilityAUR、ocztoolboxAUR、oczcloutAUR。

### 三星（Samsung）

除了使用 Magician 軟體外，也有其它方法升級固件（儘管三星認為這是「不受支持」的）。Magician 軟體可以創建包含固件更新的啟動盤，然而三星不再為消費級 SSD 提供該軟體。此外，三星提供的可引導 ISO 鏡像也能用來更新固件。另外一種方法是使用 magician 工具（samsung_magician-consumer-ssdAUR）。Magician 只支持三星品牌的 SSD，不支持三星為其它 OEM（如聯想）製造的 SSD。

注意：對於這些信息，三星提供得並不十分明確。他們似乎有 4 個不同的固件更新頁面，每個都介紹了不同的更新方法。

如果你想通過在 Linux 下創建的 Live USB 來更新固件（而不是在 Windows 下使用三星的 Magician 軟體），參見[11]。注意，該文章描述的通過 MBR 創建可啟動 U 盤的方法在一些新主板上（例如 Intel NUC）不再受支持。

#### 在 Linux 下更新

以下方法可以原生（不使用可啟動 U 盤）更新 SSD 固件。首先，訪問三星的下載頁，進入」Samsung SSD Firmware「一節，然後下載適用於你的 SSD 的最新固件（ISO 鏡像）。

注意：若 ISO 鏡像中沒有下面提到的 `initrd` Linux 鏡像，請跳到#較舊的 SSD 一節。

從 ISO 鏡像中解壓 Linux `initrd` 鏡像（將 samsung_ssd_firmware 替換為對應的 ISO 鏡像文件名）：

    $ bsdtar xf samsung_ssd_firmware.iso initrd

解壓 `root/fumagician/`。該目錄中包含固件更新文件：

    $ bsdtar xf initrd root/fumagician

最後，以根用戶權限運行 `root/fumagician/fumagician`，確認成功更新固件後，重啟計算機。

如果重啟後固件版本沒有變化，可以執行 `root/fumagician/fumagician 2> log` 並檢查日誌裡的報錯。例如，如果日誌裡寫著 'unzip is not available'，就說明需要安裝 unzip 或從 initrd 中提取 unzip。

#### 較舊的 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 的 Disk Number 獲取 SSD 對應的硬碟編號：

    # magician --list

更新 SSD 固件（將 firmware_package_path 替換為對應的固件包路徑）：

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

最後，以根用戶權限執行 `magician --list`，檢查輸出中 Firmware 對應的固件版本是否成功更新，並重啟計算機。

### 閃迪（SanDisk）

對於 SanDisk SSD Toolkit 不支持的作業系統，閃迪提供了 ISO 鏡像來進行固件更新。

你必須選擇對應 SSD 型號和容量（例如 60GB 或 256GB）正確的固件。燒錄 ISO 鏡像後，從創建的 CD/DVD 啟動盤啟動計算機即可（或許能使用 USB 啟動盤）。

此外，由於 ISO 鏡像只包含了 Linux 內核及 initrd，也可以將它們提取到 `/boot` 分區下，並用 GRUB 或 Syslinux 啟動來更新固件。

另見：

- SanDisk Extreme SSD Manual Firmware update version R211
- SanDisk Ultra SSD Manual Firmware update version 365A13F0
- SanDisk Ultra+ SSD Manual Firmware update version X2316RL - 以根用戶權限執行 `smartctl -i dev/disk/by-id/*SanDisk!(*part*)` 檢查是否使用了「H2」或「HP」型號。

## 另見

- Discussion on Reddit about installing Arch on an SSD
- Re: Varying Leafsize and Nodesize in Btrfs
- Re: SSD alignment and Btrfs sector size
- Erase Block (Alignment) Misinformation?
- Is alignment to erase block size needed for modern SSD's?
- Btrfs support for efficient SSD operation (data blocks alignment)

分類：​

- 存儲
- 使用「模板:風格」標記的頁面或章節

固態硬碟
新增話題