Flash的出现把存储的世界搅翻了天,仿佛一夜之间发现了新大陆,所有旧世界的东西都变得笨拙。NVMe驱动义无反顾地抛弃了Linux blk,开发自己的队列管理。

当第一次看到NVMe重新使用Linux Block队列管理blk-mq的时候,还是比较惊讶的:现在的NVMe工作的好好的,为什么要换,增加blk-mq会不会造成性能下降?相信很多人都有这个疑惑。刚好手上有个centos7.2环境,我们就来一探究竟:

强势回归,Linux blk用实力证明自己并不弱!-LMLPHP

上图是我按NVMe是否使用blk-mq做的简单测试,可以看到,从Latency和IOPS两个方面都没有较大变化,说明blk-mq的引入带来的overhead非常小。那么blk-mq是怎么做到的呢?

就从blk-mq的那篇paper说起吧。在<Linux Block IO: Introducing Multi-queue SSD Access on Multi-core Systems>中,作者着重强调了之前single-queue的缺陷(多核竞争访问引入锁,跨NUMA中断处理,跨NUMA内存访问),非常不适合为现代的多路服务器高性能介质服务。痛定思痛,在blk-mq中对这方面大做修改。

blk-mq引入了两层Queue的概念,Software Queue和 Hardware Queue。这样的设计有多个目的:

1,在Software Queue中把Queue的数量设置死(与Core数量相等或者与MUMA 数量相等),这样就不会产生竞争了

2,Hardware数量由底层驱动决定,可以是一个或者多个;这也是为了尽快和之前的SATA SAS使用的单队列兼容

3,在software Queue里把 I/O Scheduling等Block积累几十年的Feature用起来,与底层驱动的联系由Hardware Queue负责。

那Software Queue和Hardware Queue的数量应该是多少呢?作者用实验给出了答案:如下在每个Core上发送相同数量的I/O,然后测试不同Hardware Queue和Software Queue的数量对性能产生的影响。

单个Software Queue的情况下,无论Hardware Queue是多少,性能都很差!

强势回归,Linux blk用实力证明自己并不弱!-LMLPHP

每个Core配一个Software Queue的情况下,Hardware Queue与Software Queue相等的情况下最好(core少的情况下跟NUMA一样也取得不错的性能)!

强势回归,Linux blk用实力证明自己并不弱!-LMLPHP

当然,这个测试也有一定的局限性,就是在单个Queue的情况下,测了最差的情况(所有的Core都去访问一个Queue)。


由于NVMe本身就是Multi-Queue的设计,跟这种队列配合起来还是比较容易的。只要将Hardware Queue和NVMe Queue一一对应就行。要移植NVMe到blk-mq最主要的工作就是定义下面的结构体。

强势回归,Linux blk用实力证明自己并不弱!-LMLPHP

第一个成员queue_rq指定blk-mq向驱动提交request的函数,第二个map_queue定义如何将software queue和hardware queue对应,第三个init_hctx是hardware Queue创建时调用(可以在这里将NVMe Queue与Hardware Queue绑定),init_request是在分配Request时调用,timeout是发生timeout时的调用。这些函数都是供blk-mq使用的。

blk-mq通过一个blk_mq_tag_set结构体来定义队列组合(可以指定timeout值,iodepth和hardware queue的个数等)。NVMe驱动在每一个设备加载时就定义一个这样的对象,然后在分配namespace的时候使用ns->queue = blk_mq_init_queue(&dev->tagset)给每个Namespace分配一个队列(request_queue 类型,包含hardware queue和software queue信息)。

强势回归,Linux blk用实力证明自己并不弱!-LMLPHP

下面是NVMe驱动定义的Hardware Queue初始化时的调用函数,可以看到将NVMe Queue赋给了Hardware Queue的driver_data。

强势回归,Linux blk用实力证明自己并不弱!-LMLPHP

当blk-mq下发Request的时候,会传递Hardware Queue对象,通过取出hardware Queue的driver_data,就可以得到Request对应的nvme queue了。

强势回归,Linux blk用实力证明自己并不弱!-LMLPHP

所以,用了blk-mq,NVMe驱动再也不用管request要放到哪个NVMe Queue了,而且I/O timeout,I/O统计这些都可以交给blk干。最重要的,还能够享受blk的IO scheduling 等功能。并入blk-mq后,NVMe驱动轻松了很多,性能有很好,对于开发者来说,何乐而不为?

参考文献

Linux Block IO: Introducing Multi-queue SSD Access on Multi-core Systems

提示

本文选自公众号《存储技术最前线》,欢迎关注获取最新文章。

往期NVMe驱动文章回顾

NVMe驱动解析-注册设备

NVMe驱动解析-关键的BAR空间

NVMe驱动解析-DMA传输

NVMe驱动解析-响应I/O请求

强势回归,Linux blk用实力证明自己并不弱!-LMLPHP

05-02 18:45