NVMe设备命令大小限制

来源:互联网 发布:js设置button颜色 编辑:程序博客网 时间:2024/05/16 02:50

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的赋值了。

0 0
原创粉丝点击