多队列块层

多队列块层

简介

在早些时期,高性能的存储设备的IOPS只能跑到几百,而当今的高端设备动辄可以跑到几百万。所以内核块层的设计已经远远不能满足当今的IO处理需要。最近几年,社区已经意识到必须针对SSD这些高速的设备来重新设计一套新的机制。

从2.6.10开始,通用块层的基本结构就没有太大的变化。Linux设备驱动模型为块驱动提供了两种接口:一个是”request”方式,在这个模式下,通用块层维护一个简单的请求队列;新的IO请求提交到请求队列的末端,而驱动从前端开始接收并处理请求。当请求加入队列后,通用块层会将请求重新排序以减少寻道时间;并合并相邻的请求。

多队列的patch应该是3.13正式合入了主干

这种请求队列的实现方式是整个系统中最大的瓶颈。队列只有一个互斥锁,在大规模系统中,这个锁会在多个处理器之前频繁地切换。并且请求队列实际上是一个链表,修改链表中的元素的代价相对很大,而且在块层中,请求队列会被平凡的修改。所以一般在开发高性能存储驱动时,一般不会有人采用请求队列这种方式。

第二种是“make request”方式,这种方式可以让驱动直接处理request。但它的设计初衷并不是为了高性能设备,而是用于MD、RAID等这些堆叠的设备。主要是为了在请求发往下层的设备之前,做一些预处理。但用这种方式的代价也很大:有关队列的处理必须由驱动实现,而不能利用通用块层已有的能力。

为了解决以上的这些问题,提出了多队列块层的方式。在这种模式下,请求队列被分割成若干个队列:
- 在每一个CPU或者每一个node上面建立一个提交队列。每个CPU在自己的队列上面提交IO请求,不和其他CPU交互。这样的实现方式消除了cpu之间对锁的竞争(在每个cpu上建立队列),或者极大降低了锁的竞争(在每个Node上建立队列)。
- 硬件调度队列只是为驱动程序缓存IO请求。

块层还是用之前的方式处理提交队列的请求。针对SSD的排序几乎没有什么效果;事实上,跨多个设备的并行请求处理对性能提升很大。所以,不做排序,只做合并能够改善性能。因为提交队列是建立在每一个cpu上的,所以不可能跨队列来合并IO请求。但是,相邻的请求几乎总是来自同一个程序,所以这些请求会自动分发到同一个提交队列上,所以不能夸cpu的合并也不是什么大问题。

块层会按照驱动声明的最大个数,向硬件队列上提交请求。大多数的设备都只有单硬件队列,但一些高端设备已经支持多队列来提升并发性。在这些设备上,所有的IO处理都在用一个CPU上完成,能够尽可能地使用本地缓存。

在新的架构下写一个高性能的块驱动也非常简单。驱动只需要实现一个处理请求、并且在处理完成后回调块层的queue_rq函数。可以参考主干中的例子:null_blk.c。

以上参考自:http://lwn.net/Articles/552904/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值