高级格式
硬盘驱动器 (HDD) 的最小物理存储单元是 扇区。固态驱动器 (SSD) 的对应物是页。 [1] 存储设备固件会将它们的物理扇区抽象为软件可以操作的逻辑扇区。该扇区的大小指的是磁盘上可寻址的最小单元的大小。
- 物理扇区大小
- 这是物理存储设备声明它可以原子写入的最小单元。对于 HDD,它是盘片上扇区的实际大小。传统上,HDD 的物理扇区大小是 512 字节,这意味着每个扇区可以容纳 512 字节的数据。然而,随着 高级格式 HDD 的推出,物理扇区大小增加到 4096 字节 (4 KiB),以提高存储密度并改善纠错能力。SSD 不会暴露它们的实际 NAND 闪存页大小,通常为 4 KiB 到 16 KiB,而是将报告的物理扇区大小与其逻辑扇区大小相同。对于 NVMe SSD,如果可用,将使用 原子写入单元断电 (AWUPF) 参数值。
- 逻辑扇区大小
- 逻辑扇区大小,也称为操作系统扇区大小,表示暴露给操作系统和应用程序的扇区大小。它是软件层面用于读取和写入存储设备的扇区大小。逻辑扇区大小可能与物理扇区大小不同。例如,物理扇区大小为 4096 字节的高级格式 HDD 可能仍然提供 512 字节的逻辑扇区大小,以兼容旧系统和应用程序。
不同的“层”,即设备、堆叠块设备和文件系统,应使用相同的扇区大小。如果它们不一致,固件的转换层中的映射过程,虽然通常是透明的,但会导致可避免的开销。
可以使用 lsblk 检查存储设备的*报告*的逻辑和物理扇区大小。
$ 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
LOG-SEC是逻辑扇区大小 (操作系统使用的可寻址单元)。PHY-SEC是设备报告的物理扇区大小。
PHY-SEC 值通常反映逻辑扇区大小,并不代表真实的物理写入粒度 (例如,NAND 页大小或原子写入单元)。大多数消费级 NVMe 驱动器不通过标准接口暴露此信息。NVMe 1.2a 规范将 AWUPF 定义为按逻辑块单元索引,并警告 AWUPF 可能为零,而零不代表物理 NAND 页大小。或者,可以查询 sysfs 条目。
$ cat /sys/class/block/drive/queue/physical_block_size $ cat /sys/class/block/drive/queue/logical_block_size
扇区大小也可以在 fdisk、smartctl 和 hdparm 的输出中看到。
这些值同样反映了设备报告的内容,但对于 SSD 或 NVMe 驱动器可能*不准确*,因为它们经常抽象或省略真实的物理特性。 [3]
有关 NVMe 驱动器的更详细信息,例如支持的 LBA 格式和原子写入单元粒度 (如果可用),以下 NVMe CLI 命令可能会有所帮助。
# nvme id-ns /dev/nvme0n1 | grep -i lbaf # nvme id-ctrl /dev/nvme0n1 | grep -i awupf
但是,许多驱动器只显示一个 LBA 格式 (例如,lbads:9,表示 512 字节的逻辑块),以及 `awupf` 值为 `0`,表明未提供原子写入单元信息。
更改扇区大小
某些 NVMe 驱动器和“企业级” SATA 硬盘驱动器支持使用标准的 NVMe (Format NVM,NVM 命令集规范 1.0 或更高版本) 或 ATA (SET SECTOR CONFIGURATION EXT,ATA 命令集 - 4 或更高版本) 命令更改其报告的扇区大小。对于硬盘驱动器,这会更改逻辑扇区大小以匹配物理扇区大小以获得最佳性能。而对于 NVMe 固态驱动器,逻辑和物理扇区大小值都会被更改。
SATA 固态驱动器通常不支持更改其扇区大小。例外情况是某些 Intel SATA SSD,它们可以更改报告的物理扇区大小,但不能更改逻辑扇区大小。 [2] 请遵循 #Intel 更改其报告的物理扇区大小。
更改驱动器的扇区大小是一个复杂的过程,需要低级格式化。作为替代方法,您可以在驱动器上创建文件系统时手动指定所需的扇区大小以获得最佳性能。请参阅 #dm-crypt 和 #File systems。
高级格式硬盘驱动器
要确定是否可以更改高级格式硬盘驱动器的扇区大小,请使用 hdparm 工具。
# hdparm -I /dev/sdX | grep 'Sector size:'
如果高级格式驱动器的扇区配置日志列出了多个逻辑扇区大小,则会显示一个列表。
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 扇区大小或 #File systems 块大小至少为 4096 字节并与之对齐。
一个高级格式 4Kn 驱动器。
Logical Sector size: 4096 bytes
Physical Sector size: 4096 bytes
4Kn 驱动器开箱即是最佳配置,在分区/格式化时无需特殊考虑。它们可以直接使用。
如果您的 SATA HDD 支持多个逻辑扇区大小和可选的 ATA 命令 SET SECTOR CONFIGURATION EXT (通常只在所谓的“企业级” HDD 中可用),您可以使用 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) 报告其逻辑块地址大小为 512 字节,即使它们物理上使用更大的块——通常是 4 KiB、8 KiB 或更大。
要检查 NVMe 驱动器的格式化逻辑块地址大小 (FLBAS),请使用 nvme-cli 工具并结合 Identify Namespace 命令。
# 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是每逻辑块地址 (LBA) 的额外元数据字节数。由于 Linux 对此支持不佳,最好在此选择值为 0 的格式。Relative Performance指示哪种格式将提供*降级*、*良好*、*更好*或*最佳*的性能。
smartctl 也可以显示支持的逻辑块地址大小,但它不提供用户友好的描述。例如:
# smartctl -c /dev/nvme0n1
... Supported LBA Sizes (NSID 0x1) Id Fmt Data Metadt Rel_Perf 0 + 512 0 2 1 - 4096 0 1
要更改逻辑块地址大小,请使用 nvme format 并使用 --lbaf 参数指定首选值。
# 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
这应该只需要几秒钟就能完成。
使用制造商特定程序
如果上述通用工具不允许更改扇区大小,仍有可能使用驱动器制造商的实用程序进行更改。
Intel
对于 Intel,请使用 Intel Memory and Storage (MAS) Tool (intel-mas-cli-toolAUR) 和 -set PhysicalSectorSize=4096 选项。请注意,这将仅更改报告的物理扇区大小,逻辑扇区大小将保持不变。
Seagate
Seagate 提供了 openseachestAUR。该实用程序也可用于非 Seagate 驱动器,因为它们使用标准的 ATA 和 NVMe 命令。
扫描所有驱动器以找到正确的驱动器,并打印您找到的驱动器信息。
# 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-and-may-render-the-drive-inoperable
这需要几分钟时间,之后您的驱动器将使用 4 KiB 的原生扇区大小。
分区对齐
正确对齐分区可避免过多的读-修改-写周期。个人电脑的典型做法是将每个分区的起始位置和大小对齐到 1 MiB (1 048 576 字节) 的标记。这涵盖了所有常见的页和块大小场景,因为它能被所有常用大小整除——1 MiB、512 KiB、128 KiB、4 KiB 和 512 B。
- fdisk、cfdisk 和 sfdisk 会自动处理对齐。
- gdisk 和 cgdisk 会自动处理对齐。
- sgdisk 默认仅对齐分区的起始位置。使用
-I/--align-end选项可额外启用分区大小/结束位置的对齐。
- sgdisk 默认仅对齐分区的起始位置。使用
- Parted 仅对齐分区起始位置,而不对齐大小/结束位置。创建分区时,请确保以 mebibytes 或更大的 IEC 二进制单位指定分区结束位置。
checkpartitionsalignment.sh 是一个使用 Parted 和 awk 检查对齐的 bash 脚本。
dm-crypt
从 Cryptsetup 2.4.0 开始,luksFormat 会自动检测 LUKS2 格式的最佳加密扇区大小。 [7]
但是,为了让这正常工作,设备需要报告正确的默认扇区大小,请参阅 #Changing sector size。
使用 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 reencrypt --sector-size=4096 device
文件系统
在 4Kn 磁盘 (4096 字节物理扇区大小和 4096 字节逻辑扇区大小) 上,所有 mkfs 工具都将使用 4096 字节的块大小。在 512e (4096 字节物理扇区大小,512 字节逻辑扇区大小) 和 512n (512 字节物理扇区大小和 512 字节逻辑扇区大小) 磁盘上,每个 mkfs 工具的行为都不同。
| mkfs 工具 | 512e 磁盘 | 512n 磁盘 |
|---|---|---|
| mkfs.bcachefs | 4096 | 512 |
| mkfs.btrfs(8) | 4096 | 4096 |
| mkfs.exfat(8) | 4096 | 512 |
| mkfs.ext4(8) | 40961 | 40961 |
| mkfs.fat(8) | 512 | 512 |
| mkfs.f2fs(8) | 4096 | 4096 |
| 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 |
- mkfs.ext4(8) 对于小于 512 MiB 的文件系统默认为 1024 字节扇区,对于 512 MiB 及更大的文件系统默认为 4096 字节扇区。
如果存储设备没有报告正确的扇区大小,您可以根据物理扇区大小显式格式化分区。
特别是,如果使用 512 字节的逻辑扇区大小而其物理扇区大小为 4096 字节,*叠瓦式磁记录* (SMR) 驱动器将受到严重负面影响。这些驱动器有不同的写入区域性能,并且在空闲时会发生重映射分配,但在活动写入期间 (例如,RAID 重建、备份、写入大量小文件、rsync 等),不同的文件系统扇区大小可能会将写入速度降低到每秒几兆字节,因为高性能写入区域会耗尽,而扇区转换层在叠瓦区域会被过度使用。
以下是一些显式设置 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 device0 … deviceN
已知问题
Syslinux 和 FAT
Syslinux 不支持扇区大小非 512 字节的 FAT 文件系统。
systemd-homed
systemd-homed 在 4Kn 驱动器和具有 4096 字节扇区大小的 LUKS 上无法正常工作。请参阅 systemd issue 30393 和 30394。
故障排除
NVMe 驱动器格式化失败
某些 NVMe 驱动器不支持 nvme format 命令,该命令是更改扇区大小 (LBA 格式) 所必需的。这仍然符合 NVMe 规范。问题也可能表现为 INVALID_OPCODE(2001) 或 INVALID_FORMAT: The LBA Format specified is not supported. This may be due to various conditions(0x10a)。如果是这种情况,请查看下面的“参考资料”中的链接。
要检查您的驱动器是否支持 Format NVM 命令:
# nvme id-ctrl /dev/nvme0 | grep oacs
查看 oacs 字段 (Optional Admin Command Support),这是一个 位掩码。Format NVM 支持对应于位 1 (值 0x02)。如果未设置位 1,则您的控制器不支持 Format NVM,您将无法更改 LBA 格式。
示例 (不支持 Format NVM)
oacs : 0x1d
将 0x1d 转换为二进制:0001 1101 → 未设置位 1 (从右边数第二个位是 0) → 不支持 Format NVM。
在某些情况下,即使支持 Format NVM,格式化仍然会失败。这通常发生在使用 Pyrite 但不支持 OPAL 安全的驱动器上,尤其是在使用 S0ix (Modern Standby) 的 Intel 平台上。在其他情况下,oacs 可能报告不支持 Format NVM,但在挂起/恢复周期后格式化仍然可以工作。
解决方法
- 在固件中禁用 S0ix (Modern Standby) (将睡眠模式设置为 S3 / S2idle)。
- 添加内核参数:
mem_sleep_default=s2idle - 挂起/恢复系统后再进行格式化。
受影响的型号
已知 Hynix PC601、Lenovo 和 Dell 笔记本电脑、Samsung 和 WD SN750 驱动器存在此问题。
参考
参见
- Western Digital 的高级格式:4K 扇区转换开始。
- 题为“高级格式技术”的白皮书。
- 未正确对齐 HDD 会导致读/写性能下降。有关具体示例,请参阅 [9]。