先进格式化
机械硬盘的最小物理存储单元为单个扇区。固态硬盘(SSD)相对应为页。[1] 存储设备的固件将设备上的物理扇区抽象为软件可操作的逻辑扇区。该扇区的大小即硬盘上最小可寻址单元的大小。
- 物理扇区大小
- 这是物理存储设备声称的可原子写入的最小单元。对于机械硬盘来说,这是指碟片上扇区的实际大小。在传统上,机械硬盘的物理扇区大小是 512 字节,这意味着每个扇区可以存放 512 字节的数据。但是,随着高级格式化机械硬盘的出现,物理扇区的扇区提高到了 4096 字节(4 KiB),使得存储密度和错误校正能力都有所提升。固态硬盘(SSD)则不对外 NAND 闪存的实际页大小(通常在 4 KiB 到 16 KiB 之间),而是将物理扇区大小和逻辑扇区大小汇报为同意值。对于 NVMe 固态硬盘,它会在电源故障原子写入单位(Atomic Write Unit Power Fail,AWUPF)参数可用时使用改值。
- 逻辑扇区大小
- 逻辑扇区大小(又称为操作系统扇区大小)代表了暴露给操作系统和应用的扇区大小。它是在软件层写入和读取存储设备的扇区大小。逻辑扇区大小可以和物理扇区不同,例如:为了保证旧系统和应用的兼容性,一个有 4096 字节物理扇区大小的高级格式化机械硬盘的逻辑扇区大小可能为 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
PHY-SEC
显示了物理扇区大小,LOG-SEC
显示了逻辑扇区大小。
另外,单个特定硬盘的值可以从下列 sysfs 条目读取:
$ cat /sys/class/block/drive/queue/physical_block_size $ cat /sys/class/block/drive/queue/logical_block_size
也可以通过 fdisk,smartctl 和 hdparm 的输出查看扇区大小。
修改扇区大小[编辑 | 编辑源代码]
部分 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:'
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
代表各类格式所提供的性能级别(包括 degraded,good,better 和 best)。
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
修改需要数秒来完成。
在启动结束阶段会发出非标准的“security freeze”的系统上时,生产于 2020 年前的硬盘可能会拦截 {{ic|Format NVM} 命令。[3][4] 如果 nvme format
命令失败,可以先尝试休眠系统(确保使用 S3 而不是 S0ix 休眠),然后在唤醒系统后尝试再次运行 nvme format
命令。[5][6]
使用制造商专用工具[编辑 | 编辑源代码]
如果上述通用工具无法修改扇区大小,可以试下使用硬盘制造商的专用工具进行修改。
英特尔(Intel)[编辑 | 编辑源代码]
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
修改需要数分钟,完成后你的硬盘扇区就是 4K 原生大小了。
分区对齐[编辑 | 编辑源代码]
正确的分区对齐可避免过多的读写操作。对于个人电脑而言,通常建议将各分区的起始端和大小对齐到 1 MiB(1 048 576 bytes)位置。这一操作涵盖了多数常见的页和块大小场景(通常的有 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 bash 脚本来使用 Parted 和 awk 检查对齐。
dm-crypt[编辑 | 编辑源代码]
As of Cryptsetup 2.4.0, luksFormat
automatically detects the optimal encryption sector size for LUKS2 format [9].
However, for this to work, the device needs to report the correct default sector size, see #Changing sector size.
After using cryptsetup luksFormat
, you can check the sector size used by the LUKS2 volume with
# cryptsetup luksDump device | grep sector
If the default sector size is incorrect, you can force create a LUKS2 container with a 4K sector size and otherwise default options with:
# cryptsetup luksFormat --sector-size=4096 device
The command will abort on an error if the requested size does not match your device:
# cryptsetup luksFormat --sector-size 4096 device (...) Verify passphrase: Device size is not aligned to requested sector size.
If you encrypted your device with the wrong sector size, the device can be re-encrypted by running:
# cryptsetup reencrypt --sector-size=4096 device
文件系统[编辑 | 编辑源代码]
在 4Kn(物理和逻辑扇区大小为 4096 字节)硬盘上,所有 mkfs 工具都会使用 4096 字节块大小。在 512e(4096 字节物理扇区大小,512 字节逻辑扇区大小)及 512n(物理和逻辑扇区大小为 512 字节)硬盘上,不同的 mkfs 工具会使用不同的值。
mkfs 工具 | 512e 硬盘 | 512n 硬盘 |
---|---|---|
mkfs.bcachefs | 4096 | 512 |
mkfs.btrfs(8) | 4096 | 4096 |
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 |
- mkfs.ext4(8) 默认为小于 512 MiB 的文件系统使用 1024 字节块大小,为 512MiB 及以上的使用 4096 字节大小。
如果存储设备没有汇报正确的扇区大小,你可以手动将分区按照物理扇区大小进行格式化。
特别是对于由固件管理的叠瓦式磁记录(SMR)硬盘,例如在物理扇区大小为 4096 字节的设备上使用了 512 字节逻辑扇区大小,它们将受到严重影响。这类磁盘有不同的写入性能区间,且在空闲时会进行重映射和重分配。但是当出现大量写入活动时(例如 RAID resilvering,备份,写入大量小文件,rsync 等),由于高性能写入区被耗尽且叠瓦区会拖慢扇区转换层,文件系统扇区与物理扇区大小不一致可能导致写入速度降到每秒个位数兆字节。
以下为一些将扇区显式设为 4096 字节大小的命令示例:
- Bcachefs:
# bcachefs format --block_size=4096 /dev/device0 /dev/deviceN --replicas=n
- 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
参考[编辑 | 编辑源代码]
- Western Digital’s Advanced Format: The 4K Sector Transition Begins
- White paper entitled "Advanced Format Technology."
- Failure to align one's HDD results in poor read/write performance. See [10] for specific examples.