专栏名称: 企业存储技术
企业存储、服务器、SSD、灾备等领域技术分享,交流 | @唐僧_huangliang (新浪微博 )
目录
相关文章推荐
哎咆科技  ·  疯了吧,iPhone 16 Pro ... ·  昨天  
ZOL中关村在线  ·  AI风起云涌,OPPO勇立潮头 ·  昨天  
EETOP  ·  芯片精品课打折倒计时! ·  5 天前  
ZOL中关村在线  ·  iPhone 16销量堪忧,二手贩子狂喜? ·  6 天前  
51好读  ›  专栏  ›  企业存储技术

探索与解决:Intel E810网卡的4ms单并发IO延迟问题

企业存储技术  · 公众号  · 硬件  · 2024-09-28 17:27

正文

注:本文内容引用自张洋老师的知乎文章 https://zhuanlan.zhihu.com/p/735757082,他是一位存储研发专家。

问题现象和背景

近期,zStorage分布式块存储系统在海光+麒麟+E810网卡环境下,使用FIO工具测试4K单并发随机读/写IO时,延迟达到4ms。而这里唯一的变量是E810网卡;如果采用Mellanox网卡,在同样的测试用例下,IO延迟约为100us左右。那么问题出在网卡吗?还是另有原因?以下是分析和探索的过程分享。

问题定界

要分析上述高时延问题,首先需要对问题进行定界:是zStorage存储软件的问题,还是Host端的问题?针对这一问题,我们做了以下几件事情:

  • - 时延分析:zStorage FrontEnd从收到IO到应答IO给Host,耗时 < 100us,符合预期。这个实验表明问题大概率不在存储端,但仍不能完全断定问题在Host端。


  • - 更换HOST:重新使用一个内核版本为5.10的系统,进行相同的测试用例,时延恢复正常。这个结果至少说明,更换内核可以解决问题,问题大概率与内核有关。


  • - Ftrace跟踪分析:在出问题的HOST上开启Ftrace,跟踪nvmf和rdma相关函数。发现4ms的时延确实出现在Host端的处理上。如下图所示:在58225.458457这个时间点,Host的IB驱动已经收到了存储节点的ACK应答,但直到58225.462423这个时间点才调用nvme_rdma_send_done。这个实验表明,确实是Host端的内核存在一个4ms的延迟。

4ms延迟流程深究

根据Ftrace的信息,可以看到在4ms后,由smp_apic_timer_interrupt触发,完成了消息的发送。

在 Linux 内核中,smp_apic_timer_interrupt 是处理APIC(Advanced Programmable Interrupt Controller)定时器中断的中断处理程序。当该中断触发时,它可以调用定时器相关的处理程序,通常与调度器、进程切换、软中断等内核机制相关。APIC 定时器是每个 CPU 的本地定时器,用于周期性地触发中断,从而执行某些周期性的任务。

具体来说,这个APIC定时器的频率较低,通常在1000Hz以下,而当前出问题的Host为250Hz,因此每4ms调度一次,这与IO延迟4ms是相吻合的。然而,这个频率是在内核编译时确定的,修改起来并不容易,且直觉上问题不太可能出在这里。毕竟,为了解决这个问题,不可能将频率改为100万Hz。那么,为什么IO会在smp_apic_timer_interrupt的调度流程中完成呢?IO真正的完成应该是在什么流程中呢?

继续探究IO未及时处理的原因

继续使用Ftrace跟踪更多详细的信息。

ib_cq_completion_softirq的下一个函数调用是__raise_softirq_irqoff。翻阅内核源码后,发现irq_poll_sched这个函数至关重要。它负责调度软中断处理,并与IO完成的路径密切相关。进一步分析irq_poll_sched的调用时机和作用,可能揭示出为何IO在软中断处理链中被延迟触发。

这意味着,irq_poll_sched函数并不希望在当前流程中立即处理I/O,而是将当前I/O加入到CPU的延迟任务处理队列中,等待延迟处理。然而,实际情况是处理延迟了4ms,这个延迟确实过长了。注意这一行代码:__raise_softirq_irqoff(IRQ_POLL_SOFTIRQ);__raise_softirq_irqoff() 触发了指定类型的软中断,这里是IRQ_POLL_SOFTIRQ,用于调度一个软中断处理函数来处理加入轮询队列的I/O任务。

接下来,进一步查看内核源码,以分析IRQ_POLL_SOFTIRQ如何调度以及为什么延迟长达4ms?

IRQ_POLL_SOFTIRQ这个软中断是与irq_poll_softirq函数绑定在一起的。这意味着,一旦使用__raise_softirq_irqoff触发了软中断,应该在短时间内调用irq_poll_softirq,以处理刚才的I/O完成。然而,在实际情况中,I/O处理延迟了4ms,这表明在软中断的调度和处理之间存在瓶颈或延迟。

对IO处理流程稍作总结

ROCE网卡的中断处理流程已经梳理清楚:

  • irdma 发送数据到存储节点,使用 RDMA 协议传递数据。


  • - 存储节点的网卡收到数据后,在大约 10 微秒内返回 ACK,表明数据接收完成。


  • irdma 通过网卡中断收到 ACK 后,开始处理当前的 CQE。它将 CQE 传递给 CPU 的 irq_poll 机制,并通过 __raise_softirq_irqoff(IRQ_POLL_SOFTIRQ) 触发另外一个软中断。


  • - 这个时候,irq_poll 的软中断机制应该被立即处理,快速响应以完成 CQE 处理。


  • - 实际上,软中断并未在触发后立即被处理,而是等到 4 毫秒后由 smp_apic_timer_interrupt 触发。这导致了预期外的延迟。

__raise_softirq_irqoff为什么未及时触发处理软中断?

经过一番查找,终于找到了答案:https://github.com/torvalds/linux/commit/4133b013faf31fbab61d4deb626fcb4390042eba

这段描述解释了为何在特定场景中,需要使用raise_softirq_irqoff()而不是__raise_softirq_irqoff()来触发软中断,特别是在非中断上下文中(如工作队列或内核线程中的软中断调度)。

简单来说,某些场景下__raise_softirq_irqoff是不生效的。而raise_softirq_irqoff函数是对__raise_softirq_irqoff的封装,如果当前不在中断上下文,则会调用一个wakeup_softirqd函数,唤醒ksoftirqd进程以立即处理软中断。

结论

至此,问题原因已经很清晰了,就是将__raise_softirq_irqoff改成raise_softirq_irqoff即可,删除两个下划线。然而,在不修改内核驱动的情况下,应该如何解决这个问题呢?毕竟在同样的HOST上,Mellanox卡没有出现问题。

尝试修改irdma驱动源代码

IRDMA:这是Intel特定的RDMA驱动,专门处理支持IRDMA的Intel网卡,如E810。它处理RDMA连接的管理、数据传输的加速,并与IBCORE模块协作完成数据的高效传输。

实际上还是有一些思路可行,例如:

  • - 可否在irdma驱动中增加一行代码,使用不带下划线的raise_softirq_irqoff?编译驱动时却报错:WARNING: "raise_softirq" [/root/irdma-1.15.11/src/irdma/irdma.ko] undefined! 未再继续深究。


  • - 使用Tasklet来触发延迟任务。 Tasklet 是一种基于 SoftIRQ 的延迟执行任务机制,专门为简单、短时间内完成的任务设计。它本质上是一个简化的 SoftIRQ,开发者可以通过 tasklet 将不紧急的工作推迟到稍后执行。TASKLET_SOFTIRQ 是 Linux 内核中的软中断(SoftIRQ)机制之一,专门用于延迟执行轻量级任务的框架。它通过一种称为tasklet的机制来处理可延迟执行的任务,适用于需要在较短时间内完成的工作,而不需要立即执行,并且不需要中断整个系统调度。
    经过测试,该方法有效,时延为130us,解决了4ms延迟的问题。

  • - 可否在irdma驱动中增加wakeup_softirqd,以触发软中断处理?——未尝试。


  • - 其他实验中,导致了内核崩溃,或者RDMA连接不上等问题。——未采用。

作者

“云和恩墨 zStorage 分布式存储团队” 张洋

参与这个问题的是一个攻关小组,其中大部分思路由团队中的一位RDMA高手(zzy)提出并实验。


扩展阅读:《企业存储技术》文章分类索引更新(微信公众号合集标签)


:本文只代表作者个人观点,与任何组织机构无关,如有错误和不足之处欢迎在留言中批评指正。进一步交流,可以加我的微信:490834312。如果您想在这个公众号上分享自己的技术干货,也欢迎联系我:)


感谢您的阅读和支持!《企业存储技术》微信公众号:HL_Storage

长按二维码可直接识别关注


历史文章汇总http://www.toutiao.com/c/user/5821930387/

http://www.zhihu.com/column/huangliang