You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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日志页的方法。

问题原因
  1. Windows默认NVMe驱动限制:Windows 10自带的stornvme.sys驱动对LID=5这类包含设备命令集信息的敏感日志页有处理逻辑限制,不会直接将请求透传给设备,即使设备本身支持,也会返回空数据但标记操作成功。
  2. 缓冲区适配问题: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,提问作者洪書凱

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 07:00:19