NVMe设备命令大小限制

NVMe设备命令大小限制

1 定义

单个NVMe命令是有一定大小限制的,host如果提交一个超过限制大小的命令,将会终止执行并得到一个值为0x02的状态码,代表Invalid Field in Command。

NVMe设备单个命令大小由Maximum Data Transfer Size (MDTS)限制,这个数字可以通过identify命令获取。

MDTS的单位是Minimum Memory Page Size(CAP.MPSMIN),它的定义是NVMe controller可以支持的host的最小内存页大小。每一个NVMe设备至少要支持4K的host页大小,因此从PCI Register中获得的MPSMIN的值定义为log后减12的结果。亦即:

MPSMINReal=2CAP.MPSMIN+12

MDTS的值也是log后的结果,因此实际的MDTS以字节为单位:

MDTSReal=2MDTS+CAP.MPSMIN+12

可以发现在NVMe设备初始化函数 nvme_dev_add 中有这样的表述:

int shift = NVME_CAP_MPSMIN(readq(&dev->bar->cap)) + 12;
if (ctrl->mdts)
    dev->max_hw_sectors = 1 << (ctrl->mdts + shift - 9);

显然,这段语句具体阐释了这一运算过程。注意到,在算sector数的时候有一个减去9的操作,这是因为每个sector默认大小为512B。

2 应用

nvme-scsi.c 用于将一个标准scsi命令转化为NVMe命令。它的 nvme_trans_do_nvme_io 函数负责read/write命令的转换。考虑到一个scsi读写命令使用的缓冲区可能会发送超过上述大小,这个函数需要将之分割成小块并分别填充成单独的NVMe命令:

u32 max_blocks = queue_max_hw_sectors(ns->queue);
u32 num_cmds = nvme_trans_io_get_num_cmds(hdr, cdb_info, max_blocks);
for (i = 0; i < num_cmds; i++) {
    ...
}

显然ns->queue中存了一些有意思的值。这些值是哪里来的呢?可以看到,在添加NVMe设备过程中调用的用于对namespace进行初始化的函数 nvme_alloc_ns 中有如下语句:

blk_queue_max_hw_sectors(ns->queue, dev->max_hw_sectors);

显然就是来自上面那次对dev->max_hw_sectors的赋值了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值