3、基础功能测试:设备枚举与识别、命名空间扫描、容量与LBA格式校验

好,咱们进入第三个章节。前面两章我们把测试环境和工具链搭好了,现在该真刀真枪地干活了。

基础功能测试,说白了就是回答三个问题:

  • 系统认没认出这个NVMe设备?
  • 设备里有多少个命名空间?
  • 每个命名空间的容量和LBA格式对不对?

这三个问题看似简单,但我在项目中遇到过不少坑。有些设备在枚举阶段就翻车了,有些是命名空间数量对不上,还有些是LBA格式配错了导致性能异常。嗯,咱们一个一个来拆解。

3.1 设备枚举与识别

设备枚举是第一步。你插上NVMe SSD,系统得能发现它,并且正确识别它的厂商、型号、固件版本。

我个人习惯先用 lspci 看一眼。NVMe设备在PCIe总线上,所以这条命令最直接:

# 查看NVMe控制器
lspci -vnn | grep -i nvme

# 输出示例
01:00.0 Non-Volatile memory controller [0108]: Samsung Electronics Co Ltd NVMe SSD Controller PM9A1 [144d:a80a] (rev 01)

这里要注意的是,有些设备可能被识别为「Non-Volatile memory controller」,但厂商ID和设备ID对不上。我曾经遇到过一颗国产主控,lspci显示的是「Generic NVMe Controller」,没有具体厂商信息。这种情况就要警惕了——可能是驱动没加载对,或者设备枚举阶段就有问题。

接下来用 nvme list 命令,这是最常用的工具:

nvme list

Node             SN                   Model                                    Version  Namespace Usage                      Format           FW Rev
---------------- -------------------- ---------------------------------------- -------- --------- -------------------------- ---------------- --------
/dev/nvme0n1     S6P9NB0R123456       Samsung SSD 980 PRO 1TB                  1.4      1         500.11  GB / 500.11  GB    512   B +  0 B   5B2QGXA7

看到这个输出,基本就放心了。但别急,我建议你多检查几个点:

  • Node:设备节点是否存在,比如 /dev/nvme0/dev/nvme0n1
  • Model:型号字符串是否完整,有没有乱码
  • FW Rev:固件版本是否和标称一致
  • Version:NVMe协议版本,比如1.3、1.4、2.0
注意:如果 nvme list 输出为空,但 lspci 能看到设备,大概率是驱动问题。检查一下内核是否加载了 nvmenvme_core 模块。

3.2 命名空间扫描

命名空间(Namespace)是NVMe协议里一个很重要的概念。一个物理设备可以分成多个逻辑空间,每个空间独立管理。

你想想看,如果设备宣称有4个命名空间,但实际只扫出来2个,那后面的测试全白做。

我一般用 nvme id-ctrl 查看控制器的能力,再用 nvme list-ns 列出所有命名空间:

# 查看控制器支持的命名空间数量
nvme id-ctrl /dev/nvme0 | grep -i nn

nn     : 4

nn 字段表示控制器支持的命名空间总数。如果这里显示4,但 nvme list-ns 只列出2个,那就有问题了。

# 列出所有命名空间
nvme list-ns /dev/nvme0

[   0]:0x1
[   1]:0x2
[   2]:0x3
[   3]:0x4

这里输出的是命名空间ID(NSID),从1开始。如果列表数量和 nn 一致,说明扫描通过。

小技巧:有些设备支持动态命名空间管理,比如通过NVMe-MI或NVMe over Fabrics动态添加。这种情况下,扫描结果可能和静态配置不一致。我建议在测试报告中注明「静态扫描」还是「动态扫描」。

3.3 容量与LBA格式校验

容量校验,听起来简单,但坑不少。我记得有一次,客户反馈说「1TB的盘,系统只显示953GB」。其实这是正常的,因为厂商用十进制(1TB = 1,000,000,000,000字节),而系统用二进制(1TiB = 1,099,511,627,776字节)。但作为测试,我们要确认的是:设备报告的容量和标称容量是否在合理误差范围内

nvme id-ns 查看命名空间的详细信息:

nvme id-ns /dev/nvme0n1

nsze    : 0x3a386000
ncap    : 0x3a386000
nuse    : 0x3a386000
nsfeat  : 0x0
nlbaf   : 0
flbas   : 0
mc      : 0
dpc     : 0
dps     : 0
nmic    : 0
rescap  : 0
fpi     : 0
dlfeat  : 0
lbaf0   : 0:0:0:0:0

关键字段解释:

字段 含义 校验要点
nsze 命名空间总容量(LBA数量) 乘以LBA大小后,应接近标称容量
ncap 命名空间最大容量 通常等于 nsze,如果小于则说明有预留空间
nuse 当前已使用的LBA数量 新盘应为0或接近0
nlbaf 支持的LBA格式数量 至少为0(表示支持1种格式)
flbas 当前使用的LBA格式索引 应在0到 nlbaf 之间
lbaf0 LBA格式0的描述 格式为 LBA数据大小:元数据大小:相对性能:...

容量计算很简单:

总容量(字节) = nsze × LBA数据大小

# 示例:nsze = 0x3a386000 = 976,773,120 LBA
# LBA数据大小 = 512字节
# 总容量 = 976,773,120 × 512 = 500,107,862,016 字节 ≈ 500GB

LBA格式校验,我建议重点关注两点:

  • 支持的格式是否完整:比如设备宣称支持512B、1KB、2KB、4KB,但实际只实现了512B和4KB,那就要标记为缺陷。
  • 当前格式是否合理:有些设备默认用4KB LBA,但上层文件系统可能只支持512B扇区。这种不匹配会导致性能下降甚至IO错误。
实战经验:我曾经测试过一颗企业级SSD,它支持8种LBA格式,但 nlbaf 字段只显示7。后来发现是固件bug,第8种格式的索引写错了。这种问题用 nvme id-ns 一眼就能看出来。

3.4 自动化测试脚本示例

手动测试一遍还行,但回归测试时总不能每次都敲命令吧?我写了个简单的脚本,把这些检查点串起来:

#!/bin/bash
# NVMe基础功能测试脚本

DEVICE="/dev/nvme0"
NAMESPACE="/dev/nvme0n1"
EXPECTED_CAPACITY_GB=500

echo "=== 1. 设备枚举检查 ==="
if [ -e "$DEVICE" ]; then
    echo "[PASS] 设备节点存在: $DEVICE"
else
    echo "[FAIL] 设备节点不存在"
    exit 1
fi

echo "=== 2. 命名空间扫描 ==="
NS_COUNT=$(nvme list-ns $DEVICE | wc -l)
if [ "$NS_COUNT" -ge 1 ]; then
    echo "[PASS] 命名空间数量: $NS_COUNT"
else
    echo "[FAIL] 未发现命名空间"
    exit 1
fi

echo "=== 3. 容量校验 ==="
NSZE=$(nvme id-ns $NAMESPACE | grep "nsze" | awk '{print $3}')
LBA_SIZE=$(nvme id-ns $NAMESPACE | grep "lbaf0" | awk -F: '{print $1}')
CAPACITY_BYTES=$((NSZE * LBA_SIZE))
CAPACITY_GB=$((CAPACITY_BYTES / 1000000000))

if [ "$CAPACITY_GB" -eq "$EXPECTED_CAPACITY_GB" ]; then
    echo "[PASS] 容量正确: ${CAPACITY_GB}GB"
else
    echo "[WARN] 容量偏差: 期望 ${EXPECTED_CAPACITY_GB}GB, 实际 ${CAPACITY_GB}GB"
fi

echo "=== 测试完成 ==="

这个脚本虽然简单,但覆盖了核心检查点。你可以根据实际需求扩展,比如加入LBA格式校验、固件版本比对等。

3.5 常见问题与避坑指南

最后,分享几个我踩过的坑:

  • 设备节点重复:有时候系统会生成 /dev/nvme0/dev/nvme1 指向同一个物理设备。这是因为驱动加载了两次。解决办法是检查 /sys/class/nvme/ 下的符号链接。
  • 命名空间ID不连续:理论上NSID从1开始连续递增,但有些设备会跳过某些ID。比如显示1、2、4,缺少3。这不一定是bug,但需要确认。
  • LBA格式切换失败:有些设备支持多种LBA格式,但切换后需要复位才能生效。如果测试时发现格式切换后容量不对,先试试 nvme reset
我的习惯:每次测试前,先执行 nvme listnvme id-ctrl 把设备信息保存到日志文件。这样出了问题可以回溯,看看是测试过程中变了,还是初始状态就不对。

好了,基础功能测试就讲到这里。下一章我们会深入IO路径测试,看看读写性能和数据完整性怎么验证。记住,基础不牢,地动山摇——设备枚举和命名空间扫描这一步,千万别偷懒。