Windows下无法获取LID=5的NVMe日志页问题及解决咨询
问题描述
在Windows 10环境中,使用以下代码通过DeviceIoControl调用IOCTL_STORAGE_QUERY_PROPERTY获取NVMe日志页:
ZeroMemory(buffer, bufferLength); query = (PSTORAGE_PROPERTY_QUERY)buffer; protocolDataDescr = (PSTORAGE_PROTOCOL_DATA_DESCRIPTOR)buffer; protocolData = (PSTORAGE_PROTOCOL_SPECIFIC_DATA)query->AdditionalParameters; query->PropertyId = StorageAdapterProtocolSpecificProperty; query->QueryType = PropertyStandardQuery; protocolData->ProtocolType = ProtocolTypeNvme; protocolData->DataType = NVMeDataTypeLogPage; protocolData->ProtocolDataRequestValue = lid; protocolData->ProtocolDataRequestSubValue = 0; result = DeviceIoControl(FileHandle, IOCTL_STORAGE_QUERY_PROPERTY, buffer, bufferLength, buffer, bufferLength, &returnedLength, NULL);
遇到以下场景差异:
- 场景1:获取LID1-3的日志页,设备正常响应,执行成功;
- 场景2:获取LID=5(Command Supported and Effects)的日志页,设备无返回,但
GetLastError()返回0(SUCCESS),执行失败; - 场景3:Linux环境下调用对应API可正常获取LID1-5的日志页。
需明确场景2的问题原因,以及Windows 10中正确获取LID=5日志页的方法。
问题原因
- Windows默认NVMe驱动限制:Windows 10自带的
stornvme.sys驱动对LID=5这类包含设备命令集信息的敏感日志页有处理逻辑限制,不会直接将请求透传给设备,即使设备本身支持,也会返回空数据但标记操作成功。 - 缓冲区适配问题:LID=5日志页的默认数据量(通常为4KB以上)可能超过当前代码分配的缓冲区大小,驱动在缓冲区不足时不会抛出错误,仅返回空数据,导致
GetLastError()仍为0。
解决方法
方法1:使用IOCTL_STORAGE_PROTOCOL_COMMAND直接发送NVMe命令
绕过驱动封装,直接构造NVMe原生的Get Log Page命令(Opcode 0x02)发送请求,示例代码如下:
// 初始化命令结构体 STORAGE_PROTOCOL_COMMAND cmd = {0}; cmd.ProtocolType = ProtocolTypeNvme; cmd.DataType = NVMeDataTypePassthrough; cmd.CommandLength = sizeof(NVME_COMMAND); cmd.Flags = STORAGE_PROTOCOL_COMMAND_FLAG_ADAPTER_REQUEST; // 构造Get Log Page命令 NVME_COMMAND* nvmeCmd = (NVME_COMMAND*)cmd.Command; nvmeCmd->CommandOpcode = NVME_OPCODE_GET_LOG_PAGE; nvmeCmd->CommandSpecific[0] = 5; // 指定LID=5 nvmeCmd->CommandSpecific[1] = 0; nvmeCmd->DataTransferLength = htole32(bufferLength); // 缓冲区长度建议设为4096字节以上 // 发送命令 result = DeviceIoControl(FileHandle, IOCTL_STORAGE_PROTOCOL_COMMAND, &cmd, sizeof(cmd) + bufferLength, &cmd, sizeof(cmd) + bufferLength, &returnedLength, NULL);
方法2:更新Windows 10系统至最新版本
Windows 10 20H2及之后的版本对NVMe驱动做了优化,部分场景下可直接通过原代码获取LID=5日志页。
方法3:使用设备厂商专用NVMe驱动
替换Windows默认的stornvme.sys为设备厂商提供的专用驱动,这类驱动通常会完整支持NVMe协议的所有日志页请求。
内容的提问来源于stack exchange,提问作者洪書凱
相关产品推荐
相关产品推荐

