Linux上传统的块设备层(Block Layer)和IO调度器(如cfq)主要是针对HDD(hard disk drivers)设计的。我们知道,HDD设备的随机IO性能很差,吞吐量大约是几百IOPS(IOs per second),延迟在毫秒级,所以当时IO性能的瓶颈在硬件,而不是内核。但是,随着高速SSD(Solid State Disk)的出现并展现出越来越高的性能,百万级甚至千万级IOPS的数据访问已成为一大趋势,传统的块设备层已无法满足这么高的IOPS需求,逐渐成为系统IO性能的瓶颈。
为了适配现代存设备(高速SSD等)高IOPS、低延迟的IO特征,新的块设备层框架Block multi-queue(blk-mq)应运而生。本文就带大家来了解下Linux 块设备层的blk-mq框架和代码实现。
一、单队列框架和存在的问题
Linux上传统块设备层使用单队列(Single-queue/SQ)架构,如图1所示。简单来说,块设备层负责管理从用户进程到存储设备的IO请求,一方面为上层提供访问不同存储设备的统一接口,隐藏存储设备的复杂性和多样性;另一方面,为存储设备驱动程序提供通用服务,让这些驱动程序以最适合的方式接收来自上层的IO请求。Linux Block Layer主要提供以下几个方面的功能:
图1. 单队列的Linux block layer设计图1. 单队列的Linux block layer设计
图片引用自《Linux Block IO: Introducing Multi-queue SSD Access on Multi-core Systems》
由于采用单队列(每个块设备1个请求队列--Requst Queue)的设计,传统的Block Layer对多核体系的可扩展性(scalability)不佳。当系统配备现代高速存储器件时,单队列引入的软件开销变得突出(在多socket体系中尤为严重),成为IO性能的瓶颈。多核体系中blk-sq的软件开销主要来自三个方面:
图2. 高IOPS场景下cpu热点数据
图片引用自《High Performance Storage with blk-mq and scsi-mq》图片引用自《High Performance Storage with blk-mq and scsi-mq》
图3. blk-sq IOPS吞吐量随cpu数量的变化曲线,blk-sq支持的最高吞吐量大概在1MIOPS 图片引用自《Linux Block IO: Introducing Multi-queue SSD Access on Multi-core Systems》
二、多队列框架和解决的问题
针对blk-sq存在的问题,Jens Axboe (Linux内核Block Layer Maintainer)提出了多队列(multi-queue/MQ)的块设备层架构(blk-mq),如图4所示:
图4. 两层队列的Block Layer设计图
图片引用自《Linux Block IO: Introducing Multi-queue SSD Access on Multi-core Systems》
blk-mq中使用了两层队列,将单个请求队列锁的竞争分散多个队列中,极大的提高了Block Layer并发处理IO的能力。两层队列的设计分工明确:
MQ架构解决了SQ架构中请求队列锁竞争和远端内存访问问题,极大的提高了Block Layer的IOPS吞吐量。从图5中,我们可以看到Linux 3.17-rc3 中scsi-mq+blk-mq,与图2相同的高IOPS场景下仅3%的cpu时间耗费在锁获取上。
图5. scsi-mq_+blk-mq高IOPS场景下cpu热点数据
图片引用自《High Performance Storage with blk-mq and scsi-mq》
图6. IOPS吞吐量随cpu数量的变化曲线,blk-mq更加接近raw设备的性能
图片引用自《Linux Block IO: Introducing Multi-queue SSD Access on Multi-core Systems》
三、多队列框架代码分析
blk-mq代码在Linux-3.13(2014)内核中合入主线,在Linux-3.16中成为内核的一个完整特性,在Linux-5.0内核中,blk-sq代码(包括基于blk-sq的IO调度器,如cfq、noop)已被完全移除,MQ成为Linux Block layer的默认选项。下面基于Linux-5.6.0内核介绍blk-mq代码和关键数据结构。
request和tag分配
blk-mq中,request和tag是绑定的。首先,我们来看下两个与tag分配有关的重要数据结构--blk_mq_tags和blk_mq_tag_set。
与SQ框架一样,MQ框架中使用request结构体来描述IO请求;不同的是,SQ使用内存池来分配request结构体(参见__get_request),在request往驱动派发时分配tag(参见blk_queue_start_tag),MQ中request和tag分配是绑定在一起的(参见blk_mq_get_request), 具体表现为:
blk_mq_alloc_tag_set: 为一个或者多个请求队列分配tag和request集合(tag set可以是多个request queue共享的,例如UFS设备,一个host controller只有一个tag set,但器件可能划分成多个LU--Logical Unit,每个LU有单独的request queue, 这些不同的request queue共享一个tag set),主要流程如下:
图7. scsi-mq驱动初始化时tag set分配流程
blk_mq_get_request: 为bio分配request。MQ中request占用的内存在块设备驱动初始化时分配完成(tags->static_rqs), tag作为数组的索引获取对应的request,因此MQ中分配request即分配tag(使用sbitmap标记对应tag的是否已被使用)。该函数的主要流程如下:
图8. blk-mq bio提交时request分配流程
request_queue初始化
基于blk-mq的块设备驱动初始化时,通过调用blk_mq_init_queue初始化IO请求队列(request_queue)。例如,scsi-mq驱动中,每次添加scsi设备(scsi_device)时都会调用blk_mq_init_queue接口来初始化scsi设备的请求队列。 blk_mq_init_queue:初始化IO请求队列--request_queue。函数的主要流程如下:
1.设置队列的mq_ops(q->mq_ops)为set->ops (例如scsi对应的实现是scsi_mq_ops)
2.设置request超时时间,初始化timeout_work(处理函数是blk_mq_timeout_work)
3.设置队列的make_request回调为blk_mq_make_request (bio的提交时会用到)
4.分配和初始化percpu软件队列(ctx)
5.关联request_queue和块设备的tag set
6.更新软件队列(ctx)到硬件派发队列(hctx)的映射关系(map: ctx->hctx)
图9. scsi-mq驱动创建scsi device时初始化requst_queue流程
IO的提交(submit)
blk-mq中,通过调用blk_mq_make_request将上层提交的bio封装成request并提交到块设备层,它的主要流程如下:
图10. blk-mq中IO提交流程
1.如果是fua/flush请求,则将request插入到flush队列,并调用blk_mq_run_hw_queue 启动请求派发
2.如果当前线程正在做IO plug且块设备是硬件单队列的(nr_hw_queues=1),则将request插入到当前线程的plug list
3.如果配置了调度器,则调用blk_mq_sched_insert_request将请求插入调度器队列(如果没有实现insert_requests接口,则插入到当前cpu的软件队列中)
4.如果是硬件多队列块设备上的同步IO请求,则调用blk_mq_try_issue_directly尝试将request直接派发到块设备驱动
5.其他情况,则调用blk_mq_sched_insert_request插入request(同case 3)
IO的派发(dispatch)
blk-mq中通过调用blk_mq_run_hw_queue派发IO请求到块设备驱动,MQ框架中存在很多的点会触发IO请求往块设备驱动派发,主要如下:
blk_mq_run_hw_queue: 启动硬件队列派发IO请求,可以是同步/异步的执行的。如果队列不在静默状态(quiesced)且有IO请求pending,则启动派发:
图11. blk-mq启动硬件队列派发IO请求的流程
无论是同步还是异步的派发模式,最终都会调用__blk_mq_run_hw_queue派发IO请求,这个函数先检查执行的上下文,然后调用blk_mq_sched_dispatch_requests派发IO请求到块设备驱动,这个函数的主要流程如下:
图12. blk-mq派发IO请求的流程
上述4种情况都会调用blk_mq_dispatch_rq_list 将IO请求派发到块设备驱动,这个函数使用块设备驱动实现的几个接口完成派发逻辑:
IO的完成(complete)
下面以UFS+scsi-mq驱动为例,讲解IO完成处理的过程,主要流程如图13所示:
图13. ufs+scsi-mq驱动中一个IO的完成流程
1.对于硬件单队列的块设备,调用__blk_complete_request处理。如果发起IO请求的cpu就是当前cpu或者和当前cpu共享缓存,则发起当前cpu上的block软中断,在block软中断中继续request完成处理流程
2.对于硬件单队列的块设备,如果不满足case 1的条件,则通过IPI(inter-processor interrupt)发起其他cpu上的block软中断,在block软中断继续request完成处理流程
3.对于硬件多队列设备,如果当前cpu与发起IO请求的cpu不共享缓存(且不是高优先级的IO请求),则调用__blk_mq_complete_request_remote发起远端cpu上的request完成处理流程(IPI)
4.对于硬件多队列设备,非上述情况,直接在当前cpu上(硬件中断上下文)继续request完成处理流程
四、多队列IO调度器
事实上,在blk-mq框架一开始是不支持IO调度器的(Linux-3.13)。由于高速存储器件IO特征是高IOPS,低延迟,我们希望IO的软件开销尽可能低,而IO调度会增加软件开销,所以专门针对这类器件设计的blk-mq在一开始并没有加入IO调度的能力。
当时的Linux块设备层是SQ和MQ两套框架共存的(SQ用于HDD这样的慢速块设备驱动,MQ用于nvme这样的高速块设备驱动)。Linux Block Layer的发展趋势是希望能够使用一套框架同时满足慢速器件和高速器件的需求,所以blk-mq引入后,Linux上的块设备驱动程序开始往MQ框架迁移,在Linux-5.0上,所有基于SQ的块设备驱动都完成了向MQ框架的转化,Block Layer的SQ框架和相关IO调度器被完全移除。
我们知道对于慢速器件(特别是旋转磁盘,随机IO性能很差)来讲,IO调度是十分重要的,同时一些高速器件(特别是硬件单队列的器件,如emmc,ufs)也有IO调度的需求。
因此在Linux-4.11上,Jens Axboe在MQ框架上增加了IO调度的能力,同SQ框架一样,MQ中的IO调度器也是插件化的,框架提供一系列的接口,由具体的IO调度算法(如mq-deadline)实现这些接口:
目前基于blk-mq实现的IO调度器主要有下面几个:
五、结语
本文主要介绍了blk-mq框架,基于这个框架,我们能够实现下面几件事情:
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。