先进格式化

来自 Arch Linux 中文维基
(重定向自Advanced Format

此页面或章节适合移动到 Storage layout and alignment

附注: “先进格式化”仅适用于机械硬盘。(在 Talk:先进格式化#Rewrite Advanced Format to a new Sector Sizes page 讨论)


提示:“高级格式化”一词在中文下可以指代先进磁盘格式,也可指代高级磁盘格式化;为避免歧义,本文将使用“先进格式化”一词:讨论:先进格式化#关于名称

机械硬盘的最小物理存储单元为单个扇区。固态硬盘(SSD)相对应为页。[1] 存储设备的固件将设备上的物理扇区抽象为软件可操作的逻辑扇区。该扇区的大小即硬盘上最小可寻址单元的大小。

注意: 无论存储设备为何种类型,软件和文档可能将“扇区”与“块”互换使用。
物理扇区大小
这是物理存储设备声称的可原子写入的最小单元。对于机械硬盘来说,这是指碟片上扇区的实际大小。在传统上,机械硬盘的物理扇区大小是 512 字节,这意味着每个扇区可以存放 512 字节的数据。但是,随着先进格式化机械硬盘的出现,物理扇区的扇区提高到了 4096 字节(4 KiB),使得存储密度和错误校正能力都有所提升。固态硬盘(SSD)则不对外 NAND 闪存的实际页大小(通常在 4 KiB 到 16 KiB 之间),而是将物理扇区大小和逻辑扇区大小汇报为同意值。对于 NVMe 固态硬盘,它会在电源故障原子写入单位(Atomic Write Unit Power Fail,AWUPF)参数可用时使用改值。
逻辑扇区大小
逻辑扇区大小(又称为操作系统扇区大小)代表了暴露给操作系统和应用的扇区大小。它是在软件层写入和读取存储设备的扇区大小。逻辑扇区大小可以和物理扇区不同,例如:为了保证旧系统和应用的兼容性,一个有 4096 字节物理扇区大小的先进格式化机械硬盘的逻辑扇区大小可能为 512 字节。

对于不同的“层”而言,即设备,堆叠块设备和文件系统,应保持同一扇区大小。否则,虽然固件的转换层的映射操作是透明的,仍会带来本可避免的开销。

可通过 lsblk 列出当前物理和逻辑扇区大小:

本文或本章节的事实准确性存在争议。

原因: 下列的两种命令(lsblkcat /sys/class...)都无法准确提供 NVMe 硬盘的物理扇区大小(可能涉及所有 SSDs),而是会给出逻辑扇区的大小。(在 Talk:先进格式化 中讨论)
$ lsblk -td
NAME    ALIGNMENT MIN-IO OPT-IO PHY-SEC LOG-SEC ROTA SCHED       RQ-SIZE  RA WSAME
sda             0   4096      0    4096    4096    1 mq-deadline      64 128    0B
nvme1n1         0   4096      0    4096    4096    0 none           1023 128    0B
nvme0n1         0   4096      0    4096    4096    0 none           1023 128    0B

PHY-SEC 显示了物理扇区大小,LOG-SEC 显示了逻辑扇区大小。

另外,单个特定硬盘的值可以从下列 sysfs 条目读取:

$ cat /sys/class/block/drive/queue/physical_block_size
$ cat /sys/class/block/drive/queue/logical_block_size

也可以通过 fdisksmartctlhdparm 的输出查看扇区大小。

修改扇区大小[编辑 | 编辑源代码]

警告: 修改硬盘的扇区大小将不可恢复地抹除所有数据。

部分 NVMe 和“企业级”SATA 硬盘分别支持通过标准的 NVMe(NVMe 命令集标准 1.0 或以上的 Format NVM)或 ATA(ATA 命令集 - 4 或以上的 SET SECTOR CONFIGURATION EXT)命令修改它们汇报的扇区大小。对于机械硬盘而言,这一操作通过修改它们的逻辑扇区大小到与物理扇区大小一致,优化了硬盘性能。而对于 NVMe 固态硬盘而言,逻辑扇区和物理扇区的大小都受到更改。

SATA 固态硬盘通常不支持修改扇区大小。部分 Intel SATA SSD 仅可以被修改汇报的物理扇区大小,无法修改逻辑扇区大小。[2] 可按照 #Intel 中的操作来修改硬盘汇报的物理扇区大小。

修改扇区大小包含了一系列复杂的操作,其中涉及到了低级格式化。作为替代,你可以在硬盘上创建文件系统时手动指定扇区大小来优化性能。详细信息可参考 #dm-crypt#文件系统

先进格式化机械硬盘[编辑 | 编辑源代码]

使用 hdparm 工具确定先进格式化硬盘的扇区大小是否可被更改:

# hdparm -I /dev/sdX | grep 'Sector size:'
注意: 对于通过 USB 连接的硬盘,对应的 USB 桥接器需支持 SAT(SCSI/ATA 翻译)(ANSI INCITS 431-2007)。

Advanced Format drives whose Sector Configuration Log lists multiple logical sector sizes will show a list of them:

        Logical  Sector size:                   512 bytes [ Supported: 512 4096 ]
        Physical Sector size:                  4096 bytes

不支持修改逻辑扇区大小的硬盘将只会汇报当前扇区大小。以一块 512e 先进格式化硬盘为例:

        Logical  Sector size:                   512 bytes
        Physical Sector size:                  4096 bytes

为了达到这一类硬盘的最佳性能,请确保 #dm-crypt 扇区大小或#文件系统块大小至少为 4096 字节,并与其对齐。

对于一块先进格式化的 4Kn 硬盘:

        Logical  Sector size:                  4096 bytes
        Physical Sector size:                  4096 bytes

4Kn 硬盘在出厂时已经是最佳配置,不需要在分区/格式化是进行特殊操作,可以照常使用。

如果你的 SATA 机械硬盘支持多个逻辑扇区大小和可选的 SET SECTOR CONFIGURATION EXT ATA 命令(例如希捷宣传带有 FastFormat 功能的硬盘),你可以使用 hdparm 来在支持的不同逻辑扇区大小间进行切换。可使用以下命令将其设为 4096 字节(即 4Kn):

# hdparm --set-sector-size 4096 --please-destroy-my-drive /dev/sdX

之后 hdparm 应汇报逻辑扇区大小为 4096 字节:

# hdparm -I /dev/sdX | grep 'Sector size:'
        Logical  Sector size:                  4096 bytes [ Supported: 512 4096 ]
        Physical Sector size:                  4096 bytes

NVMe 固态硬盘[编辑 | 编辑源代码]

虽然固态硬盘(SSD)经常使用较大的物理块(通常为 4 KiB,8 KiB,有时会更大),它们通常还是将自己的逻辑块大小汇报为 512 字节。

可以通过 nvme-cli 使用 Identify Namespace 命令来查看 NVMe 硬盘的格式化后逻辑块地址大小(Formatted Logical Block Address Size, FLBAS):

# nvme id-ns -H /dev/nvme0n1 | grep "Relative Performance"
LBA Format  0 : Metadata Size: 0   bytes - Data Size: 512 bytes - Relative Performance: 0x2 Good (in use)
LBA Format  1 : Metadata Size: 0   bytes - Data Size: 4096 bytes - Relative Performance: 0x1 Better
  • Metadata Size 是每个逻辑块地址(Logical Block Address, LBA)的额外元数据字节大小。这一功能在 Linux 上尚无完善支持,所以最好是使用该值为 0 的格式。
  • Relative Performance 代表各类格式所提供的性能级别(包括 degradedgoodbetterbest)。

smartctl 也可以显示设备支持的逻辑块地址大小,但输出的结果可读性不佳。例如:

# smartctl -c /dev/nvme0n1
...
Supported LBA Sizes (NSID 0x1)
Id Fmt  Data  Metadt  Rel_Perf
 0 +     512       0         2
 1 -    4096       0         1

可以使用 --lbaf 参数向 nvme format 命令传入目标值来修改逻辑块地址大小:

# nvme format --lbaf=1 /dev/nvme0n1
You are about to format nvme0n1, namespace 0x1.
WARNING: Format may irrevocably delete this device's data.
You have 10 seconds to press Ctrl-C to cancel this operation.

Use the force [--force] option to suppress this warning.
Sending format operation ... 
Success formatting namespace:1

修改需要数秒来完成。

注意: 确保分区时参照#分区对齐进行,否则将破坏任何性能优势。

本文或本章节的事实准确性存在争议。

原因: 在调整电源状态或是 UEFI 设置前,建议用户使用原生 nvme 命令检查操作日志,或是使用类似 nvme reset 的命令软重置控制器。(在 Talk:先进格式化 中讨论)


在启动结束阶段会发出非标准的“security freeze”的系统上时,生产于 2020 年前的硬盘可能会拦截 {{ic|Format NVM} 命令。[3][4] 如果 nvme format 命令失败,可以先尝试休眠系统(确保使用 S3 而不是 S0ix 休眠),然后在唤醒系统后尝试再次运行 nvme format 命令。[5][6]

使用制造商专用工具[编辑 | 编辑源代码]

如果上述通用工具无法修改扇区大小,可以试下使用硬盘制造商的专用工具进行修改。

英特尔(Intel)[编辑 | 编辑源代码]

本文内容或本节内容已经过期。

原因: 自从 Intel 固态硬盘业务被 SK 海力士以 Solidigm 品牌收购后,Intel MAS 工具就只能用于傲腾(Optane)产品上,不再能被用于管理固态硬盘。Solidigm 提供了与 Intel MAS 过去功能相同的 solidigm-sst-storage-tool-cliAUR 工具,可参考 Solid_state_drive/NVMe#Intel/Solidigm。 (在Talk:先进格式化讨论)

这篇文章的某些内容需要扩充。

原因: Intel 的工具只会修改汇报的物理扇区大小,逻辑扇区大小仍将保持为 512 字节。[7] (在 Talk:先进格式化 中讨论)

For Intel use the Intel Memory and Storage (MAS) Tool (intel-mas-cli-toolAUR) with the -set PhysicalSectorSize=4096 option.

希捷(Seagate)[编辑 | 编辑源代码]

对于希捷可以使用 openseachestAUR

扫描所有硬盘来找到要修改的硬盘,然后输出对应硬盘的相关信息:

# openSeaChest_Basics --scan
# openSeaChest_Basics -d /dev/sdX -i

应该可以看到硬盘的详细信息了。请确保序列号与修改目标匹配。

通过以下命令检查硬盘支持的逻辑区块大小:

# openSeaChest_Format -d /dev/sdX --showSupportedFormats

如果其中包含 4096,你可以使用以下命令将逻辑扇区大小修改为对应值:

# openSeaChest_Format -d /dev/sdX --setSectorSize=4096 --confirm this-will-erase-data

修改需要数分钟,完成后你的硬盘扇区就是 4 KiB 原生大小了。

分区对齐[编辑 | 编辑源代码]

正确的分区对齐可避免过多的读写操作。对于个人电脑而言,通常建议将各分区的起始端和大小对齐到 1 MiB(1 048 576 bytes)位置。这一操作涵盖了多数常见的页和块大小场景(通常的有 1 MiB,512 KiB,128 KiB,4 KiB 和 512 B)。

警告: 分区对齐错误将造成无法在 dm-crypt/LUKS 上使用 4096 字节扇区大小,参见 [8]
  • fdisk,cfdisk 和 sfdisk 会自动处理分区对齐。
  • gdisk 和 cgdisk 会自动处理分区对齐。
    • sgdisk 默认只对齐分区的起始端。可以通过 -I/--align-end 选项额外启用分区大小和末端对齐。
  • Parted 只对齐分区起始端,而不对齐分区大小和末端。在创建分区时,请确保使用 mebibytes 或是更大的 IEC 二进制单位指定分区末端。

可以通过 checkpartitionsalignment.sh bash 脚本来使用 Parted 和 awk 检查对齐。

dm-crypt[编辑 | 编辑源代码]

这篇文章的某些内容需要扩充。

原因: Add example for plain dm-crypt. (在 Talk:先进格式化 中讨论)

Cryptsetup 2.4.0开始,luksFormat会自动检测 LUKS2 格式的最佳加密扇区大小[9]

但要实现这一点,需要设备报告正确的默认扇区大小,详情请参考#修改扇区大小

执行 cryptsetup luksFormat 后,你可以使用如下命令确认 LUKS2 卷所使用的扇区大小:

# cryptsetup luksDump device | grep sector

如果默认扇区大小不正确,可以使用默认选项并强制创建一个扇区大小为 4 KiB 的 LUKS2 容器:

# cryptsetup luksFormat --sector-size=4096 device

如果请求的大小与设备不匹配,命令会出现报错并终止:

# cryptsetup luksFormat --sector-size 4096 device
(...)
Verify passphrase: 
Device size is not aligned to requested sector size.
注意: 参阅 cryptsetup issue 585 来了解在硬盘确实使用 4 KiB 物理扇区的情况下,命令仍可能失败的原因。

如果您使用了错误的扇区大小对设备进行加密,可以使用如下命令重新加密设备:

警告: 所包含的文件系统的块大小必须是 4096 字节或其倍数,否则就会崩溃。
# cryptsetup reencrypt --sector-size=4096 device

文件系统[编辑 | 编辑源代码]

这篇文章的某些内容需要扩充。

原因: Differentiate which mkfs utilities use 4096 explicitly and which use the page size (getconf PAGESIZE). (在 Talk:先进格式化 中讨论)

在 4Kn(物理和逻辑扇区大小为 4096 字节)硬盘上,所有 mkfs 工具都会使用 4096 字节块大小。在 512e(4096 字节物理扇区大小,512 字节逻辑扇区大小)及 512n(物理和逻辑扇区大小为 512 字节)硬盘上,不同的 mkfs 工具会使用不同的值。

非 4Kn 硬盘的文件系统块大小(字节)
mkfs 工具 512e 硬盘 512n 硬盘
mkfs.bcachefs 4096 512
mkfs.btrfs(8) 4096 4096
mkfs.exfat(8) 512 512
mkfs.ext4(8) 40961 40961
mkfs.fat(8) 512 512
mkfs.f2fs(8) 512 512
mkfs.jfs(8) 4096 4096
mkfs.nilfs2(8) 4096 4096
mkfs.ntfs(8) 512 512
mkfs.reiserfs(8) 4096 4096
mkfs.udf(8) 512 512
mkfs.xfs(8) 4096 512
mkswap(8) 4096 4096
zpool-create(8) 512 512
  1. mkfs.ext4(8) 默认为小于 512 MiB 的文件系统使用 1024 字节块大小,为 512MiB 及以上的使用 4096 字节大小。

如果存储设备没有汇报正确的扇区大小,你可以手动将分区按照物理扇区大小进行格式化。

特别是对于由固件管理的叠瓦式磁记录(SMR)硬盘,例如在物理扇区大小为 4096 字节的设备上使用了 512 字节逻辑扇区大小,它们将受到严重影响。这类磁盘有不同的写入性能区间,且在空闲时会进行重映射和重分配。但是当出现大量写入活动时(例如 RAID resilvering,备份,写入大量小文件,rsync 等),由于高性能写入区被耗尽且叠瓦区会拖慢扇区转换层,文件系统扇区与物理扇区大小不一致可能导致写入速度降到每秒个位数兆字节。

注意: 在 x86_64 系统上,Linux 无法挂载扇区大于 4 KiB 的文件系统。具体细节和当前进度可参考 Large block sizes (LBS)

以下为一些将扇区显式设为 4096 字节大小的命令示例:

  • Bcachefs:
    # bcachefs format --block_size=4096 /dev/device0 /dev/deviceN --replicas=n
  • exFAT:
    # mkfs.exfat -s 4096 /dev/device
  • ext4:
    # mkfs.ext4 -b 4096 /dev/device
  • FAT:
    # mkfs.fat -S 4096 /dev/device
  • NTFS-3G:
    # mkfs.ntfs -Q -s 4096 /dev/device
  • UDF:
    # mkfs.udf -b 4096 /dev/device
  • XFS:
    # mkfs.xfs -s size=4096 /dev/device
  • ZFS:
    # zpool create -o ashift=12 poolname raidz device0deviceN

参考[编辑 | 编辑源代码]