Skip to content

Namespace

Crane Chu edited this page May 13, 2020 · 6 revisions

发送一个IO命令需要Buffer、Qpair和Namespace类。我们已经看过前面两个类,现在轮到Namespace了。通过Namepsace类,脚本可以向某个Namespace发出IO命令,当然也可以同时向多个Namespace发送任意IO命令。Namespace类主要提供对NVMe协议里面第6章内容的支持。这里是一个例子。

def test_namespace_multiple(buf):  #L1
    addr_list = [b'3d:00.0']  #L2
    nvme_list = [d.Controller(a) for a in addr_list]  #L3

    for nvmex in nvme_list:  #L5
        qpair = d.Qpair(nvmex, 8)  #L6
        nvmexn1 = d.Namespace(nvmex)  #L7

        #Check if support write uncorrectable command
        wuecc_support = nvmex.id_data(521, 520) & 0x2
        if wuecc_support != 0:  #L11
            nvmexn1.write_uncorrectable(qpair, 0, 8).waitdone()  #L12
            with pytest.warns(UserWarning, match="ERROR status: 02/81"):
                nvmexn1.read(qpair, buf, 0, 8).waitdone()  #L14
                
            nvmexn1.write(qpair, buf, 0, 8).waitdone()  #L16
            def this_read_cb(dword0, status1):  #L17
                assert status1>>1 == 0
                nvmexn1.write_uncorrectable(qpair, 0, 8)  #L19
            nvmexn1.read(qpair, buf, 0, 8, cb=this_read_cb).waitdone(2)  #L20

            def another_read_cb(dword0, status1):  #L22
                logging.info("dword0: 0x%08x" % dword0)
                logging.info("phase bit: %d" % (status1&1))
                logging.info("dnr: %d" % ((status1>>15)&1))
                logging.info("more: %d" % ((status1>>14)&1))
                logging.info("sct: 0x%x" % ((status1>>9)&0x7))
                logging.info("sc: 0x%x" % ((status1>>1)&0xff))
            with pytest.warns(UserWarning, match="ERROR status: 02/81"):
                nvmexn1.read(qpair, buf, 0, 8, cb=another_read_cb).waitdone()  #L30
  • L1. 建立一个测试函数,声明一个4K的Buffer对象。
  • L2. 将所有待测设备的BDF地址收集在一个List里面,这里受限于平台,只有一个设备。
  • L3. 对所有BDF地址创建Controller对象。
  • L5. 对所有Controller对象依次做下列测试。这里也可以使用Python的mutliprocessing做多进程并发测试。
  • L6. 在被测controller上建立qpair对象。
  • L7. 在被测controller上建立namespace对象。
  • L11. 检查这个controller是否支持write uncorrectable命令。
  • L12. 发起并回收write uncorrectable命令,将LBA0-7定义为uncorrectable。
  • L14. 读取LBA0-7,期望产生02/81 (Unrecovered Read Error)错误状态,并捕获这个warning。
  • L16. 写LBA0-7,覆盖掉uncorrectable状态。
  • L17. 定义一个回调函数,供L20处的读命令结束时使用。
  • L19. 在回调函数中发起第二次write uncorrectable命令,将LBA0-7定义为uncorrectable。
  • L20. 再次读取LBA0-7,能正常读取,没有错误状态。这条读命令返回后,pynvme会自动调用指定的回调函数,回调函数会发起另一条命令。所以这里waitdone参数为2,表示等待2条命令结束,包括此行读命令以及回调函数里面发起的第二条write uncorrectable命令。
  • L22. 定义另外一个回调函数,在L30处的命令结束时调用。pynvme会给回调函数2个参数,分别是CQE的dowrd0以及status字段。需要注意的是,为了处理方便,此处的status字段也包含了phase bit,此处和spec定义略有差异。回调函数里面打印status字段里面的具体信息。
  • L30. 最后一次读取LBA0-7,又期望捕获错误状态。

以前pytest命令行里面会带上pciaddr参数。这个参数给给pytest fixture nvme0使用的。但这个测试函数定义里面并没有用到nvme0,所以命令行不需要提供pciaddr这个参数。参数-s会让pytest打印更多log到屏幕。我们能看到第一次和最后一次读返回了错误状态02/81,而且这个错误状态被脚本捕获,符合脚本的期望,所以最终测试结果是PASS。

laptop:~/pynvme▶ sudo python3 -m pytest scripts/cookbook.py::test_namespace_multiple -s
================================= test session starts =================================
platform linux -- Python 3.8.2, pytest-5.4.1, py-1.8.1, pluggy-0.13.1
rootdir: /home/cranechu/pynvme, inifile: pytest.ini
plugins: cov-2.8.1
collected 1 item                                                                      

scripts/cookbook.py::test_namespace_multiple 
----------------------------------- live log setup ------------------------------------
[2020-05-13 21:06:34.598] INFO script(65): setup random seed: 0x3fe38b16
[2020-05-13 21:06:34.947681] NOTICE driver.c(1085) ns_table_init: memory is not large enough to keep CRC32 table.
[2020-05-13 21:06:34.947725] NOTICE driver.c(1086) ns_table_init: Data verification is disabled!
[2020-05-13 21:06:34.954729] NOTICE nvme_qpair.c(132) nvme_io_qpair_print_command: READ sqid:1 cid:5 nsid:1 lba:0 len:8
[2020-05-13 21:06:34.954753] NOTICE nvme_qpair.c(303) spdk_nvme_qpair_print_completion: UNRECOVERED READ ERROR (02/81) sqid:1 cid:5 cdw0:0 sqhd:0002 p:1 m:0 dnr:1
[2020-05-13 21:06:34.968916] NOTICE nvme_qpair.c(132) nvme_io_qpair_print_command: READ sqid:1 cid:4 nsid:1 lba:0 len:8
[2020-05-13 21:06:34.968938] NOTICE nvme_qpair.c(303) spdk_nvme_qpair_print_completion: UNRECOVERED READ ERROR (02/81) sqid:1 cid:4 cdw0:0 sqhd:0006 p:1 m:0 dnr:1
------------------------------------ live log call ------------------------------------
[2020-05-13 21:06:34.968] INFO another_read_cb(87): dword0: 0x00000000
[2020-05-13 21:06:34.969] INFO another_read_cb(88): phase bit: 1
[2020-05-13 21:06:34.969] INFO another_read_cb(89): dnr: 1
[2020-05-13 21:06:34.969] INFO another_read_cb(90): more: 0
[2020-05-13 21:06:34.969] INFO another_read_cb(91): sct: 0x2
[2020-05-13 21:06:34.969] INFO another_read_cb(92): sc: 0x81
PASSED
---------------------------------- live log teardown ----------------------------------
[2020-05-13 21:06:34.971] INFO script(67): test duration: 0.374 sec


================================== 1 passed in 0.42s ==================================