此技能指导用户执行恢复操作,当运行在 Btrfs 文件系统中的 NixOS 系统遇到物理 SSD 坏扇区(NVMe I/O 错误)时,这些错误会破坏只读 /nix/store 中的特定路径。该技能解决了硬件级块重映射与软件级 Nix 存储状态对齐之间的差距。
触发条件 #
sudo nix-store --verify --check-contents --repair因内核 I/O 错误而卡住或崩溃。dmesg报告 NVMe 设备出现critical medium error或failed command: READ FPDMA QUEUED。dmesg报告特定 inode 出现BTRFS warning: csum failed。
执行协议 #
阶段 1:缓解物理坏块问题(硬件级) #
当某个物理扇区无法读取时,常规操作系统工具会卡住。我们必须强制 SSD 控制器清除并重新映射该坏块,通过向其中写入零值来实现。
- 从
dmesg中识别出故障的 LBA 地址(例如:sector 31547800)。 - 使用低级 NVMe 工具向损坏的块区域写入零值:注意:这绕过了 Btrfs,强制 SSD 控制器重新映射损坏的 NAND 闪存。
sudo nvme write-zeroes /dev/<nvme_device> -s <start_lba> -c <block_count> # 示例:sudo nvme write-zeroes /dev/nvme0n1 -s 31547800 -c 200
阶段 2:解决 Btrfs 校验和 (CSUM) 不匹配问题(文件系统级) #
写入零值后,硬件错误已消除,但文件系统检测到损坏(被零值覆盖)的数据,因为 Btrfs 校验和不一致。
- 触发读取操作以捕捉校验和错误并定位损坏的 Inode:
sudo btrfs scrub start -B / # 查看 dmesg 中的: "BTRFS warning: csum failed ... ino <inode_number>" - 将损坏的 Inode 映射到
/nix/store中的实际文件路径:sudo btrfs inspect-internal inode-resolve <inode_number> / # 如果上述方法失败,可使用: sudo find / -inum <inode_number> 2>/dev/null
阶段 3:清除损坏的 Nix 存储路径(包管理器级) #
由于 /nix/store 是不可变的(只读),我们必须临时将其重新挂载为可写,以删除损坏的包。
- 以可写权限重新挂载 Nix Store:
sudo mount -o remount,rw /nix/store - 修改权限并删除损坏的包目录(使用阶段 2 中找到的路径):
sudo chmod -R +w /nix/store/<hash>-<package-name> sudo rm -rf /nix/store/<hash>-<package-name>
阶段 4:Nix 数据库重建与验证(系统级) #
强制 Nix 识别缺失的路径,从二进制缓存中下载健康的副本,并重新验证系统完整性。
- 强制 Nix 下载/重建被删除的存储路径:
sudo nix-store --realise /nix/store/<hash>-<package-name> - (可选但推荐)运行全系统范围的 NixOS 修复以解决任何级联依赖问题:
sudo nixos-rebuild switch --repair - 进行最终深度验证检查:
sudo nix-store --verify --check-contents
预期结果 #
- 硬件: SSD 坏块成功重新映射。
- 文件系统: Btrfs
csum错误被清除。 - 操作系统:
/nix/store数据库完整性恢复,所有损坏的包重新下载到完好且经过验证的状态。